# M4 Verification Architecture Contract (Attire, Government ID, Certification)

Status: Partially implemented in dev (core endpoints + async in-memory processor)  
Date: 2026-02-24  
Owner: Technical Lead

## Implementation status today (dev)
1. Implemented routes:
- `POST /core/verifications`
- `GET /core/verifications/{verificationId}`
- `POST /core/verifications/{verificationId}/review`
- `POST /core/verifications/{verificationId}/retry`
2. Current processor is in-memory and non-persistent (for fast frontend integration in dev).
3. Next hardening step is persistent job storage and worker execution before staging.
4. Attire uses a live Vertex vision model path with `gemini-2.0-flash-lite-001` by default.
5. Government ID and certification use third-party adapter contracts (provider URL/token envs) and fall back to `NEEDS_REVIEW` when providers are not configured.

## 1) Goal
Define a single backend verification pipeline for:
1. `attire`
2. `government_id`
3. `certification`

This contract gives the team exact endpoint behavior, state flow, and ownership before coding.

## 2) Principles
1. Upload is evidence intake, not final verification.
2. Verification runs asynchronously in backend workers.
3. Model output is a signal, not legal truth.
4. High-risk identity decisions require stronger validation and human audit trail.
5. Every decision is traceable (`who`, `what`, `when`, `why`).

## 3) Verification types and policy

## 3.1 Attire
1. Primary check: vision model + rule checks.
2. Typical output: `AUTO_PASS`, `AUTO_FAIL`, or `NEEDS_REVIEW`.
3. Manual override is always allowed.

## 3.2 Government ID
1. Required path for mission-critical use: third-party identity verification provider.
2. Model/OCR can pre-parse fields but does not replace identity verification.
3. Final status should require either provider success or manual approval by authorized reviewer.

## 3.3 Certification
1. Preferred path: verify against issuer API/registry when available.
2. If no issuer API: OCR extraction + manual review.
3. Keep evidence of the source used for validation.

## 4) State model
1. `PENDING`
2. `PROCESSING`
3. `AUTO_PASS`
4. `AUTO_FAIL`
5. `NEEDS_REVIEW`
6. `APPROVED`
7. `REJECTED`
8. `ERROR`

Rules:
1. `AUTO_*` and `NEEDS_REVIEW` are machine outcomes.
2. `APPROVED` and `REJECTED` are human outcomes.
3. All transitions are append-only in audit events.

## 5) API contract

## 5.1 Create verification job
1. Route: `POST /core/verifications`
2. Auth: required
3. Purpose: enqueue verification job for previously uploaded file.
4. Request:
```json
{
  "type": "attire",
  "subjectType": "staff",
  "subjectId": "staff_123",
  "fileUri": "gs://krow-workforce-dev-private/uploads/<uid>/item.jpg",
  "rules": {
    "attireType": "shoes",
    "expectedColor": "black"
  },
  "metadata": {
    "shiftId": "shift_123"
  }
}
```
5. Success `202`:
```json
{
  "verificationId": "ver_123",
  "status": "PENDING",
  "type": "attire",
  "requestId": "uuid"
}
```

## 5.2 Get verification status
1. Route: `GET /core/verifications/{verificationId}`
2. Auth: required
3. Purpose: polling from frontend.
4. Success `200`:
```json
{
  "verificationId": "ver_123",
  "type": "attire",
  "status": "NEEDS_REVIEW",
  "confidence": 0.62,
  "reasons": ["Color uncertain"],
  "extracted": {
    "detectedType": "shoe",
    "detectedColor": "dark"
  },
  "provider": {
    "name": "vertex-attire",
    "reference": "gemini-2.0-flash-lite-001"
  },
  "review": null,
  "createdAt": "2026-02-24T15:00:00Z",
  "updatedAt": "2026-02-24T15:00:04Z",
  "requestId": "uuid"
}
```

