Skip to content
HRTEQDocs
Documentation API

DocsRecruitment

Stage gates

The compliance engine: the five requirement types and exactly what satisfies each, blocking versus advisory, the order the checks run in, and how an override is recorded.

This is the part of HRTEQ that makes it a compliance system rather than a CRM with stages. A stage carries requirements, and those requirements are checked when an application tries to enter it. If a blocking requirement is unmet, the move does not happen.

Requirements are entry conditions on the target stage. The gate evaluates the requirements of the stage you are moving into, never the one you are leaving. “Visa Processing requires a verified passport” means you cannot *enter* Visa Processing without one. Reading it the other way round makes the whole configuration look wrong.

The five requirement types#

Every requirement is one of these. `refCode` points at what it checks.
TyperefCodeSatisfied when
DOCUMENT_TYPEA document type code, e.g. PASSPORTA document of that type exists and is VERIFIED — and, if the type tracks expiry, has an expiry date that is still in the future.
CHECKLIST_ITEMA checklist code, e.g. CONTRACT_SIGNEDThe application’s checklist item for that code is marked done.
ROLE_SIGNOFFA staff role, e.g. DOCUMENT_OFFICERThe corresponding SIGNOFF_<ROLE> checklist item is done. This is how a handoff between officers is made explicit.
FIELD_PRESENTA dotted field path, e.g. applicant.mobileThat field on the applicant or the application is not blank.
PAYMENT_CLEAREDWORKER or EMPLOYERFor WORKER: the balance is settled and Accounts has signed the financial clearance. For EMPLOYER: no charge is UNPAID or PARTIAL.

Document requirements in detail#

A document requirement is the strictest of the five, and the one most likely to surprise. Uploading is not enough, and neither is uploading and having it on file.

  • Nothing uploaded → “Not uploaded yet.”
  • Uploaded but still PENDING or SUBMITTED“Uploaded but not yet verified by the Document Officer.”
  • Rejected → “Rejected: ” followed by the recorded rejection reason.
  • Expired → “On file but expired.”
  • Verified, the type tracks expiry, but no expiry date was captured → “Verified but the expiry date is missing.”
  • Verified and past its expiry date → “Expired on ” followed by the date.

The gate looks in both document pools — the applicant’s own documents and the application’s — so a single requirement list can reference a passport and a visa without caring which object holds which.

This is why expiry tracking is not cosmetic. A verified medical result that lapsed last week stops satisfying its requirement the moment it lapses. Nobody has to notice. The nightly sweep also flips lapsed documents to EXPIRED, so the reason shown to the officer is accurate either way.

Payment clearance in detail#

For the worker side, a zero balance is necessary but not sufficient. Accounts must also have signed off, recorded as financialClearedAt. That produces two distinct messages — “Outstanding worker balance of 4500.00” and “Balance is settled but Accounts has not signed the financial clearance” — which are two different problems for two different people.

Waived charges are excluded from the billed total. Employer-side clearance is simpler: it counts charges still UNPAID or PARTIAL.

Blocking versus advisory#

Each requirement has a blocking flag. Blocking requirements stop the move. Advisory requirements are evaluated and reported but do not stop anything — they are the ones you want visible without turning them into a wall.

A gate result reports both sets separately: unmetBlocking and unmetAdvisory. The move is allowed when unmetBlocking is empty, which is to say advisory items never affect the decision.

The order the checks run#

A stage transition is a single code path, and it enforces four things in this order. Knowing the order tells you which error you will see first.

  1. Module write permission

    Can this actor write applications at all? A Liaison Officer cannot, so nothing else is evaluated.

  2. The target stage’s owning role

    Only the role owning the target stage — or an Owner or System Administrator — may move an application into it. Terminal stages skip this check entirely.

  3. The entry-requirement gate

    Every requirement on the target stage is evaluated. Terminal stages are never gated. A blocked move returns 409 with code GATE_BLOCKED and the full gate attached.

  4. An override reason, if overriding

    Only an Owner or System Administrator gets this far past a blocked gate, and only with a written reason of at least ten characters.

409 GATE_BLOCKED
{
  "ok": false,
  "code": "GATE_BLOCKED",
  "error": "Visa Processing has 2 unmet requirement(s). Ask an Owner or System Administrator if this genuinely needs an override.",
  "gate": {
    "targetStageCode": "VISA_PROCESSING",
    "targetStageName": "Visa Processing",
    "owningRole": "LIAISON_OFFICER",
    "allowed": false,
    "unmetBlocking": [
      {
        "type": "DOCUMENT_TYPE",
        "label": "NBI clearance verified",
        "refCode": "NBI",
        "blocking": true,
        "satisfied": false,
        "detail": "Expired on 2026-04-30."
      },
      {
        "type": "ROLE_SIGNOFF",
        "label": "Document Officer compliance sign-off",
        "refCode": "DOCUMENT_OFFICER",
        "blocking": true,
        "satisfied": false,
        "detail": "Awaiting sign-off from the document officer."
      }
    ],
    "unmetAdvisory": []
  }
}

Overrides#

An override is a recorded exception, not a bypass. Four things happen:

  1. The reason must be at least ten characters after trimming. A blank or terse reason is refused, with the message stating that the reason is recorded.
  2. The reason is stored on the stage-history row.
  3. The full set of unmet blocking requirements is snapshotted onto that row — label, type, refCode and the detail string — as it was at that moment. Fixing the document later does not rewrite history.
  4. The audit action is application.stage_overridden, not application.stage_advanced, so overrides are separable and countable.
Overrides are the metric a DMW inspection will care about. The point of storing the unmet snapshot is to be able to answer, months later, exactly what was missing when someone decided to proceed anyway and who decided it. Use overrides sparingly and write reasons a stranger can evaluate.

Automatic advancement#

After any authorised action that changes a gate fact, the server checks the immediate next stage. If every requirement on it is satisfied — not just the blocking ones — the application advances automatically.

The constraints on automatic progression are deliberately tight:

  • One stage only, and only the immediate next active, non-terminal stage.
  • Never into a terminal stage.
  • Never through an unsatisfied requirement, blocking or advisory.
  • Never for a stage with no configured requirements — an unconfigured stage must not become a hole the process falls through.
  • Only for applications whose status is IN_PROGRESS.

In day-to-day use this is what makes the board feel alive: a Document Officer verifies a medical result, and the application moves to the next stage and lands in the next officer’s queue without a handoff message.

Terminal stages are never gated#

Withdrawals, rejections, failed medicals and visa denials must always be recordable. Gating them would mean an application that cannot be closed, which is worse than one closed early. So terminal stages skip both the ownership check and the gate, and are reachable from any stage.

Configuring your own gates#

Stages and their requirements are per-organization rows, seeded with a DMW-aligned default set and intended to be edited. When you change them, three rules will save you trouble:

  • Put a requirement on the stage where the evidence *arrives*, not where it is *used*. The medical result belongs on the entry to Document Processing, because that is the moment it must exist.
  • Use blocking: false for anything you want visible but would routinely override. A requirement you override every week should not be blocking.
  • Use ROLE_SIGNOFF at each genuine handoff. It is the difference between an officer having finished and an officer having stopped.

The full seeded tree, with every stage’s requirements listed, is in the Stage reference.

Was this page helpful?