Immigration — Work / Visit Pass Applications (Singapore MOM)
1. Document Control
| Document Title | Singapore MOM Work / Visit Pass Application Automation |
|---|---|
| Document ID | SOP-IMM-001 |
| Version | 1.0 (Draft for Automation Build) |
| Effective Date | [Insert Date] |
| Review Date | [Insert Date + 12 months] |
| Document Owner | Head of Immigration |
| Approver | Managing Director |
| Status | Draft |
Distribution
| Role Title | Access Rights |
|---|---|
| IMM Operator | Edit (intake, review, submit gate) |
| Platform Admin | Edit (incl. threshold config) |
| Client Submitter | Portal form + document upload only |
| Applicant | Portal form + document upload only |
2. Purpose and Scope
This SOP covers the AI-assisted preparation of a Singapore work / visit pass application: an IMM Operator initiates an application for an employer entity + applicant party, the applicant completes a portal form and uploads documents, the applicant is screened (KYC), eligibility is evaluated against the per-pass-type SG rules, an assisted Ministry of Manpower (MOM) submission pack is assembled, and — after a mandatory human gate — the operator files in EP Online / WPOL and records the acknowledgement. A pass-renewal deadline is then tracked.
The platform does not auto-file with MOM. Submission to the authority is always human-performed (FR-IMM-007); the agent produces a transcribable pack and records the real acknowledgement the operator obtains.
The workflow is IMM.PREPARE_APPLICATION (one AgentRun per application). See the run lifecycle for the full state machine.
3. Pass Types
The six SG pass types the platform recognises (admin-configurable thresholds, dedicated form definitions where bespoke):
| Pass type | Form definition id | Notes |
|---|---|---|
EMPLOYMENT_PASS | imm.application.employment_pass.v1 | EP Online. Salary + qualification + contract. |
S_PASS | imm.application.s_pass.v1 | WPOL. Salary + skills certificate + contract. |
DEPENDANT_PASS | imm.application.dependant_pass.v1 | EP Online. Sponsor pass + relationship proof. |
PERSONALISED_EMPLOYMENT_PASS | imm.application.generic.v1 | Generic form; threshold configurable. |
ONE_PASS | imm.application.generic.v1 | Overseas Networks & Expertise Pass; generic form. |
SOCIAL_VISIT_PASS | imm.application.generic.v1 | Long-term visit pass; threshold typically 0. |
Pass types without a bespoke form definition fall back to the generic definition (immFormDefinition in packages/agent-runtime/src/modules/imm-form-defs.ts): the common identity fields + a passport bio-data page.
4. Required Documents per Pass Type
Authored as data in packages/agent-runtime/src/modules/imm-form-defs.ts. Each required-doc slot has a stable key (the portal + completeness check address it by) and maps to a lean KycDocType so uploaded files persist as KycDocument rows (no schema migration).
Common fields (every pass type): full name (passport), pass type (prefilled, locked), employer (prefilled, locked), passport number, nationality, date of birth.
| Pass type | Extra form fields | Required documents (slot key → KycDocType) |
|---|---|---|
EMPLOYMENT_PASS | monthly salary (prefilled), job title, highest qual. | passport_bio_page → ID; educational_certificate → OTHER; employment_contract → OTHER |
S_PASS | monthly salary (prefilled), job title | passport_bio_page → ID; educational_certificate → OTHER; employment_contract → OTHER |
DEPENDANT_PASS | sponsor's pass number, relationship to sponsor | passport_bio_page → ID; proof_of_relationship → OTHER; sponsor_proof_of_address → PROOF_OF_ADDRESS |
| generic fallback | — | passport_bio_page → ID |
The portal blocks submit until every required-doc slot has a file. Slot keys are carried on KycDocument.verificationStatus as UPLOADED:<slotKey>.
5. Eligibility Rules and Threshold Config
5.1 The SG IMM rule pack
packages/rules/src/packs/sg-imm.ts (SG_IMM_PACK, version 0.1.0) — four BLOCK rules evaluated at the evalEligibility step. A failure of any rule throws ImmEligibilityBlockedError and the run goes FAILED.
| Rule id | Check | Blocks when |
|---|---|---|
SG.IMM.SALARY_THRESHOLD | salary_meets_threshold | applicant monthly salary < the per-pass-type threshold (SGD) |
SG.IMM.DOCUMENTS_PRESENT | required_documents_present | any required-doc slot is missing |
SG.IMM.SCREENING_CLEARED | screening_cleared | screening outcome is CONFIRMED_MATCH |
SG.IMM.EMPLOYER_ELIGIBLE | employer_eligible | the employer entity is not LIVE |
5.2 Per-pass-type salary thresholds (platform config)
Thresholds are PLATFORM settings, not tenant data. They live on the global, non-tenant-scoped Jurisdiction.config.immThresholds JSON (key = pass type, value = monthly SGD). At eval time the IMM workflow reads immThresholds[passType] for the employer's jurisdiction and injects it onto a per-run copy of the pack's minMonthlySalarySgd (the shared SG_IMM_PACK constant is never mutated). Fallback when no value is configured: 5000 SGD (DEFAULT_IMM_SALARY_SGD).
Who edits them: PLATFORM_ADMIN only, at /dashboard/jurisdictions.
API:
GET /admin/jurisdictions— list jurisdictions.GET /admin/jurisdictions/:id— detail incl. currentimmThresholds.PATCH /admin/jurisdictions/:id/config— merge-updateimmThresholds(validates: each key is one of the six known pass types, each value a non-negative finite number; rejects the whole patch on the first offence). Writes an audit eventjurisdiction.imm_thresholds.setunder Tenant 0.
Representative SG figures (seed/doc reference only — exact values are admin-configured): EP 5600, S Pass 3150, PEP 22500, ONE Pass 30000, DP 6000, Social Visit 0 (REPRESENTATIVE_IMM_THRESHOLDS_SGD).
6. The Human Gate (FR-IMM-007)
Submission to MOM is a tier-4 proposed action (IMM.SUBMIT_APPLICATION) pinned to a mandatory human gate. The submit workflow step never files — it routes the run to AWAITING_REVIEW in the shared review inbox.
The IMM Operator:
- Opens the application detail (
/dashboard/imm/applications/[id]), reviews eligibility, documents, and the assembled MOM pack. - Files the application manually in EP Online / WPOL, transcribing from the pack's
mappedFields+ artifact. - Approves the gate via
POST /ops/review-inbox/:reviewTaskId/approvewithapplyInput.filing.acknowledgementNumber(optionalfiledAt,reference).
The apply executor (imm-apply.ts, the only writer) then records the FilingTransaction(MOM, PASS_APPLICATION, ACKNOWLEDGED), persists the pack as a Document(IMM_APPLICATION), upserts a StatutoryDeadline(PASS_RENEWAL), emits FILING_OUTCOME, and closes the run. It is idempotent — a retry that finds the filing already written is a no-op.
Permissions: IMM intake, review, and the submission gate are restricted to IMM_OPERATOR + PLATFORM_ADMIN (operatorRolesForModule('IMM')). The IMM.SUBMIT_APPLICATION permission is ENTITY-scoped.
7. Renewal Tracking (FR-IMM-008 / Workstream 5)
When a filing is acknowledged, a StatutoryDeadline(PASS_RENEWAL) is created (default filedAt + 24 months, or the operator-supplied renewal date).
The daily deadline-scheduler worker calls sweepPassRenewals (packages/db/src/deadlines.ts) per tenant. It re-derives each PASS_RENEWAL deadline's status from its due date against a 60-day lead time:
UPCOMING→ more than 60 days out (riskLOW);DUE_SOON→ within 60 days (riskMEDIUM);OVERDUE→ past due (riskHIGH).
The status is written only when it actually changes (idempotent), and a DEADLINE_STATE event is emitted on every real transition. On the first crossing into DUE_SOON (the UPCOMING → DUE_SOON edge only — repeated sweeps never re-alert), one Notification of type PASS_RENEWAL_DEADLINE_APPROACHING is created per active IMM_OPERATOR / PLATFORM_ADMIN, linking to /dashboard/imm?entityId=<entityId>. Renewal itself is re-initiated manually — the sweep never auto-creates a run.
8. End-to-End Flow Summary
| Step | Actor | Action | System effect |
|---|---|---|---|
| 1 | IMM Operator | Start application (/dashboard/imm) | IntakeRequest + AgentRun (IMM.PREPARE_APPLICATION) queued |
| 2 | System | classify → collectApplicationForm (FORM, pauses) | FormInstance + magic link; run AWAITING_CLIENT |
| 3 | Applicant | Open /portal/imm/:token, fill form, upload docs, submit | KycDocument rows; FormInstance SUBMITTED; resume enqueued |
| 4 | System | collectDocuments → screen → evalEligibility | KycCase + ScreeningResult; BLOCK ⇒ FAILED |
| 5 | System | assembleApplication → submit | MOM pack assembled; tier-4 action proposed; run AWAITING_REVIEW |
| 6 | IMM Operator | File in EP Online / WPOL; approve gate with acknowledgement | FilingTransaction + Document + StatutoryDeadline; CLOSED |
| 7 | System (daily) | sweepPassRenewals | PASS_RENEWAL status transitions + one-time DUE_SOON notify |
9. Related
- Run lifecycle (status machine)
- Userflows:
docs/userflows/immigration/ - CLAUDE.md —
## Project(Immigration product summary)