## 5.3 Review override
1. Route: `POST /core/verifications/{verificationId}/review`
2. Auth: required (reviewer role later; auth-first now + explicit reviewer id logging)
3. Purpose: final human decision and audit reason.
4. Request:
```json
{
  "decision": "APPROVED",
  "note": "Document matches required certification",
  "reasonCode": "MANUAL_REVIEW"
}
```
5. Success `200`:
```json
{
  "verificationId": "ver_123",
  "status": "APPROVED",
  "review": {
    "decision": "APPROVED",
    "reviewedBy": "user_456",
    "reviewedAt": "2026-02-24T15:02:00Z",
    "note": "Document matches required certification",
    "reasonCode": "MANUAL_REVIEW"
  },
  "requestId": "uuid"
}
```

## 5.4 Retry verification job
1. Route: `POST /core/verifications/{verificationId}/retry`
2. Auth: required
3. Purpose: rerun failed or updated checks.
4. Success `202`: status resets to `PENDING`.

## 6) Worker execution flow
1. API validates payload and ownership of `fileUri`.
2. API writes `verification_jobs` row with `PENDING`.
3. Worker consumes job, marks `PROCESSING`.
4. Worker selects processor by type:
- `attire` -> model + rule scorer
- `government_id` -> provider adapter (+ optional OCR pre-check)
- `certification` -> issuer API adapter or OCR adapter
5. Worker writes machine outcome (`AUTO_PASS`, `AUTO_FAIL`, `NEEDS_REVIEW`, or `ERROR`).
6. Frontend polls status route.
7. Reviewer finalizes with `APPROVED` or `REJECTED` where needed.

## 7) Data model (minimal)

## 7.1 Table: `verification_jobs`
1. `id` (pk)
2. `type` (`attire|government_id|certification`)
3. `subject_type`, `subject_id`
4. `owner_uid`
5. `file_uri`
6. `status`
7. `confidence` (nullable)
8. `reasons_json`
9. `extracted_json`
10. `provider_name`, `provider_ref`
11. `created_at`, `updated_at`

## 7.2 Table: `verification_reviews`
1. `id` (pk)
2. `verification_id` (fk)
3. `decision` (`APPROVED|REJECTED`)
4. `reviewed_by`
5. `note`
6. `reason_code`
7. `reviewed_at`

## 7.3 Table: `verification_events`
1. `id` (pk)
2. `verification_id` (fk)
3. `from_status`, `to_status`
4. `actor_type` (`system|reviewer`)
5. `actor_id`
6. `details_json`
7. `created_at`

## 8) Security and compliance notes
1. Restrict verification file paths to owner-owned upload prefixes.
2. Never expose raw private bucket URLs directly.
3. Keep third-party provider secrets in Secret Manager.
4. Log request and decision IDs for every transition.
5. For government ID, keep provider response reference and verification timestamp.

## 9) Provider configuration (environment variables)
1. Attire model:
- `VERIFICATION_ATTIRE_PROVIDER=vertex`
- `VERIFICATION_ATTIRE_MODEL=gemini-2.0-flash-lite-001`
2. Government ID provider:
- `VERIFICATION_GOV_ID_PROVIDER_URL`
- `VERIFICATION_GOV_ID_PROVIDER_TOKEN` (Secret Manager recommended)
3. Certification provider:
- `VERIFICATION_CERT_PROVIDER_URL`
- `VERIFICATION_CERT_PROVIDER_TOKEN` (Secret Manager recommended)
4. Provider timeout:
- `VERIFICATION_PROVIDER_TIMEOUT_MS` (default `8000`)

## 10) Frontend integration pattern
1. Upload file via existing `POST /core/upload-file`.
2. Create verification job with returned `fileUri`.
3. Poll `GET /core/verifications/{id}` until terminal state.
4. Show machine status and confidence.
5. For `NEEDS_REVIEW`, show pending-review UI state.

## 11) Delivery split (recommended)
1. Wave A (fast): attire verification pipeline end-to-end.
2. Wave B: certification verification with issuer adapter + review.
3. Wave C: government ID provider integration + reviewer flow hardening.
