---
title: "Criminal Background Translation"
slug: criminal-background-translation
section: Documents & Identity
status: stable
description: "The settled specification for the Criminal Background Clearance workflow step: one applicant document requirement whose logical document record can carry multiple linked artifacts — the applicant's original upload, an AI-generated Englis…"
last-updated: 2026-10-07
---

# Criminal Background Translation

The settled specification for the Criminal Background Clearance workflow step: one applicant document requirement whose logical document record can carry multiple linked artifacts — the applicant's original upload, an AI-generated English translation, and any later manual or certified translation. The translation is a supporting child artifact of the original, never a second applicant requirement or a second workflow step.

## Overview & Core Principle

The applicant sees exactly one required step: upload your Criminal Background Clearance. They upload the original once. When the original is not in English and its language is in the supported set, Globus generates an English translation underneath it; when the language is unsupported, the same step asks the applicant to upload an English translation, stored underneath the original the same way.

> **One applicant requirement, one document record, multiple linked files underneath it.**
>
> The step still collects a single document type — Criminal Background Check — but inside Globus that one document record can contain the original file, an English translation child artifact (AI-generated for supported languages, applicant-supplied for unsupported ones), and a staff manual or certified translation when the active translation is not good enough.

Two completion moments are deliberately separate: **applicant submission complete** (the original was uploaded and passed basic validation) and **document verified** (staff has reviewed and approved the full package, including the English translation where one was required). The applicant has done their part after uploading; Globus does not mark the document verified until review completes.

## Parent–Child Document Model

```
Workflow Step
└── Document Requirement
    └── Document Record
        ├── Original Artifact
        ├── AI English Translation Artifact
        └── Optional Manual/Certified Translation Artifact
```

### Terminology

| Term | Meaning |
| --- | --- |
| Document type | The business meaning of the document — criminal_background_check. |
| Document record | One logical criminal background submission belonging to an applicant. |
| Document artifact | An individual file on the record. Roles: original, ai_translation, manual_translation, certified_translation. |

The original and translation are two artifacts on the same logical document record — not two unrelated documents. The generated translation inherits the parent document type and requirement; it never creates another requirement.

### Data Model

Three tables carry the model. Statuses listed here are **document-package statuses** — they never leak into workflow-step status (see Step Status Integration).

| Table | Key fields | Status vocabulary |
| --- | --- | --- |
| document_package_requirements | application_id, workflow_step_instance_id, field_key, document_type_id, satisfied_by_record_id | not_submitted, processing, pending_review, verified, rejected, replacement_requested, waived |
| document_package_records | requirement_id, current_original_artifact_id, current_translation_artifact_id, detected_language, translation_required, processing_status, review_status | processing: not_started … completed, failed, manual_intervention_required; review: not_ready, pending_review, verified, rejected, replacement_requested |
| document_package_artifacts | record_id, artifact_role, parent_artifact_id, language_code, version_number, generated_by, supersedes_artifact_id, is_current, checksum | pending, accepted, rejected, superseded, translation_inaccurate, manual_review_required (via artifact_reviews) |

The translation must point to the exact original it was produced from: `translation.parent_artifact_id = original.id`. This is essential because the applicant may later upload a replacement original.

### Versioning & Immutability

Document artifacts are immutable after creation. When the applicant uploads a replacement: create a new original artifact, mark the previous original no longer current, preserve the previous original and translation for audit, re-run detection and translation, and link the new translation to the new original. Nothing is overwritten or deleted; prior versions remain visible in document history but are excluded from active review unless a reviewer selects them.

When the applicant withdraws (deletes) a not-yet-approved CBC upload from the portal, the active package record is retired (`isCurrent = false`, requirement returned to not_submitted, an `artifact_superseded` audit event with reason `portal_withdrawal`) but its artifacts, text extractions and stored bytes are preserved as evidence; only the mutable applicant-document row is removed, and the applicant loses access. The retire step matches on the original artifact's storage path, so a stale concurrent delete cannot detach a newer replacement that reused the same document row — it returns a DOCUMENT_WITHDRAWAL_STALE conflict instead. Approved documents cannot be deleted or replaced from the portal: withdrawing an approved (or legacy verified) document returns 409 `DOCUMENT_NOT_DELETABLE`, a portal upload over an existing approved document of the same type returns 409 `DOCUMENT_ALREADY_APPROVED`, and a signed-agreement artifact cannot be withdrawn in any state (409 `SIGNED_AGREEMENT_NOT_DELETABLE`).

Duplicate-upload prevention while processing must have an escape hatch: re-upload is temporarily disabled during normal processing, but becomes available when processing exceeds a configured timeout, fails permanently, or staff requests a replacement. Idempotency protection prevents double-click duplicates; there is no indefinite lock. In the Applicant Portal (PPPToo) the upload field is read-only while a current record is actively processing and unlocks on a terminal processing state (completed, failed, manual_intervention_required, awaiting_applicant_translation), when the requirement status is replacement_requested, or when the processing timeout elapses (default 10 minutes, overridable via VITE_CBC_PROCESSING_TIMEOUT_MS). A missing or unparsable record timestamp, or one more than 5 minutes ahead of the client clock, fails open (unlocked) so corrupt data can never strand the applicant. Identical in-flight uploads for the same field are coalesced into a single request.

## Step Library Configuration

The Advanced File Upload field configuration gains a Document Processing section, frozen into the published step version and copied into the workflow instance snapshot:

```json
{
  "documentTypeKey": "criminal_background_check",
  "documentProcessing": {
    "languageDetectionEnabled": true,
    "requiredLanguage": "en",
    "translateWhenLanguageDiffers": true,
    "translationMethod": "ai",
    "saveAsChildArtifact": true,
    "generatePdf": true,
    "reviewRequired": true,
    "translationFailureAction": "manual_review"
  }
}
```

## Step Status Integration

The workflow step uses only the canonical step-status enum — not_started, in_progress, submitted, approved, rejected, completed. No parallel step-status vocabulary is introduced.

| Event | Step status |
| --- | --- |
| Applicant uploads the original (passes basic validation) | submitted |
| Reviewer approves the document package | approved |
| Workflow engine confirms all completion conditions | completed |

Approval and completion may resolve in the same transaction but remain separate concepts. Richer states (processing, translation_required, pending_review, verified, replacement_requested) belong to the document package, never to the step.

## Upload API — Adapter, Not Replacement

The Applicant Portal's existing endpoint POST /api/upload-criminal-background (flat response body) **remains operational**. Its internals are repointed at the new document-package service: it creates/resolves the requirement, creates the document record, stores the file as the original artifact, starts the pipeline, and returns the existing response fields (optionally adding non-breaking fields).

Migration to the generic artifact endpoint (POST /api/applications/:applicationId/document-requirements/:requirementId/artifacts) is a controlled API migration requiring a Globus API contract ticket, an Applicant Portal consumer ticket, contract tests, a deprecation period, and removal only after usage reaches zero. This guards against the documented phantom-endpoint failure mode where a portal called a never-existing nested route and every step save 404'd.

The form-engine bundle's generated contract also declares `POST /api/criminal-background/extract-date` and `POST /api/criminal-background/translate`. Globus deliberately registers neither: the contract map (`server/contracts/formEngineUploadContractMap.ts`) records both as `host-delegated`, because the bundle routes date extraction and translation through host-provided callbacks and never calls those paths through its adapter, and a guard test fails CI if either gains a route. The translation itself is the `translateCriminalBackground` service in `server/services/translationSkills.ts`, which is not exposed at the contract path.

CBC processing starts at upload, not at Save & Continue. `POST /api/portal/applications/:appId/documents` hands a `police-clearance` upload to the package pipeline as soon as the applicant-document row is persisted (optional additive `stepKey` request field; response shape unchanged). The handoff is best-effort: an ingestion error never fails the upload response — instead one deduplicated operational incident and ticket (`CBC_UPLOAD_INGESTION_HANDOFF_FAILED`) are recorded for that exact document version. The upload slot (workflow definition, step key, field key) is resolved server-side from the application's pinned workflow version and the upload field tagged `metadata.documentType = police-clearance`; the portal's `stepKey` is only a consistency hint, and an ambiguous, missing or mismatched slot is skipped rather than guessed. Step submission remains the reconciliation door and no-ops on the same package via the same-object guard, so there is no duplicate package, record or run.

The portal reads package state from `GET /api/portal/criminal-background/status?applicationId=...`, which returns each requirement's current record (processing and review status, detected language and label, `translationRequired`, `translationFallbackRequired`) with original and current translation artifact refs, each carrying a portal-scoped `downloadUrl` (`GET /api/portal/document-packages/artifacts/:artifactId/download`). Ownership mismatches are non-disclosing 404s. The unsupported-language door is `POST /api/portal/document-packages/:requirementId/applicant-translation` (PDF, JPEG or PNG, max 20 MB), usable only while the record's processing status is `awaiting_applicant_translation`.

Portal-submitted CBC uploads are ingested regardless of storage shape. Both the legacy flat-upload shape and the newer array / document-reference shape resolve correctly. When an applicant submits multiple entries in the array, ingestion resolves the newest underlying upload. (Fixed Aug 11 2026 — previously only the legacy flat shape resolved and newer-shape submissions were silently ignored; the array shape is now fully supported.)

## Processing Pipeline

```
Original uploaded
  → file validation and malware scan
  → determine whether PDF contains usable text
  → extract embedded text OR run OCR (per page for mixed PDFs)
  → detect source language from extracted text
  → English?            yes → straight to review
  → supported language?  yes → translate → validate → generate English PDF
                              → store translation as child artifact
  → unsupported language     → request applicant English translation upload
                              (see Unsupported Language — Applicant English Upload)
  → language undetermined    → route to review queue (BACKGROUND_CHECK_LANGUAGE_UNDETERMINED)
  → send document package for human review
```

The pipeline therefore distinguishes four detection outcomes: **English** (no translation needed), **supported non-English** (Globus translates automatically), **unsupported non-English** (the applicant supplies the English translation), and **language undetermined** (staff review decides). In every branch the compliance outcome is the same invariant: **the package cannot be verified until a reviewable English version exists.**

OCR and translation are separate processes: OCR extracts text from scanned images or image-based PDFs; AI translation converts extracted source-language text to English. Text-based PDFs skip OCR (extraction_method = embedded_text); scans use OCR (extraction_method = ocr); mixed PDFs are processed per page (extraction_method = hybrid). OCR output is stored as structured processing data (document_package_text_extractions), never as an applicant-facing document.

The MVP pipeline uses the approved in-cluster OCR service (GCP Document AI general raw-text endpoint). Capabilities beyond raw text — per-page confidence, orientation correction, handwriting detection, structured blocks — must be explicitly labeled in tickets as Existing OCR capability, New Globus orchestration, New OCR-service capability, or Future enhancement. Do not assume they exist.

### Language Detection — Text-First (Option B)

Language detection runs against the OCR-extracted text, not against the document image. The language reported by the OCR service is used when present; when it reports none (embedded-text PDFs, or scans where OCR is language-silent), detection runs on the extracted text through a dedicated unglossed capability (`language-detection-gcp`, internal GCP translation service, context `general`, no glossary, translation output discarded, no OpenAI fallback). The glossary-backed criminal-background translation that follows always carries an explicit source language code — Cloud Translation rejects glossary requests without one, and `translateCriminalBackground` fails fast with a permanent `TRANSLATION_CONFIG_ERROR` if the code is missing. If the detector cannot determine a language the record routes to manual review, never to English. A detection failure is attributed to the `detecting_language` stage and follows the normal transient-retry classification. The text is needed for translation anyway, it avoids a second vision pass, it uses the approved in-cluster OCR service, and it prevents provider drift. A vision-based fallback is permitted only when OCR returns too little usable text AND the fallback provider is approved for criminal-background PII AND the fallback is explicitly part of the architecture.

> **Single-pipeline rule.** The pre-existing GPT-4o-mini Vision language-detection work (9 document-type pairs) must be amended to exclude criminal background documents, with a cross-reference to the translation-orchestration ticket. Two detection pipelines for the same document type are not permitted.

Multilingual documents: if material content exists in a non-English language, translation_required = true. Do not rely only on the first page — police certificates often carry stamps, annotations, or reverse pages in another language.

### Supported Translation Languages

Automatic English translation is **mandatory** for five source languages. These are a product-governance commitment, owned by this specification — not an assertion about the OCR/translation microservice's internal language-pair list:

| Language | Code | Support level |
| --- | --- | --- |
| Portuguese | pt | Mandatory — automatic translation |
| Polish | pl | Mandatory — automatic translation |
| Swedish | sv | Mandatory — automatic translation |
| Spanish | es | Mandatory — automatic translation |
| Filipino (incl. Tagalog detection) | fil / tl | Mandatory — automatic translation |

Any additional languages the approved in-cluster translation service can handle **may** be enabled as bonus support, but they are optional: the implementation must not gate delivery on them, and product must not promise them to applicants or sponsors. The Private OCR page's "nine currently supported language pairs" line is a description of the current service, not a commitment — the mandatory set above is the only contractual list.

The supported set is held as a central list that the pipeline consults after detection — in the current implementation the `CBC_AUTO_TRANSLATE_LANGUAGES` constant in `shared/models/cbcLanguages.ts` (es, fil, pt, pl, sv), gated on real glossary coverage (`globus-criminal-terms-v2`); `CBC_MANDATORY_LANGUAGES` is used for reporting only, not as a gate. Adding a bonus language is a governed configuration change plus a validation pass; removing a mandatory language requires a specification change here first. Detection maps regional variants to their base code (pt-BR → pt); Filipino accepts both `fil` and `tl` detections.

### Unsupported Language — Applicant English Upload

When detection returns a language outside the supported set, Globus does not fail the submission and does not route it to a dead end. The Applicant Portal renders a **second upload control inside the same Criminal Background Check step**: "Your document appears to be in a language we can't translate automatically. Please upload an English translation of this document."

Behaviour and constraints:

- **Same package, child artifact.** The applicant-supplied English translation is stored as a child artifact on the same document record with `artifact_role = manual_translation`, `generated_by = applicant`, and `parent_artifact_id` pointing at the exact original it translates. It is never a second workflow step, a second document requirement, or a separate document record. The existing `manual_translation` role is reused — the actor (`generated_by`) distinguishes applicant-supplied from staff-uploaded manual translations; no new artifact role is introduced.
- **Original submission stays complete.** Uploading the original still moves the step to `submitted` — the applicant is not penalised for the language of a government-issued document. The document package, however, remains unverifiable until an English version exists: `translation_required = true`, requirement status stays `pending_review`, and the package routes with reason code BACKGROUND_CHECK_TRANSLATION_REQUIRED so Compliance can see it is waiting on the applicant's translation.
- **Replacement supersedes the pair.** If the applicant replaces the original, the previously uploaded English translation is marked superseded along with it (its `parent_artifact_id` no longer points at a current original). Detection re-runs on the new original; the fallback upload control re-appears only if the new original is also unsupported.
- **Applicant-safe copy only.** The portal message names no vendor, shows no confidence scores or error diagnostics, and does not enumerate the supported-language list as a limitation ("we can't translate X" is fine; internal pipeline detail is not).
- **Compliance invariant unchanged.** Whether the English version was generated by Globus or supplied by the applicant, staff review it side-by-side with the original and verification remains blocked until the package — including a reviewable English version — is approved. Staff retain all existing actions (reject, request replacement, upload their own manual or certified translation superseding the applicant's).

### Translation Output & Generated PDF

The translation service receives extracted text in page order with page boundaries and document context, and is instructed to preserve names, dates, identifiers, and headings; mark unreadable text as [Illegible]; and never infer, invent, summarize, or omit readable content. Output is structured per page (source text retained internally for staff comparison), validated before PDF generation: every source page has a translated page, names/dates/document numbers preserved, no silent omission, no non-English target text. Entity mismatches create warnings, never replace source data. Two of the checks are hard failures, though. The source page numbers must be unique and form exactly 1..N for the reported page count, every source page must have a translated page, and a page with machine-readable text must have non-empty translated text; any gap fails with `CBC_TRANSLATION_PAGE_MISMATCH`. Identity tokens are the distinct digit runs of four or more characters on a page (years, dates, document numbers), and the source and translated sets must be exactly equal, so a token missing from the translation or one that appears only in the translation fails with `CBC_TRANSLATION_IDENTITY_MISMATCH` (the code and page number are recorded, never the token). Either failure sets the record to `manual_intervention_required` with reason code `BACKGROUND_CHECK_TRANSLATION_INACCURATE` before any PDF is generated. A blank source page is only a warning.

The generated PDF is clearly marked: header "AI-GENERATED ENGLISH TRANSLATION — derived from the original document, does not replace the original, human verification required"; per-page original page number, source language, and warnings; footer with document record ID, original artifact version, translation artifact version, and generated timestamp. It is never presented as a certified or government-issued document.

## Failure States & Queue Routing

Processing failures never lose the original upload. Transient failures get bounded retries (e.g. max 3, provider/network errors only). The applicant sees only a plain message — "Your document was received, but the English translation could not be completed automatically. Our team will review it." — never provider errors, confidence percentages, or technical details.

Routing uses the **existing** compliance/document-review queue structure — no new queue is created. The queue answers *who works on this* (Background Check Reviewer sees background_check cards); the reason code answers *why it is there*:

| Situation | Routing |
| --- | --- |
| Normal document awaiting review | Existing background-check document-review queue |
| Translation failed / OCR quality low / language undetermined / reviewer marks translation inaccurate / certified translation required | Same queue, with the matching BACKGROUND_CHECK_* reason code |
| Unsupported language awaiting applicant English translation upload | Same queue, BACKGROUND_CHECK_TRANSLATION_REQUIRED — visible to Compliance as waiting-on-applicant |

> **Deferred taxonomy question.** The evidence/document queue-family taxonomy is an open architecture decision (per-evidence queues vs a single queue keyed by reason code). This feature must not silently decide it — the implementation ticket references the existing decision point and requires confirmation of which queue family owns the work item.

## Rules Engine Integration

The compliance rule is authored as a standard regulatory / compliance_attestation rule using the existing decision contract and outcome classes — no PASS / NEEDS_REVIEW / FAIL parallel model. In plain terms: the rule checks that a current original exists, the language has been identified, a current English translation exists when required, the package has been reviewed, and no blocking issue remains; the engine returns an existing outcome class and emits the appropriate reason code and queue item.

Reason codes are added through central catalog governance, prefixed for reportability: BACKGROUND_CHECK_TRANSLATION_REQUIRED, BACKGROUND_CHECK_TRANSLATION_FAILED, BACKGROUND_CHECK_TRANSLATION_INACCURATE, BACKGROUND_CHECK_OCR_QUALITY_INSUFFICIENT, BACKGROUND_CHECK_LANGUAGE_UNDETERMINED, BACKGROUND_CHECK_CERTIFIED_TRANSLATION_REQUIRED. (A "processing underway" reason code is deliberately excluded — transient pipeline states live on the document record, not in a review queue.)

A separate set of catalogue reason codes serves the criminal-background compliance review itself (seeded from `server/seed/reasonCodeCatalog.ts`, severity hint `review`, routing domain `eligibility_documents`): `CRIMINAL_BACKGROUND_REVIEW_REQUIRED` (the outcome needs human review before the applicant can advance) and four sub-reasons, `CRIMINAL_BACKGROUND_DOCUMENT_UNREADABLE`, `CRIMINAL_BACKGROUND_TRANSLATION_FAILED` (the document could not be translated for review), `CRIMINAL_RECORD_INDICATOR_DETECTED` (an indicator of a criminal record was detected) and `CRIMINAL_BACKGROUND_UNABLE_TO_DETERMINE` (the result could not be determined from the document). Each holds the item for compliance review and carries an applicant message saying staff will review it. They are distinct from the BACKGROUND_CHECK_* translation-pipeline codes above.

Evaluation evidence surfaces: original present, detected language, whether the detected language is in the supported set, translation required, translation present and type (AI-generated, applicant-supplied, staff manual, certified), review status, and the resulting outcome.

> **Retired — no longer a J-1 Standard bundle member.** The package-verification rule (working key `background_check.package_verified`, "Criminal Background Package Verified (J-1)") was retired by migration `20271110000000_retire_cbc_package_verified_rule`: its published version is archived, the definition's published pointer is cleared, and it was dropped from the J-1 Standard bundle (`j1-standard`) by publishing a new immutable bundle version (published bundles are never edited in place). The definition, its versions and its publish-audit trail are retained. Nothing now gates on staff having verified the package, including the English translation where one was required. Criminal-background enforcement is the upload-presence rule (`documentation.criminal_background_upload_required`, hard blocking) plus `compliance.criminal_background_ai_assessment` (holds for review). The `backgroundCheckPackageVerified` and `backgroundCheckPackageStatus` facts are still produced and shown as compliance evidence; to gate on package verification again, author a new rule against that fact and attach it by publishing a new J-1 Standard bundle version.

## Review Model

Staff see one Criminal Background Check card carrying both files (original + translation, side by side, with page-to-page navigation), plus processing metadata (detected language, extraction method, OCR confidence, warnings). The card labels the translation's provenance — AI-generated, applicant-supplied, staff manual, or certified — so reviewers know an applicant-supplied English translation deserves the same scrutiny as an uncertified manual one. Reviewer actions: approve document package, reject document, request replacement, mark translation inaccurate, upload manual translation, upload certified translation, regenerate AI translation.

Artifact-level findings are stored separately from the package decision (artifact_reviews: pending, accepted, rejected, superseded, translation_inaccurate, manual_review_required). Package verification is not possible while the current translation is marked inaccurate or requires manual review.

The compliance case decision and evidence API, which serves the Compliance Console and the review queue alike, refuses bad input with 422. A refused decision is `COMPLIANCE_CASE_DECISION_REFUSED` and invalid evidence is `COMPLIANCE_CASE_EVIDENCE_INVALID`; the specific gap is in `details.code`. Decision codes include `RESOLUTION_OUTCOME_UNKNOWN` (a reviewer tried to record a system-only disposition as the resolution outcome), `CRIMINAL_BACKGROUND_OUTCOME_WRONG_CASE` (a criminal-background outcome was sent for a case that is not the criminal-background review case), `QUEUE_CASE_LINK_MISMATCH` (a review queue item was resolved with a case id that is not the case it is attached to) and `CASE_DECISION_PATH_UNAVAILABLE` (an item attached to a case can only be resolved through the case decision, and that path is not available in the calling context). Evidence codes when attaching evidence to a case: `EVIDENCE_KIND_UNKNOWN` (not an attachable kind), `EVIDENCE_REFERENCE_REQUIRED` (an `external_link` with no URL), `EVIDENCE_REFERENCE_UNSAFE` (the URL is not a complete http or https address, or embeds credentials), `EVIDENCE_DESCRIPTION_REQUIRED` (no label, note, URL or document), `EVIDENCE_DOCUMENT_REQUIRED` (an `applicant_document` with no document chosen) and `EVIDENCE_DOCUMENT_LOOKUP_UNAVAILABLE` (documents cannot be referenced from this context).

| Outcome | Effect |
| --- | --- |
| Approve | record review_status = verified; requirement = verified; step may complete |
| Reject original | record = rejected; requirement = replacement_requested; applicant provides a new original |
| Translation inaccurate | record processing_status = manual_intervention_required; original stays valid; applicant is NOT asked to re-upload unless the original is also defective |
| Manual / certified translation uploaded | new child artifact; AI translation marked superseded if the manual version becomes active |

### Certified Translation Definition

certified_translation is not just a file label. The role is assigned only when certification details are recorded: certification_type, certified_by_name, certified_by_organisation, certifier_registration_number, certification_country, certification_date, attestation_artifact_id, verified_by_staff_id, verified_at. manual_translation means an approved actor uploaded a translation with no formal certification claimed; certified_translation means verifiable certification or attestation accepted under the relevant program policy, confirmed by Globus staff before it becomes the active accepted translation.

## RBAC & PII Projection

Background-check detail is one of the five hard-coded Platform PII Registry entries — full suppression on all non-staff surfaces. Every retrieval path (package API, event feeds, exports, reports, audit interfaces) goes through the shared response projector; no endpoint returns artifacts or extracted fields merely because the caller can reach the route.

Permissions: document.background_check.view, .review, .request_replacement, .upload_translation, .mark_translation_inaccurate, .regenerate_translation, .override, .view_audit.

What each key gates (from the RBAC seed): `.view` views the package (originals, translations, review state); `.review` accepts, rejects or marks translation artifacts inaccurate; `.request_replacement` asks the applicant for a replacement document; `.view_audit` views the package audit trail; `.upload_translation` uploads a manual or certified translation and is enforced on the upload route; `.mark_translation_inaccurate` flags an AI translation as inaccurate, requiring manual handling; `.regenerate_translation` re-runs the AI translation pipeline and is enforced on the regenerate route; `.override` overrides a package decision outside the normal review flow, is a restricted key and requires a reason.

| Actor | Can | Cannot |
| --- | --- | --- |
| Applicant | Upload/replace the original; upload an English translation when prompted for an unsupported language; see applicant-safe status; **see their own original and the generated AI translation** (settled product decision) | Approve, regenerate, mark translation accurate, classify as certified; see risk findings, reviewer notes, queue reasons, confidence details |
| Partner | **Upload the original on the applicant's behalf, same as a Globus user** (settled product decision — current RBAC Upload grant stays) | See review findings, reviewer notes, queue reason details, extracted criminal-record text, or translation review internals — projection still masks everything except the upload action and a coarse requirement status (Complete / Pending / Applicant action required) |
| Background-check reviewer (staff) | View package, approve/reject, mark inaccurate, request replacement, trigger regeneration, upload manual translation | — |
| Compliance staff with override | Override package decisions, accept manual/certified translations, supersede a translation, record an exception with mandatory justification | — |

Files are encrypted at rest and in transit, served only via time-limited authenticated URLs, never public; every view/download is logged; applicant documents are never used to train external models; providers must be approved for applicant PII. Feature-specific governance references the existing Platform AI Governance, PII Registry, data-retention, and approved-provider policies rather than restating them.

## Audit Requirements

Every significant event is recorded: original uploaded, language detected, unsupported language fallback presented, applicant English translation uploaded, OCR started/completed, translation started/completed/failed, translated PDF generated, translation marked inaccurate, manual translation uploaded, artifact superseded, document approved/rejected, replacement requested. Each event carries application_id, document_record_id, artifact_id where applicable, event_type, actor, timestamp, previous/new state, metadata, and correlation_id.

> **Audit records describe events without copying sensitive text.** Extracted or translated criminal-record content must never appear in previous_state, new_state, metadata, or general logs. Good: `{"eventType":"translation_completed","artifactId":"123","sourceLanguage":"es","targetLanguage":"en"}`. Bad: any payload embedding translated record text.

Originals, generated translations, prior versions, and review decisions are never deleted or overwritten.

## Implementation Ticket Split

Five tickets, routed per the contract-vs-consumer convention (Globus core work on Globus boards; portal consumer work on the Applicant Portal board; OCR service work as its own ticket):

| Ticket | Scope |
| --- | --- |
| Globus Core — parent/child document package | Records, artifacts, immutable versioning, document statuses, step-status integration, package retrieval behind PII projection, RBAC, audit, reviewer UI |
| OCR Service — background document extraction | GCP Document AI integration, confirmed output contract, extraction, genuinely-existing confidence data, failures, service security |
| Globus Core — translation orchestration | Language detection from OCR text (Option B), translation request, English PDF creation, child-artifact creation, retries, timeouts, manual-intervention states; **includes amending the pre-existing GPT-4o-mini vision-detection ticket to exclude criminal background documents** |
| Rules and Queues | Existing outcome-class integration, BACKGROUND_CHECK_* reason-code catalog entries, existing review-queue routing, compliance gate evaluation, evaluation evidence |
| Applicant Portal consumer | Preserving the existing upload contract, applicant-safe processing messages, upload/replacement behaviour, timeout re-upload, applicant view of the AI translation, the unsupported-language English-translation upload control (same step, child artifact), eventual migration to the generic document API |

> **Filed — translation fallback delivery ticket.** The mandatory language set and unsupported-language applicant English upload fallback are filed as IT Tech Delivery Team ticket **"CBC Translation: mandatory language set + unsupported-language applicant English upload fallback"** (Asana task 1217709826504784), Sprint 33 (Current + Original Sprint), Workflow Status "New Requirements (To Do)", assigned to **Samuel O'Regan**. Its scope covers the supported-language configuration, the fallback upload control, package-verification gating, replacement supersession, provenance labelling, audit events, and the test scenarios listed on that ticket.

## Related Pages

Document Storage (storage backend, signed URLs, versioning, state machine) · Form Engine (upload endpoint registry) · Applicant Lifecycle (stepper placement, compliance gates) · Rules Engine Architecture (outcome classes, reason-code catalog) · Queue System (document-review queues) · RBAC (permission matrix) · Applicant vs Application Data (Platform PII Registry).
