# Verixa — User Requirements Specification

# Module 39B (Addendum): Phase-2 Verified Production Build — Verification-Scope Delta (Claude-Code-Ready)

> **Two-document split (matches the HTML flow phases).** **URS-39A** = Phase-1 Demo Environment (segregation / synthetic / no-record-of-record). **URS-39B (this document)** = Phase-2 verified production build delta. Phase-3 partner validation is governed by the partner's own CSV/CSA. **Demo controls are NOT in this document — see URS-39A.**

| Field | Value |
|---|---|
| Module ID | URS-39B (Phase-2 verified production build; companion to **URS-39A** Phase-1 Demo; addendum to target-state URS 1–36 + URS-38) |
| Document type | **Cross-module build-delta URS addendum.** It does NOT replace URS-02/03/04/05/06/12/13/16/17/18/21/22/28/30/32/35/38; it specifies the **net-new pilot build** against them, with confirmed current-state repo evidence. |
| Architecture Bindings | Subject to **ARCH-AI-001 (AI Optionality & Manual Continuity)**. All MIRA/AI surfaces are **advisory only**. **EU AI Act transparency obligations shall be assessed by RA/legal:** for MIRA's advisory/limited-risk use, **Article 50** (transparency for certain/generative/interactive AI) may apply; **Article 13** (transparency to deployers) applies **only if** MIRA or a deployed configuration is classified high-risk. **Roles:** Verixa is the **provider of the MIRA AI system**; Anthropic/Azure are **GPAI model providers** (GPAI provider obligations applying from 02-Aug-2025). Internal **EU GMP Annex 22 (Draft 2025)** control (Annex-22-aligned, internal forward-looking — **enforceability and final clause mapping: `Unknown — evidence required`**): generative/probabilistic AI is **PROHIBITED** in any critical GMP decision path (batch disposition, OOS classification, CAPA/deviation/finding disposition, closure, reopen). No AI service is the sole path to create, dispose, or close a regulated record. |
| Module Owner (Engineering) | Pilot Squad (2.5 FS + 1 build hand) · QA/Validation (2 QA + 1 CSV/CSA-RA contractor) |
| Repo basis | `dev-vimal-audit-2 @ 3bd2fe47` (READ-ONLY static audit, 2026-05-31). Build on a feature branch off this base. |
| Governed by | `Verixa_Pilot_Execution_Plan_v3_MASTER.md`. Verixa **verifies**; the design partner **validates** intended use. Never "validated." |
| Status | **Draft / blockers open / not executed / not approved — RECOMMENDED for controlled engineering build planning only (NOT yet signed/approved).** NOT approved for validation execution, G-7 issuance, Part 11 control claim, release-readiness claim, or production-verified claim. ("Approved" shall mean a recorded human approval signature, not advisory suitability.) All requirements PLANNED; implementation/verification status `Unknown — evidence required` until executed evidence + QA disposition exist. **Current-state references code-validated against `dev-vimal-audit-2` on 2026-05-31 (§7B): 16/17 accurate, 1 corrected, 0 fabricated** (raw grep/read evidence to be retained as a validation artifact). Line numbers must be re-confirmed at build. **This is a build-delta spec, NOT a validation package (see §7C).** |

---

## 0. Document Framing

### 0.1 Purpose
This addendum is a **controlled engineering build-planning spec** (NOT a binding contract until baseline-approved) for the **Phase-2 production-verified build delta** on top of the existing target-state URS 1–36. It is written so a **non-domain engineer using Claude Code or Cursor** can take a single requirement block, paste its **Claude Code Handoff Block** into the agent, and build the change against the real repo — with the current-state file:line, the reference implementation to copy, the acceptance criteria, the required tests, and the verification gates already supplied. It saves engineers the discovery step.

> **Scope framing (read first).** URS-39B governs the **Phase-2 production-verified build delta** and the regulated controls it requires. **Phase-1 demo behaviour is governed ONLY by the separate document `URS-39A` and the pilot flow (G-DEMO, hard-locked 26-Jun-2026) — NOT by this document.** Demo features may be visually complete without being production-verified. **URS-39B is not the demo script.**

### 0.2 Audience
Backend/frontend engineers (incl. AI-assisted via Claude Code/Cursor), QA/validation engineers, the CSV/CSA-RA contractor, AI Owner, product owner, and inspectors.

### 0.3 How to use this addendum with Claude Code (time-saver)
1. Pick the work-package (WP) you own.
2. Read its **Why / Current-state / Target-state / Acceptance / Tests**.
3. Copy its **🤖 Claude Code Handoff Block** verbatim into Claude Code/Cursor at the repo root on your feature branch.
4. The block already contains: repo context, branch, the `CLAUDE.md` QS rules + verification gates, the exact files + line refs, the reference pattern to copy, the Definition of Done, and the required tests. Let the agent draft; **you (named human) review and own every merged line** (AI-assisted-dev control, §0.6).
5. Run the verification gate block. Capture evidence to G-7.

### 0.4 Plain-language primer
Verixa is a quality-management system for drug/biotech companies; regulators can inspect every action. Three non-negotiables apply to every change here: **(1)** every database write is tenant-scoped (`tdal.withTenant`), row-level-secured (RLS), and audited (`auditTrailService.logWithTx` in the same transaction) — never raw `pool.query`; **(2)** every GxP approval, closure, or disposition step **identified as regulated, authority-controlled, or parent-URS e-signature-controlled** shall require e-signature **verification against the e-signature substrate** before transition (not merely stored); **(3)** AI is advisory only — labelled, logged, human-accepted before it touches a record, never in a critical GMP decision.

### 0.5 Conventions
- **Requirement IDs:** `URS-39-<WP>-<seq>` (e.g., `URS-39-WP4-01`). Business rules: `BR-39-<WP>-<n>`. Acceptance: `AC-39-<WP>-<n>`. Test cases: `TC-39-<WP>-<n>`.
- **Priority:** MUST (pilot-blocking) / SHOULD (pilot-desirable) / COULD (defer).
- **Current-state verdict:** CONFIRMED / PARTIALLY CONFIRMED / REFUTED / `Unknown — evidence required`, from the 2026-05-31 read-only audit. Line numbers are audit-observed and **must be re-confirmed at build time** (`Schema/line verification required`).
- **Commitment:** all six workflows + MIRA are **IN SCOPE — COMMITTED**. Go-live is **per-workflow**: a workflow is "production-verified" only if built + risk-based-verified + in G-7 + covered by signed G-8 + no open integrity/AI/security/supplier blocker; otherwise demo-only or deferred to a controlled wave (target 01 Sep, buffer to 15 Sep).

### 0.6 AI-assisted-development control (binding for this addendum)
Because the team builds with Claude Code + Cursor in a GAMP 5 Category 5 system: **(a)** every change carries **named-human code-review evidence**; **(b)** the `CLAUDE.md` verification gate runs in **CI with retained evidence**; **(c)** integrity-core changes (WP-4, WP-13b, WP-2) are built by senior devs (agent-assisted), not the new build hand; **(d)** the human reviewer is accountable for every merged line. Decide the **PDF generation library in Week 1** (shared by WP-12 + WP-13).

### 0.7 Glossary (terms used here)
| Term | Plain meaning |
|---|---|
| TDAL | Tenant Data Access Layer — `tdal.withTenant(tenantId, db=>…)` sets `app.current_tenant_id` for RLS. |
| RLS | Row-Level Security — Postgres policy isolating tenant rows. |
| e-sig substrate | The `electronic_signatures` table; a signature is "verified" when read back and checked for signer, entity binding, meaning, freshness. |
| HITL | Human-in-the-loop — AI draft → human accept/edit/reject before record impact. |
| SoD | Segregation of Duties — actor A ≠ actor B on linked steps. |
| MIRA | Verixa's advisory AI copilot (LLM-backed; Anthropic/Azure). |
| G-7 / G-8 | Supplier assurance evidence pack / signed quality agreement (responsibility split). |

---

## 1. Document Control
| Item | Value |
|---|---|
| Version | 0.1 Draft |
| Date | 2026-05-31 |
| Supersedes | none (additive to URS 1–36 / URS-38) |
| Approval (target) | Product Owner + QMS SME + Validation + QA Approver + AI Owner + Founder |

---

## 2. Scope

### 2.1 In scope (the pilot build delta)
Platform foundation (WP-1 access/scope, WP-2 event-spine subset, WP-4 e-sig substrate verification, WP-5 audit-chain coverage); the six workflows (WP-6 Document Control, WP-7 Deviation, WP-8 RCA, WP-9 CAPA, WP-10 Findings→CAPA, WP-12 Inspection Readiness export); the MIRA engine (WP-11 training gate, WP-13 MIRA guardrails + PDF, WP-13b fail-closed AI audit, MIRA V7 provider assurance); and the differentiator (WP-14 readiness scorecard, per URS-38). Each maps to its parent URS module §21/§22/§23 addendum.

### 2.2 Out of scope
GMP batch disposition/release, equipment/calibration, environmental monitoring, stability, APQR/PQR, OOS/OOT as a standalone in-scope workflow, multi-tenant/multi-site operation (single-tenant lock per WP-1), full scope-eligibility enforcement (deferred to Phase 2), advanced authoring (Word round-trip/redline beyond pilot need), and any high-risk autonomous AI decisioning.

**WP-3 (multi-mode / co-sign e-signature) — explicitly OUT of Phase-1 build scope** unless a named Phase-1 workflow step is formally declared multi-signer by QA and Product. No WP-3 implementation shall be assumed from URS-39. (Note: WP-7 critical-deviation executive co-sign, URS-39-WP7-01, is a defined two-signer step on that one path; it does not require the general WP-3 multi-mode engine.)

### 2.3 Regulatory drivers (applicability)
21 CFR Part 11 (§11.10(d)(e), §11.70, §11.100(c)); EU Annex 11; EU Annex 22 (Draft 2025 — **internal Annex-22-aligned control; enforceability + final clause mapping `Unknown — evidence required`** until RA/legal confirms official status); EU AI Act 2024/1689 (Verixa = **provider of the MIRA AI system**; Anthropic/Azure = **GPAI model providers**, obligations from 02-Aug-2025; transparency article — **Article 50** for advisory/limited-risk, **Article 13** only if high-risk — **to be confirmed by RA/legal**); FDA CSA (issued 03-Feb-2026, supersedes 24-Sep-2025) — risk-based verification. *Exact clause enforceability + AI Act article mapping subject to jurisdiction-specific RA/legal assessment.*

### 2.4 Phase-1 demo — moved to URS-39A

Phase-1 demo environment requirements (segregation, synthetic data, no record-of-record, watermark, G-DEMO gate, no demo→production migration) live in the separate document **`URS-39A — Phase-1 Demo Environment`**. They are intentionally **not** in this Phase-2 build document. Demo features may be visually complete in URS-39A scope without being production-verified under this document.

---

## 3. Build Requirements (per work package)

> Each block is self-contained. The **🤖 Claude Code Handoff Block** is paste-ready.

### Shared verification gate (every WP must pass — paste with any handoff)
```
GATES (run before commit; CI-enforced, retain evidence):
  cd packages/backend && npx tsc --noEmit --strict
  cd packages/frontend && npx tsc --noEmit --strict
  npx eslint packages/ --max-warnings 0
  cd packages/backend && npx vitest run
  # audit-trail coverage (must be empty): mutations without auditTrailService.log
  grep -rn "INSERT INTO\|UPDATE .* SET\|DELETE FROM" packages/backend/src/modules/ --include="*.ts" | grep -v audit | grep -v ".test." | grep -v "// AUDIT-EXEMPT:"
  # RLS coverage (must be empty): new tables without RLS
  grep -rn "CREATE TABLE" packages/backend/src/db/migrations/ -l | xargs grep -L "ENABLE ROW LEVEL SECURITY"
  # no any (must be empty)
  grep -rn ": any\b\|as any\b" packages/backend/src packages/frontend/src --include="*.ts" --include="*.tsx" | grep -v ".test." | grep -v "// ANY-JUSTIFIED:"
  # raw pool.query outside TDAL (must be empty)
  grep -rn "pool\.query" packages/backend/src/modules --include="*.ts" | grep -v ".test." | grep -v "// RAW-SQL-JUSTIFIED:"
  # no LLM in critical GMP modules (must be empty)
  for m in batch gmp oos-oot stability; do grep -rn "anthropic\|openai\|llm\|mira" packages/backend/src/modules/$m/ --include="*.ts" 2>/dev/null | grep -v ".test."; done
GATE LIMITATIONS (read before relying on these):
  - These grep checks are a SMOKE GATE, not validation evidence. They can false-positive and false-negative.
  - Before RC freeze, run a real route/mutation INVENTORY script (enumerate every route + every INSERT/UPDATE/DELETE and assert audit + TDAL + RLS coverage per item) — grep alone is insufficient.
  - `// ANY-JUSTIFIED:` / `// AUDIT-EXEMPT:` / `// RAW-SQL-JUSTIFIED:` annotations are loopholes unless each is reviewed + signed off by QA; track them in a register.
  - Gate evidence (CI run logs) is retained per the AI-assisted-dev control (§0.6); the gate is necessary, not sufficient, for verification.
GLOBAL CONSTRAINTS for any change:
  - Every mutation: tdal.withTenant(...) + RLS on table + auditTrailService.logWithTx(...) in the SAME transaction. Never raw pool.query.
  - Every new table migration: idempotent (IF NOT EXISTS / DO $$), ENABLE ROW LEVEL SECURITY + tenant_isolation policy, -- ROLLBACK: comment, no DDL+DML mixed.
  - Every regulated, authority-controlled, or parent-URS e-signature-controlled approval/closure/disposition: withAuthority({ requiredAuthorityKey, requiresEsign:true, scopeSource:'context' }) + verify e-sig vs electronic_signatures substrate before transition.
  - Zod validation at every route boundary; structured errors (no stack traces/SQL in responses); zero `any`.
  - AI output is advisory: labelled, logged to ai_requests/llm_audit_log, human-accepted before any record write. Never generative AI in a critical GMP decision.
```

---

### WP-4 — E-signature substrate verification  ·  Priority: MUST  ·  Risk: HIGH (Part 11 §11.70)
**Parent URS:** URS-04 §21, consumed by URS-13/17/18. **GxP domain:** GDocP / CSV / Part 11.

> **⚠ SCOPE CORRECTION — CC-PILOT-2026-001 (2026-06-01, LOCKED).** The **batch module is NOT deployed in Phase-1 or Phase-2.** Therefore **WP-4 pilot scope = change-control + RCA only.** Every reference to the **batch path** below (requirements, acceptance, tests, the Claude Code handoff block, the §3D diagrams, and DS-39-WP4) is **superseded**: the `batch/service.ts` e-sig fix is **deferred to Phase-3** with URS-23. Instead, WP-4 **shall add a non-exercise check**: deployment evidence + a negative test proving the **batch hold/disposition** and **OOS disposition** *write* routes are not exercised in the pilot build. **OOS is reference/display IN Phase-1** (records seeded, displayed in the deviation, with a multi-batch `affected_batch` link — final scope decision 2026-06-02); only the **OOS operate-and-dispose workflow validation** is deferred to Phase-3. Minimal **batch master data is seeded as reference**; the batch hold/disposition workflow is Phase-3. With no live disposition write path, the deferral carries no Part 11 §11.70 pilot exposure. `oos-oot/service.ts` is also the e-sig **reference pattern** WP-4 copies.

**Why.** Some modules store a client-supplied `esig_id` on an approval **without verifying it is real** — a forgeable electronic signature on a production GxP record.

**Current-state (audit-confirmed):**
- Reference impl (correct, KEEP): `modules/oos-oot/service.ts:709–733` reads `electronic_signatures` and verifies signer, entity binding, meaning, freshness; `document-quality-gateway/service.ts:72–94` similar.
- Canonical verifier exists but under-used: `modules/hitl/esig.service.ts:650` `validateEsignatureForRecord` (6-point check) — only one caller.
- Gap (REFUTED safety): `modules/change-control/service.ts approveChange ~L964` stores `esig_id/esig_hash` with **zero** substrate read; `modules/rca/service.ts approveRCA/rejectRCA ~L786` stores `approval_esig_id`, route-permission only; `modules/batch/service.ts ~L256` verifies only when `esig_id` supplied (bypassable).

**Target-state requirements:**
- **URS-39-WP4-01 (MUST):** The system **shall** route every approval/closure/disposition through the canonical verifier (`validateEsignatureForRecord`) and verify the signature against the `electronic_signatures` substrate (signer = actor, entity_type/entity_id binding, meaning = approved, freshness window) **before** any state transition.
- **URS-39-WP4-02 (MUST):** The system **shall** write a bound `electronic_signatures` reference on the signed record; an approval presenting an invalid/forged/non-bound `esig_id` **shall** be rejected. **Error-code normalization:** callers **shall** normalize substrate-verification failures to a single outward code **`ESIG_VERIFICATION_FAILED`**, while **preserving the original diagnostic reason** (e.g., the canonical verifier's existing `RESTORE_SIGNATURE_INVALID` / `ROLLBACK_AUTHORITY_REVOKED` / signer / binding / meaning / freshness reason) in internal audit/error metadata. *(Note: `validateEsignatureForRecord` is currently used in a restore/rollback path and throws restore/rollback-specific codes; approval/closure callers must map to the single expected code so tests have one deterministic failure code.)*
- **URS-39-WP4-03 (MUST):** Change Control close/approve and RCA approve/reject **shall** mandate verification. **Batch disposition is OUT of pilot scope (module not deployed — CC-PILOT-2026-001); the batch fix is deferred to Phase-3.** In its place, the build **shall** prove the **batch hold/disposition and OOS disposition** *write* routes are not exercised in the pilot (OOS **reference/display is IN** — final scope decision 2026-06-02; full OOS workflow validation is Phase-3).

**Business rules:** `BR-39-WP4-1` no transition without verified bound signature; `BR-39-WP4-2` SoD preserved (signer eligibility unchanged); `BR-39-WP4-3` verification failure emits audit event + structured 4xx, no record mutation.

**Acceptance (Definition of Done):**
- `AC-39-WP4-1`: approval with invalid/forged `esig_id` → rejected (`ESIG_VERIFICATION_FAILED`), no record change, audit written.
- `AC-39-WP4-2`: every signed transition in **change-control and rca** has a bound, substrate-verified signature. *(Batch excluded — module not deployed; Phase-3.)*
- `AC-39-WP4-3`: existing OOS/document-quality-gateway behaviour unchanged (regression).
- `AC-39-WP4-4`: the **batch hold/disposition and OOS disposition** *write* routes are **not exercised** in the pilot build (deployment evidence + negative test); OOS **reference/display reads remain IN**.

**Tests:** `TC-39-WP4-1` forged esig rejected (negative); `TC-39-WP4-2` valid esig accepted + bound row written; `TC-39-WP4-3` **batch hold/disposition + OOS disposition write routes not exercised in the pilot (negative)** *(OOS reference/display reads remain IN; batch fix is Phase-3)*; `TC-39-WP4-4` audit event on failure; `TC-39-WP4-5` tenant isolation (sig from another tenant rejected).

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo, branch off dev-vimal-audit-2. GAMP5 Cat5 GxP. Follow CLAUDE.md QS-1..QS-24 + the Shared verification gate above.
TASK (WP-4): Make every approval/closure/disposition VERIFY the e-signature against the electronic_signatures substrate before transitioning, and write a bound signature row.
REFERENCE PATTERN TO COPY: modules/oos-oot/service.ts:709-733 (substrate verify) and the canonical verifier modules/hitl/esig.service.ts:650 validateEsignatureForRecord.
FILES TO FIX:
  - modules/change-control/service.ts approveChange (~L964 stores esig_id/esig_hash unverified) and closeChangeRequest (~L1526, no esig handling).
  - modules/rca/service.ts approveRCA + rejectRCA (~L786 stores approval_esig_id, route-permission only).
  - DO NOT TOUCH modules/batch/service.ts — batch module is NOT deployed in the pilot (CC-PILOT-2026-001); the batch e-sig fix is deferred to Phase-3 with URS-23.
DO: route change-control + rca through validateEsignatureForRecord; reject invalid/forged; NORMALIZE all substrate-verification failures to one outward code ESIG_VERIFICATION_FAILED while preserving the verifier's original reason (RESTORE_SIGNATURE_INVALID / ROLLBACK_AUTHORITY_REVOKED / signer / binding / meaning / freshness) in internal audit/error metadata; write bound electronic_signatures reference; keep SoD checks.
ALSO: prove the batch hold/disposition + OOS disposition WRITE routes are not exercised in the pilot (feature-flag off or not wired) and add a negative test. NOTE: OOS reference/display (reads) IS in scope — do NOT block OOS reads; only the OOS disposition (validated write) is Phase-3.
KEEP (do not change): modules/oos-oot/service.ts, modules/document-quality-gateway/service.ts.
ACCEPTANCE: AC-39-WP4-1/2/3 above. TESTS: TC-39-WP4-1..5 (incl. forged-esig negative + tenant isolation). 
VERIFY: re-confirm all line numbers before editing (Schema/line verification required). Run the gate block.
```

---

### WP-13b — Fail-closed LLM audit in regulated mode  ·  Priority: MUST  ·  Risk: HIGH (Annex 22 / EU AI Act, AI evidence integrity)
**Parent URS:** URS-32 §22 BR-32-GUARD-02. **GxP domain:** AI / CSV / Data Integrity.

**Why.** The AI gateway's immutable LLM audit logger is **optional**; if unwired, AI inference runs **un-audited**. In regulated mode that must be impossible.

**Current-state (audit-confirmed):** `modules/ai/ai-gateway.service.ts:100` declares `private readonly llmAudit?: LlmAuditService` (optional); the immutable hash-chain write runs only `if (this.llmAudit)` at `:228` (and `:429` embeddings). **3 production construction sites omit the logger:** `gdp/plugin.ts:92`, `document-library/plugin.ts:32`, `hardening/plugin.ts:155`. No regulated-mode/fail-closed guard exists.

**Target-state requirements:**
- **URS-39-WP13b-01 (MUST):** In regulated mode the LLM audit-chain service **shall** be **required** — the gateway shall not be constructable or invocable without it.
- **URS-39-WP13b-02 (MUST):** Any inference path where the immutable audit write fails **shall fail the request**; no AI inference completes un-audited in regulated mode.
- **URS-39-WP13b-03 (MUST):** A typed config flag **shall** default fail-closed in production tenants; non-regulated/dev behaviour documented.

**Business rules:** `BR-39-WP13b-1` no inference without an audit sink in regulated mode; `BR-39-WP13b-2` audit record captures model name, version, input hash, output, confidence, userId, accept/reject/edit; `BR-39-WP13b-3` the 3 omitting plugins are wired with the logger.

**Acceptance:** `AC-39-WP13b-1`: with the audit chain absent in regulated mode, gateway construction **or** the request fails; `AC-39-WP13b-2`: a test proves no inference completes un-audited in regulated mode; `AC-39-WP13b-3`: gdp/document-library/hardening plugins pass the logger.

**Tests:** `TC-39-WP13b-1` construct gateway without logger in regulated mode → throws; `TC-39-WP13b-2` audit-write failure → request fails, no provider effect persisted as accepted; `TC-39-WP13b-3` dev mode documented path; `TC-39-WP13b-4` each wired plugin logs an inference.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo, branch off dev-vimal-audit-2. GAMP5 Cat5 GxP. Follow CLAUDE.md + Shared verification gate. SENIOR DEV ONLY (integrity core).
TASK (WP-13b): Make the LLM audit logger REQUIRED and FAIL-CLOSED in regulated mode so no AI inference runs un-audited.
FILES: modules/ai/ai-gateway.service.ts (constructor L100 `llmAudit?`; logging gated at L228 + L429). Wiring sites that omit it: gdp/plugin.ts:92, document-library/plugin.ts:32, hardening/plugin.ts:155.
DO: add a typed regulated-mode config flag (mirror core/config.ts fail-fast pattern, no unsafe default); when regulated, require llmAudit at construction; if the audit write throws, fail the request; wire the 3 plugins with the logger.
KEEP: the existing ai_requests coarse write (L208); the provider-call path otherwise unchanged.
ACCEPTANCE: AC-39-WP13b-1/2/3. TESTS: TC-39-WP13b-1..4. 
VERIFY line numbers first. Run the gate block (incl. no-LLM-in-critical-modules check).
```

---

### WP-2 — Event-spine linkage subset  ·  Priority: MUST  ·  Risk: MEDIUM
**Parent URS:** URS-30 §21 (BR-30-SPINE-01/02/03). **GxP domain:** GMP/GDocP workflow connectivity.

**Why.** ~18 emitted events have **no consumer**, and the Finding→CAPA / Inspection-observation→Finding linkage events are **never emitted**. For the pilot, wire **only** the linkage events the six in-scope workflows need — not all 18.

**Current-state (audit-confirmed):** event bus `core/event-bus.ts` (singleton); 3 subscriber registries (`notifications/event-subscriber.ts`, `config/workflow-auto-spawn.subscriber.ts`, `handover-bridge/plugin.ts`). Orphaned (emitted, no consumer): `document_effective` (`documents/service.ts:1061`), `document_retired` (`:1144`), `document_superseded` (`:1261`), `review_status_changed` (`reviews/service.ts:622,679`), `rca_conclusion_created` (`rca/service.ts:670`), `rca_capa_linked` (`:1545,1587`), `product_*`. **`finding_capa_linked` and `inspection_observation_finding_created` do not exist anywhere.** RCA has a manual `linkCapaToRca` route action (`rca/service.ts:1473`).

**Target-state requirements:**
- **URS-39-WP2-01 (MUST):** The system **shall** wire consumers for the in-scope linkage events only: `document_effective`→training assignment (WP-11; manual acceptable for pilot), observation→finding→CAPA, deviation/OOS-confirmed→CAPA, RCA→CAPA.
- **URS-39-WP2-02 (MUST):** The system **shall** emit `finding_capa_linked` and `inspection_observation_finding_created` (new) and consume them (WP-10, WP-12).
- **URS-39-WP2-03 (MUST):** A coverage test **shall** fail if any **in-scope** GxP event has no consumer. (Out-of-scope orphaned events explicitly excluded for pilot.)

**Acceptance:** `AC-39-WP2-1` each in-scope event produces its notification/action; `AC-39-WP2-2` observation→finding→CAPA chain flows; `AC-39-WP2-3` in-scope coverage test green.

**Tests:** `TC-39-WP2-1` each in-scope event has a consumer; `TC-39-WP2-2` SOP-effective triggers training; `TC-39-WP2-3` finding-linked emits + consumed.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo, branch off dev-vimal-audit-2. GAMP5 Cat5. CLAUDE.md + Shared gate. SENIOR DEV (integrity-adjacent).
TASK (WP-2): Wire ONLY the linkage events the six pilot workflows need; do NOT wire all 18 orphaned events.
BUS: core/event-bus.ts. SUBSCRIBERS: notifications/event-subscriber.ts, config/workflow-auto-spawn.subscriber.ts.
DO: add consumers for document_effective->training (manual-assign acceptable), observation->finding->CAPA, deviation/OOS-confirmed->CAPA, rca_conclusion_created/rca_capa_linked->CAPA (or reuse rca/service.ts:1473 linkCapaToRca). Emit + consume new events finding_capa_linked, inspection_observation_finding_created. Add a coverage test that fails if an IN-SCOPE GxP event has no consumer.
KEEP: existing subscribers + working examples (deviations/service.ts:622 closure-requires-CAPA).
ACCEPTANCE: AC-39-WP2-1/2/3. TESTS: TC-39-WP2-1..3. VERIFY line numbers. Run gate.
```

---

### WP-1 — Single-tenant / site lock (scope isolation, pilot mitigation)  ·  Priority: MUST  ·  Risk: HIGH→LOW-when-locked
**Parent URS:** URS-02/03/05 §21. **GxP domain:** Access control / tenant isolation / Annex 11 §12.

**Why.** `context-gate /switch` changes active scope with **no eligibility check** (`CROSS_CONTEXT_DENIED` absent) — a data-isolation hole. Full eligibility enforcement is deferred to Phase 2; for the pilot, **lock to a single tenant/site** so the blast radius is ~zero, and prove isolation with the P6 test.

**Current-state (audit-confirmed):** `modules/context-gate/routes.ts:87–110` `/switch` only logs via `service.ts:432 logContextSwitch`; no membership/eligibility gate; `CROSS_CONTEXT_DENIED` not present anywhere. Membership-aware logic exists but is not invoked by `/switch`.

**Target-state requirements:**
- **URS-39-WP1-01 (MUST):** The pilot **shall** disable the scope-switch UI and enforce a single active scope per tenant; cross-scope switching is not part of pilot intended use.
- **URS-39-WP1-02 (MUST):** RLS **shall** be confirmed enabled on every in-scope table.
- **URS-39-WP1-03 (MUST):** A **tenant/site isolation test report (P6)** **shall** evidence that out-of-scope read/act is denied at API and DB.
- **URS-39-WP1-04 (SHOULD, Phase-2):** Full eligibility validation on `/switch` (deny ineligible with `CROSS_CONTEXT_DENIED`, persist + audit).

**Acceptance:** `AC-39-WP1-1` scope-switch disabled in pilot build; `AC-39-WP1-2` RLS present on in-scope tables (grep gate green); `AC-39-WP1-3` P6 isolation report attached.

**Tests:** `TC-39-WP1-1` cross-tenant read denied at DB (RLS); `TC-39-WP1-2` scope-switch route unavailable/locked in pilot; `TC-39-WP1-3` P6 report covers all in-scope tables.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo, branch off dev-vimal-audit-2. GAMP5 Cat5. CLAUDE.md + Shared gate.
TASK (WP-1, pilot lock): Disable scope-switch UI; enforce single active scope; confirm RLS on all in-scope tables; produce the P6 isolation test.
FILES: modules/context-gate/routes.ts:87-110 (/switch), service.ts:432 (logContextSwitch). Frontend scope-switch control.
DO: gate/disable /switch for the pilot tenant; assert single active scope; add a test that cross-tenant read is denied at DB level (RLS). Do NOT build full eligibility enforcement (Phase 2).
ACCEPTANCE: AC-39-WP1-1/2/3. TESTS: TC-39-WP1-1..3. Run gate (RLS-coverage check must be empty).
```

---

### WP-5 — Audit-chain verification coverage  ·  Priority: SHOULD (deferrable w/ documented risk)  ·  Risk: MEDIUM
**Parent URS:** URS-35 / URS-06 (#95). **GxP domain:** Data integrity / Part 11 §11.10(e).

**Why.** The on-demand `verifyRange` API covers only `audit_log`; `auth_audit_log` and `failed_operation_log` throw "not implemented." (They ARE covered by the async checkpoint job, so tamper-evidence exists — only the sync API is incomplete.)

**Current-state (audit-confirmed):** `modules/audit-log/service.ts:272 verifyRange` throws for `logTable != 'audit_log'` (`:278–285`); async coverage exists via `jobs/audit-integrity-checkpoint.job.ts` + `jobs/audit-checkpoint-table-specs.ts:8–13` (audit_log, auth_audit_log, failed_operation_log, authority_change_log).

**Target-state requirements:**
- **URS-39-WP5-01 (SHOULD):** The system **shall** implement `verifyRange` for `auth_audit_log` and `failed_operation_log` so the whole audit substrate is tamper-verifiable on demand.

**Acceptance:** `AC-39-WP5-1` `verifyRange` returns a valid/invalid result for every audit-bearing table. **Tests:** `TC-39-WP5-1` `verifyRange` returns valid/invalid for `auth_audit_log` and `failed_operation_log`. **Pilot note:** deferrable with documented risk + CAPA since the checkpoint job already provides tamper-evidence.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo. CLAUDE.md + Shared gate.
TASK (WP-5, deferrable): Implement verifyRange for auth_audit_log and failed_operation_log.
FILES: modules/audit-log/service.ts:272-285 (throws today). Mirror the audit_log range-verify logic; reuse jobs/audit-checkpoint-table-specs.ts table specs.
ACCEPTANCE: AC-39-WP5-1. If deferred to Phase 2, attach documented risk acceptance + CAPA (checkpoint job covers tamper-evidence meanwhile).
```

---

### WP-6 — Document Control / SOP core  ·  Priority: MUST (IN SCOPE — COMMITTED)  ·  Risk: HIGH (record integrity)
**Parent URS:** URS-12 §21/§22/§23 (DOC-020…040). **GxP domain:** GDocP / Part 11.

**Why.** The lifecycle spine works, but **authored content is dropped** today — a document-control system cannot lose content. Pilot core = persist+hash content, distribution + read-and-understood acknowledgment, training linkage on effective. (Word round-trip, inline redline, 4 entry points, periodic-review automation → Phase 2.)

**Current-state (audit-confirmed):** approve/effective/supersede/retire are e-sign + authority + SoD gated (`documents/routes.ts (approve ~516, effective ~607, supersede ~817, retire ~721)`) — KEEP. Authored content dropped at `DocumentAuthoring.tsx:31`. `withdrawn` state missing from `documents/lifecycle.ts`.

**Target-state requirements:**
- **URS-39-WP6-01 (MUST):** The system **shall** persist authored document content and compute a content hash on save; content shall be retrievable and version-bound.
- **URS-39-WP6-02 (MUST):** On `effective`, the system **shall** notify the configured distribution audience (in-app + email) and capture **read-and-understood acknowledgment** (DOC-028–033), each acknowledgment attributable + timestamped.
- **URS-39-WP6-03 (training-assignment evidence = MUST; automated trigger = SHOULD/Phase 2):** On `effective`, a training assignment **shall** be created/recorded for the audience. **Training-assignment evidence is MUST for effective SOPs; the automated trigger engine is SHOULD (Phase 2).** Manual assignment is acceptable **only if attributable, timestamped, and captured in G-7 evidence.**
- **URS-39-WP6-04 (SHOULD):** A signed **withdraw** transition for drafts (`withdrawn` state, DOC-026).

**Acceptance:** `AC-39-WP6-1` author content → persisted + hashed + retrievable; `AC-39-WP6-2` on effective the right audience is notified and acknowledges (attributable); `AC-39-WP6-3` existing approve/effective/supersede/retire gates unchanged.

**Tests:** `TC-39-WP6-1` content persists+hashes; `TC-39-WP6-2` acknowledgment captured with user+timestamp; `TC-39-WP6-3` effective triggers training; `TC-39-WP6-4` tenant isolation + audit on each mutation.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo, branch off dev-vimal-audit-2. GAMP5 Cat5. CLAUDE.md + Shared gate.
TASK (WP-6 core): Persist + hash authored document content (today dropped at DocumentAuthoring.tsx:31); add distribution audience + read-and-understood acknowledgment (DOC-028-033); trigger training on effective.
KEEP: documents/routes.ts (approve ~516, effective ~607, supersede ~817, retire ~721) (approve/effective/supersede/retire e-sign+authority+SoD).
MIGRATIONS: document_versions.content persistence + hash; document_distribution_rules / document_distributions / document_acknowledgments / document_type_ack_policy. Each: idempotent, RLS-on, -- ROLLBACK:, audit.
DEFER (Phase 2): Word round-trip, inline redline, 4 entry points, periodic review, withdrawn state may be SHOULD.
ACCEPTANCE: AC-39-WP6-1/2/3. TESTS: TC-39-WP6-1..4. VERIFY line numbers. Run gate.
```

---

### WP-7 — Deviation  ·  Priority: MUST (IN SCOPE — COMMITTED)  ·  Risk: HIGH
**Parent URS:** URS-16 §21. **GxP domain:** GMP.

**Why.** Closure controls are solid; pilot adds critical-tier executive co-sign. **Decision (Option A): critical deviations ARE included in Phase-2 verification scope** — the co-sign is mandatory and shall be tested, with at least one critical deviation in the verification dataset. Reopen is **out of pilot intended use** (raise a new record).

**Current-state (audit-confirmed, KEEP):** root-cause-required-to-close (`deviations/service.ts:595–600`), severity-gated mandatory CAPA (`:622–637`), mandatory closure e-sig (`:646–649`), SoD reporter≠closer (`:616–618`). Reopen blocked (`:588`); single `final_quality_approver` snapshot (`:683–702`).

**Target-state requirements:**
- **URS-39-WP7-01 (MUST):** Critical deviations are **in Phase-2 verification scope**. Closure of a critical deviation **shall** require executive-authority co-sign **in addition to** the quality approver, each a substrate-verified e-sig (WP-4). At least one critical deviation **shall** be included in the verification dataset.
- **URS-39-WP7-02 (MUST):** Existing closure gates (root-cause, severity-gated CAPA, closure e-sig, SoD) **shall** remain intact (regression).
- **URS-39-WP7-03 (Out of scope):** Governed reopen — **not** in pilot intended use; a superseding new deviation is raised instead.

**Acceptance:** `AC-39-WP7-1` critical closure requires exec co-sign (verified); `AC-39-WP7-2` all existing gates pass regression.

**Tests:** `TC-39-WP7-1` critical closure without co-sign → blocked; `TC-39-WP7-2` existing gates regression; `TC-39-WP7-3` co-sign e-sig verified vs substrate.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo. CLAUDE.md + Shared gate.
TASK (WP-7): Add critical-tier executive co-sign on deviation closure (substrate-verified e-sig per WP-4). Reopen is OUT of pilot scope.
KEEP: deviations/service.ts:595 (root cause to close), :622 (severity-gated CAPA), :646 (closure e-sig), :616 (SoD). Today single final_quality_approver snapshot at :683.
DO: for critical severity, require a second executive co-sign; both verified vs electronic_signatures.
ACCEPTANCE: AC-39-WP7-1/2. TESTS: TC-39-WP7-1..3. VERIFY lines. Run gate.
```

---

### WP-8 — RCA  ·  Priority: MUST (IN SCOPE — COMMITTED)  ·  Risk: HIGH
**Parent URS:** URS-17 §21. **GxP domain:** GMP.

**Why.** Strong record; approve e-sig isn't substrate-verified and the event-driven CAPA handoff has no consumer (a manual `linkCapaToRca` exists).

**Current-state (audit-confirmed, KEEP):** lifecycle + SoD (`rca/service.ts:1029`), mandatory-CAPA-at-close (`:1041–1063`), child-iteration reopen (`:910`), manual `linkCapaToRca` (`:1473`). Gap: approve/reject store `esig_id` unverified (`:786`); `rca_conclusion_created`/`rca_capa_linked` emitted, no consumer.

**Target-state requirements:**
- **URS-39-WP8-01 (MUST):** Approve/reject **shall** require a substrate-verified e-sig + authority (WP-4).
- **URS-39-WP8-02 (MUST):** Closing an RCA **shall** produce a linked CAPA — via the existing `linkCapaToRca` action or the WP-2 consumer of `rca_conclusion_created`.

**Acceptance:** `AC-39-WP8-1` approve/reject need verified e-sig + authority; `AC-39-WP8-2` closing an RCA yields a linked CAPA.

**Tests:** `TC-39-WP8-1` unverified esig on approve → rejected; `TC-39-WP8-2` close → CAPA linked; `TC-39-WP8-3` SoD creator≠approver.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo. CLAUDE.md + Shared gate.
TASK (WP-8): Substrate-verify RCA approve/reject e-sig (WP-4 pattern); ensure closing an RCA creates/links a CAPA.
FILES: rca/service.ts approveRCA/rejectRCA (~L786 store esig_id unverified); reuse linkCapaToRca (:1473) or wire rca_conclusion_created consumer (WP-2).
KEEP: lifecycle+SoD (:1029), mandatory-CAPA-at-close (:1041), child-iteration reopen (:910).
ACCEPTANCE: AC-39-WP8-1/2. TESTS: TC-39-WP8-1..3. VERIFY lines. Run gate.
```

---

### WP-9 — CAPA  ·  Priority: MUST (IN SCOPE — COMMITTED)  ·  Risk: HIGH
**Parent URS:** URS-18 §21. **GxP domain:** GMP.

**Why.** Best lifecycle in the platform; the effectiveness core is under-built — effectiveness determination isn't e-signed, and closure isn't blocked by open action items.

**Current-state (audit-confirmed, KEEP):** 8-state lifecycle (`capas/workflow.ts:6–13`), rework loop (`:27`), SoD (`capas/service.ts:207/320/394`), closure e-sig (`:416–419`). 3-way effectiveness outcome already exists (`completeEffectivenessCheck :557`). Gaps: `verified` transition has no e-sig (`:394–415`); closure blocks only on cascades (`:424–434`), **not** `capa_action_items`.

**Target-state requirements:**
- **URS-39-WP9-01 (MUST):** The effectiveness determination (`effectiveness_check → verified`) **shall** require a substrate-verified e-sig.
- **URS-39-WP9-02 (MUST):** Closure **shall** be blocked while any `capa_action_items` is open (`CAPA_OPEN_ACTIONS`).

**Acceptance:** `AC-39-WP9-1` effectiveness determination is e-signed; `AC-39-WP9-2` a CAPA with open action items cannot close.

**Tests:** `TC-39-WP9-1` verify transition without esig → blocked; `TC-39-WP9-2` close with open action item → `CAPA_OPEN_ACTIONS`; `TC-39-WP9-3` regression on 8-state lifecycle + SoD.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo. CLAUDE.md + Shared gate.
TASK (WP-9): E-sign the effectiveness determination (verified transition); block closure while any capa_action_items is open (CAPA_OPEN_ACTIONS).
FILES: capas/service.ts verified transition (:394-415, today SoD+result only); closure gate (:424-434, blocks on capa_cascade_items only — extend to capa_action_items). 3-way outcome already exists at :557 (do not rebuild).
KEEP: 8-state lifecycle (workflow.ts:6-13), rework loop (:27), SoD (:207/320/394), closure e-sig (:416).
ACCEPTANCE: AC-39-WP9-1/2. TESTS: TC-39-WP9-1..3. VERIFY lines. Run gate.
```

---

### WP-10 — Findings → CAPA mandatory gate  ·  Priority: MUST (IN SCOPE — COMMITTED, pulled to W7)  ·  Risk: HIGH
**Parent URS:** URS-21 §21. **GxP domain:** GMP. **Dependency note:** WP-12 inspection export depends on the observation→finding→CAPA chain this emits → build by **W7**.

**Why.** A major/critical finding can currently close with **zero** CAPA; the findings module has no CAPA reference at all.

**Current-state (audit-confirmed):** `findings/service.ts transitionStatus:559–675` enforces workflow validity + authority gate for major/critical (`:596–615`) but **never** checks for a linked CAPA; module-wide grep for `capa` = zero matches.

**Target-state requirements:**
- **URS-39-WP10-01 (MUST):** Closure of a major/critical finding **shall** be blocked without a linked acceptable CAPA.
- **URS-39-WP10-02 (MUST):** The system **shall** emit `finding_capa_linked`; inspection observations **shall** emit `inspection_observation_finding_created` (WP-2).
- **URS-39-WP10-03 (MUST):** Because **closing OR deferring** a major/critical finding is a **GxP disposition** (Option A — a deferral delays remediation and is regulated), that **disposition (close or defer)** **shall** require a **substrate-verified e-signature** (WP-4) in addition to the existing authority gate (`finding_disposition:<severity>`); for **closure**, the linked-CAPA gate also applies. *(Rationale: per the tightened global e-sign rule §0.4(2), a regulated disposition requires e-signature verification; authority gate + CAPA linkage alone is insufficient for a major/critical disposition. If QA formally determines authority+CAPA is sufficient for the pilot, that determination shall be documented as a risk-accepted deviation.)*

**Acceptance:** `AC-39-WP10-1` major/critical finding can't close without a CAPA; `AC-39-WP10-2` observation→finding→CAPA chain flows; `AC-39-WP10-3` major/critical finding **closure or defer** requires a substrate-verified e-signature (or a documented QA risk-acceptance).

**Tests:** `TC-39-WP10-1` major finding close with no CAPA → blocked; `TC-39-WP10-2` observation→finding→CAPA flow; `TC-39-WP10-3` minor finding unaffected; `TC-39-WP10-4` major/critical close without e-sign → blocked; `TC-39-WP10-5` forged/cross-tenant e-sig → rejected (`ESIG_VERIFICATION_FAILED`); `TC-39-WP10-6` major/critical **defer** without substrate-verified e-signature → blocked.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo. CLAUDE.md + Shared gate. PRIORITY: build by W7 (WP-12 depends on it).
TASK (WP-10): Block closure of major/critical findings without a linked acceptable CAPA; emit finding_capa_linked + inspection_observation_finding_created. AND add a substrate-verified e-signature to BOTH major/critical close AND defer (both are GxP dispositions, Option A) — withAuthority({requiresEsign:true}) + validateEsignatureForRecord (WP-4 pattern). Any deviation from this requires a documented QA risk-acceptance.
FILES: findings/service.ts transitionStatus:559-675 (close/defer path; authority gate at :596-615 covers close+defer for major/critical; no capa check today). MIGRATION: finding_capa_links (idempotent, RLS, -- ROLLBACK:, audit).
ACCEPTANCE: AC-39-WP10-1/2/3. TESTS: TC-39-WP10-1..6 (incl. close-without-e-sign blocked, forged-e-sig rejected, defer-without-e-sign blocked). VERIFY lines. Run gate.
```

---

### WP-12 — Inspection Readiness Evidence Pack export (the only 🔴)  ·  Priority: MUST (IN SCOPE — COMMITTED, front-loaded W7)  ·  Risk: HIGH
**Parent URS:** URS-22 §22 (BR-22-EXP-01/02, BR-22-ESC-01). **GxP domain:** GMP / inspection readiness. **Build:** +1 build hand (ring-fenced here). **Dependency:** WP-2 + WP-10.

**Why.** Selection/disposition/scorecard/e-signed close exist, but the **export — the deliverable — does not** (no hashing, no package).

**Current-state (audit-confirmed, KEEP):** `inspection-readiness/routes.ts` has selection/disposition/scorecard + e-signed close (`/:id/close` with `withAuthority requiresEsign:true`, `:183–189`). **No export route; no SHA-256/manifest/watermark/package code.**

**Target-state requirements:**
- **URS-39-WP12-01 (MUST):** The system **shall** expose `GET /inspection-readiness/:id/export` producing a controlled package (selected evidence + dispositions + scorecard).
- **URS-39-WP12-02 (MUST):** The package **shall** carry per-artifact + package **SHA-256** integrity hashes, a manifest, and a watermark; export shall be access-controlled and audited; JSON + PDF.
- **URS-39-WP12-03 (MUST):** Re-export of the same disposition set **shall** reproduce the same hash (reproducibility).
- **URS-39-WP12-04 (MUST):** Observation→finding (WP-10) and commitment→CAPA emission **shall** be wired.

**Acceptance:** `AC-39-WP12-1` one action → hash-verified inspector-ready package; `AC-39-WP12-2` re-export reproduces the hash; `AC-39-WP12-3` export audited + access-controlled.

**Tests:** `TC-39-WP12-1` export produces package + hashes; `TC-39-WP12-2` re-export hash identical; `TC-39-WP12-3` unauthorized export denied + audited; `TC-39-WP12-4` PDF + JSON render.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo, branch off dev-vimal-audit-2. GAMP5 Cat5. CLAUDE.md + Shared gate. OWNER: +1 build hand (bounded, new endpoint). PDF LIB: use the Week-1 decision (shared with WP-13).
TASK (WP-12): Build GET /inspection-readiness/:id/export -> controlled package (evidence + dispositions + scorecard) with per-artifact + package SHA-256, manifest, watermark; access-controlled + audited; JSON + PDF; reproducible hash on re-export.
KEEP: inspection-readiness/routes.ts:183-189 selection/disposition/scorecard/e-signed close.
WIRE: observation->finding (WP-10) + commitment->CAPA emission (WP-2). MIGRATION: export package + integrity manifest tables (idempotent, RLS, -- ROLLBACK:, audit).
ACCEPTANCE: AC-39-WP12-1/2/3. TESTS: TC-39-WP12-1..4 (incl. reproducible-hash + unauthorized-export-denied). VERIFY lines. Run gate.
```

---

### WP-11 — Training trigger + qualification gate  ·  Priority: SHOULD (pilot: manual acceptable)  ·  Risk: MEDIUM
**Parent URS:** URS-28 §21. **GxP domain:** GDocP / training.

**Why.** Trigger engine is dormant (inert config rows); no personnel qualification gate API. For the pilot, **manual training assignment + manual read-ack is acceptable**; auto-trigger engine → Phase 2.

**Current-state (audit-confirmed):** `training/service.ts createTrigger:773–820` only INSERTs a `training_triggers` config row (read by nothing); module has no `eventBus.on/emit`; no `document_effective` consumer; no `/training/qualification` personnel gate.

**Target-state requirements:**
- **URS-39-WP11-01 (training-assignment evidence MUST; automated trigger engine SHOULD/Phase 2):** On SOP `effective`, a training assignment **shall** be created/recorded for the audience. **For Phase 1, training-assignment evidence is MUST for effective SOPs; the automated trigger engine is SHOULD/Phase 2.** Manual assignment is acceptable only if **attributable, timestamped, and captured in G-7**.
- **URS-39-WP11-02 (COULD, Phase-2):** `GET /training/qualification` gate API blocking unqualified users at execution gates.

**Acceptance:** `AC-39-WP11-1` SOP-effective produces a training assignment for the right population (manual path acceptable + attributable + timestamped + in G-7). **Tests:** `TC-39-WP11-1` SOP-effective creates an attributable, timestamped training assignment captured as evidence.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo. CLAUDE.md + Shared gate.
TASK (WP-11, pilot-light): On SOP effective, create training assignments for the audience (manual assignment acceptable; do NOT build the full auto-trigger engine for pilot). Qualification gate API = Phase 2.
FILES: training/service.ts createTrigger:773-820 (inert config rows today). Link to WP-2 document_effective consumer.
ACCEPTANCE: AC-39-WP11-1. Run gate.
```

---

### WP-13 — MIRA guardrails + AI Governance Evidence Pack PDF  ·  Priority: MUST (IN SCOPE — COMMITTED, front-loaded W7)  ·  Risk: HIGH (AI governance)
**Parent URS:** URS-32 §22 (BR-32-TRIO/EXP/GUARD). **GxP domain:** AI / CSV. **Dependency:** WP-13b. **Verification:** starts W8/W9 (as guardrails land) → W12.

**Why.** Strong already; finish the PDF export and turn four declared safety checks into **enforced** ones.

**Current-state (audit-confirmed, KEEP):** gateway chokepoint, validated-model gate, RAG provenance, class-driven HITL handover, accept/reject, audit logging, `bypass-ai`. JSON evidence-pack export done. Guardrails **declared, not enforced**.

**Target-state requirements:**
- **URS-39-WP13-01 (MUST):** The AI Governance Evidence Pack **shall** export as **PDF** (JSON exists).
- **URS-39-WP13-02 (MUST):** Four guardrails **shall** be enforced: `AI_GATEWAY_MODEL_UNQUALIFIED` (hard-block), `AI_GATEWAY_CHOKEPOINT_BYPASSED` (detection), `MIRA_HUMAN_ON_LOOP_QUALIFICATION_GATE_FAILED` (gate), and a dead-letter queue (DLQ) for failures.
- **URS-39-WP13-03 (MUST):** The governed-AI trio surfaces (ask-your-QMS, review-assist, AI-draft) **shall** be labelled "AI-generated", logged, and human-accepted before any record write.

**Acceptance:** `AC-39-WP13-1` unqualified model blocked; `AC-39-WP13-2` gateway-bypass detected + DLQ catches failures; `AC-39-WP13-3` evidence pack exports JSON + PDF; `AC-39-WP13-4` trio surfaces labelled + logged + human-accepted.

**Tests:** `TC-39-WP13-1` unqualified model → hard-block; `TC-39-WP13-2` chokepoint bypass detected; `TC-39-WP13-3` DLQ catches a failing inference; `TC-39-WP13-4` AI draft cannot write to a GxP field without human accept; `TC-39-WP13-5` PDF export renders.

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo, branch off dev-vimal-audit-2. GAMP5 Cat5. CLAUDE.md + Shared gate. AI Owner + build hand. PDF LIB = Week-1 decision (shared with WP-12). Depends on WP-13b.
TASK (WP-13): Export AI Governance Evidence Pack as PDF; ENFORCE 4 guardrails (AI_GATEWAY_MODEL_UNQUALIFIED hard-block, AI_GATEWAY_CHOKEPOINT_BYPASSED detection, MIRA human-on-loop gate, DLQ); surface the governed-AI trio (labelled + logged + human-accepted).
KEEP: gateway chokepoint, validated-model gate (Mig 227), RAG provenance, class-driven HITL, accept/reject, audit logging, bypass-ai.
CONSTRAINT: AI advisory only; never writes to a GxP field without human accept; never generative AI in a critical GMP decision.
ACCEPTANCE: AC-39-WP13-1..4. TESTS: TC-39-WP13-1..5 (incl. AI-cannot-write-without-accept). Run gate (no-LLM-in-critical check).
```

---

### WP-14 — Quality / Inspection-Readiness Scorecard (differentiator)  ·  Priority: SHOULD (read-only; not a sign-off blocker)  ·  Risk: LOW
**Parent URS:** URS-38 (AN-001…010). **GxP domain:** Reporting (read-only).

**Why.** Backend analytics are rich; the pilot needs the frontend readiness-scorecard view. **Read-only — no GxP writes.**

**Current-state (audit-confirmed, REUSE):** `dashboard` backend rich (executive/tactical/operational, KPI engine, trends, benchmarks, alerts, export).

**Target-state requirements:**
- **URS-39-WP14-01 (SHOULD):** A frontend readiness-scorecard **shall** render live, scope/tenant-isolated pilot data with an aggregate Inspection-Readiness score (AN-003) + drill-down, and a read-ack % KPI (AN-007, depends on WP-6 DOC-033). **No write path to GxP tables (AN-010).**

**Acceptance:** `AC-39-WP14-1` scorecard renders scoped data; readiness score reproducible from documented inputs; no GxP write path. **Tests:** `TC-39-WP14-1` scorecard renders scope/tenant-isolated data + reproducible score + asserts no write path to GxP tables (read-only).

**🤖 Claude Code Handoff Block:**
```
CONTEXT: Verixa repo. CLAUDE.md + Shared gate.
TASK (WP-14, read-only differentiator): Frontend readiness-scorecard reusing the dashboard backend; aggregate Inspection-Readiness score (AN-003) + drill-down + read-ack % (AN-007). NO write path to GxP tables (AN-010).
ACCEPTANCE: AC-39-WP14-1. Run gate. (Deferrable — not a sign-off blocker.)
```

---

### MIRA-V7 — AI provider assurance (governance, not a code WP)  ·  Priority: MUST (non-delegable)  ·  Risk: HIGH
**Parent URS:** URS-32 §22. **Owner:** AI Owner (+QA). **Not a Claude-Code build task** — it is the governance/evidence pack Verixa (EU AI Act **provider**) must produce; engineers supply the technical hooks (WP-13/WP-13b).

**Target-state requirements:**
- **URS-39-V7-01 (MUST):** A documented **AI intended-use + prohibited-use** statement for MIRA (advisory NLQ over QMS, review-assist, drafting; prohibited: approve/close/sign/dispose, write-to-GxP-field-without-accept, any critical GMP decision, cross-tenant retrieval).
- **URS-39-V7-02 (MUST):** **EU AI Act provider position** (limited-risk/advisory) + GPAI dependency on Anthropic/Azure noted; human-in-the-loop oversight model.
- **URS-39-V7-03 (MUST):** **Acceptance thresholds** set by the AI Owner (grounding/citation rate, hallucination ceiling, acceptance-rate floor, low-confidence escalation) — `Unknown — evidence required` until set.
- **URS-39-V7-04 (MUST):** Version control (model/prompt/retrieval/guardrail) + monitoring + AI change-control + test coverage (hallucination, prompt-injection, wrong-tenant negatives) + the §36 readiness gate before go-live.

**Acceptance:** `AC-39-V7-1` thresholds defined and met on the test corpus; `AC-39-V7-2` hallucination/prompt-injection/wrong-tenant negatives blocked; `AC-39-V7-3` every inference logged (WP-13b); `AC-39-V7-4` readiness gate passes. **Tests:** `TC-39-V7-1` thresholds met on the test corpus; `TC-39-V7-2` hallucination/prompt-injection/wrong-tenant negatives all blocked; `TC-39-V7-3` every inference produces an immutable audit record; `TC-39-V7-4` §36 readiness gate passes before go-live. **Handoff:** CSV/CSA (validation strategy), Validation Test Architect (AI test cases), Data Integrity (audit-event adequacy), Supplier Quality (Anthropic/Azure), Security/Privacy.

---

## 3B. Functional Specification (FS-39)

> **FS = what the system shall functionally do** to satisfy each URS-39 requirement (behaviour, inputs, outputs, errors). Traces URS→FS. Owned by URS/Product. One FS row per requirement family.

| FS ID | Traces URS-39 | Functional behaviour (shall) | Preconditions / inputs | Postconditions / outputs | Error / exception behaviour |
|---|---|---|---|---|---|
| FS-39-WP4 | WP4-01..03 | On any approval/closure/disposition, read the supplied signature from the e-sig substrate, verify signer=actor, entity binding, meaning=approved, freshness; transition only if valid; persist bound reference | Authenticated actor; `signature_id`; target record in signable state | Record transitions; bound `electronic_signatures` reference stored; audit event | Invalid/forged/expired/cross-tenant → `ESIG_VERIFICATION_FAILED` 4xx; no mutation; audit event written |
| FS-39-WP13b | WP13b-01..03 | In regulated mode, refuse to construct/invoke the AI gateway without an audit sink; write the immutable LLM audit record before returning; fail the request if the audit write fails | Regulated-mode flag true; inference request | Inference returns only after audit record persisted (model, version, input hash, output, confidence, userId, accept/reject) | No audit sink → construction/request fails; audit write throws → request fails; dev mode documented |
| FS-39-WP2 | WP2-01..03 | For each in-scope domain event, invoke its consumer (notify/assign/link); emit + consume new finding/observation linkage events | In-scope event emitted | Notification/action created; CAPA/finding linked; coverage test passes for in-scope events | Missing consumer for an in-scope event → coverage test fails |
| FS-39-WP1 | WP1-01..04 | Enforce a single active scope; reject/disable scope-switch; enforce RLS on every read/write | Single-tenant pilot config | Out-of-scope read/act denied at API + DB; P6 report produced | Scope-switch attempt → unavailable/denied (pilot); Phase-2: `CROSS_CONTEXT_DENIED` + audit |
| FS-39-WP5 | WP5-01 | On-demand range verification returns valid/invalid for every audit-bearing table | `logTable`, range | Tamper status per table | Unsupported table no longer throws (implemented) |
| FS-39-WP6 | WP6-01..04 | Persist + hash authored content; on effective, notify audience + capture read-ack; trigger training | Document in authoring/effective transition | Content persisted+hashed+retrievable; acknowledgments (user+timestamp); training assignments | Save failure → no version commit; ack by non-audience rejected |
| FS-39-WP7 | WP7-01..02 | For critical deviations, require executive co-sign (verified) in addition to quality approver on closure | Critical deviation ready to close | Closure only after both verified signatures | Missing co-sign → closure blocked; existing gates unchanged |
| FS-39-WP8 | WP8-01..02 | Verify approve/reject e-sig vs substrate; on close, create/link a CAPA | RCA in approvable/closeable state | Verified approval; linked CAPA on close | Unverified esig → rejected; close without CAPA path → CAPA created or `CAPA_REQUIRED` |
| FS-39-WP9 | WP9-01..02 | Require e-sig on effectiveness determination; block closure while any action item open | CAPA in effectiveness_check/closeable | Verified `verified` transition; closure only when action items terminal | Unsigned verify → blocked; open action item on close → `CAPA_OPEN_ACTIONS` |
| FS-39-WP10 | WP10-01..03 | Block major/critical finding **closure** without linked acceptable CAPA + verified e-sig; block major/critical **defer** without verified e-sig; emit linkage events | Major/critical finding ready to close or defer; signature_id | Closure only with linked CAPA + verified e-sig; defer only with verified e-sig; `finding_capa_linked` emitted | No CAPA → close blocked; missing/invalid e-sig (close or defer) → `ESIG_VERIFICATION_FAILED`; minor unaffected |
| FS-39-WP12 | WP12-01..04 | Build a controlled inspection package (evidence+dispositions+scorecard) with per-artifact + package SHA-256, manifest, watermark; JSON+PDF; reproducible | Inspection record with selections/dispositions | Hash-verified package; identical hash on re-export; export audited + access-controlled | Unauthorized export denied + audited; render failure surfaced |
| FS-39-WP11 | WP11-01..02 | On SOP effective, create training assignment for audience (manual acceptable for pilot) | SOP effective event | Training assignment(s) created | Pilot: manual path acceptable + evidenced |
| FS-39-WP13 | WP13-01..03 | Export AI Governance Pack PDF; enforce 4 guardrails; surface labelled, logged, human-accepted AI trio | MIRA enabled; WP-13b active | Unqualified model blocked; bypass detected; DLQ catches failures; pack JSON+PDF; AI write needs human accept | Guardrail breach blocked + logged; AI cannot write GxP field without accept |
| FS-39-WP14 | WP14-01 | Render read-only readiness scorecard with aggregate score + drill-down + read-ack % | Dashboard backend; scoped data | Scorecard renders; score reproducible | No write path to GxP tables |
| FS-39-V7 | V7-01..04 | MIRA operates advisory under documented intended/prohibited use, EU-AI-Act provider position, thresholds, version control, monitoring | MIRA provider pack | Thresholds met; negatives blocked; every inference logged; readiness gate passes | Below threshold → escalate; prohibited action → blocked |

---

## 3C. Design Specification (DS-39) — Proposed design, requires review

> **DS = how it is designed/built** (files, services, migrations, endpoints, components). Authored under the **Product/Engineering Architect** seat. Every DS row is **`Proposed design — requires engineering review`**; control-domain adequacy is approved by the specialist owner (Data Integrity for audit/e-sig/records, AI Expert for AI governance, Security for isolation, CSV/CSA for validation). Line numbers are audit-observed (2026-05-31) and **must be re-confirmed at build**. (The per-WP 🤖 Handoff Blocks in §3 are the paste-ready form of this DS.)

| DS ID | Traces FS | Design element(s) (file / endpoint / migration / component) | Proposed change | Reference pattern to copy | Data / record |
|---|---|---|---|---|---|
| DS-39-WP4 | FS-39-WP4 | `change-control/service.ts` approveChange(~L964)+closeChangeRequest(~L1526); `rca/service.ts` approveRCA/rejectRCA(~L786); `batch/service.ts`(~L256) | Route through `hitl/esig.service.ts:650 validateEsignatureForRecord`; write bound row; remove batch optional bypass(~L297) | `oos-oot/service.ts:709–733`; `document-quality-gateway/service.ts:72–94` | `electronic_signatures` (read+bind); no schema add |
| DS-39-WP13b | FS-39-WP13b | `ai/ai-gateway.service.ts`(L100 ctor, L228+L429 logging); `gdp/plugin.ts:92`, `document-library/plugin.ts:32`, `hardening/plugin.ts:155` | Make `llmAudit` required in regulated mode (typed config flag, fail-fast `core/config.ts` pattern); fail request on audit-write failure; wire 3 plugins | `core/config.ts` fail-fast no-unsafe-default | `llm_audit_log` (hash chain), `ai_requests` |
| DS-39-WP2 | FS-39-WP2 | `core/event-bus.ts`; `notifications/event-subscriber.ts`; `config/workflow-auto-spawn.subscriber.ts` | Add consumers for in-scope linkage events; emit+consume `finding_capa_linked`, `inspection_observation_finding_created`; add in-scope coverage test | `workflow-auto-spawn.subscriber.ts` TRIGGER_MAP; `rca/service.ts:1473 linkCapaToRca` | event types in `event-bus.ts` |
| DS-39-WP1 | FS-39-WP1 | `context-gate/routes.ts:87–110` (/switch), `service.ts:432`; FE scope-switch control; in-scope table migrations | Disable/gate /switch; assert single scope; confirm RLS on in-scope tables; author P6 test | membership logic in `context-gate/service.ts:266–273` | RLS policies (no new table) |
| DS-39-WP5 | FS-39-WP5 | `audit-log/service.ts:272–285 verifyRange` | Implement range-verify for `auth_audit_log`, `failed_operation_log` | `jobs/audit-checkpoint-table-specs.ts:8–13` | audit log tables (read) |
| DS-39-WP6 | FS-39-WP6 | `DocumentAuthoring.tsx:31`; `documents/lifecycle.ts`; new migrations | Persist+hash content; distribution+ack tables; training trigger on effective | `documents/routes.ts (approve ~516, effective ~607, supersede ~817, retire ~721)` (keep gates) | `document_versions.content`+hash; `document_distributions`/`document_acknowledgments`/`document_distribution_rules`/`document_type_ack_policy` |
| DS-39-WP7 | FS-39-WP7 | `deviations/service.ts` closure (~L683 snapshot) | Add critical-tier exec co-sign; both verified (WP-4) | `oos-oot:709–733` (verify); existing snapshot logic | bound co-sign signatures (migration) |
| DS-39-WP8 | FS-39-WP8 | `rca/service.ts` approve/reject(~L786), `linkCapaToRca:1473` | Substrate-verify e-sig; ensure CAPA link on close | WP-4 verifier; existing `linkCapaToRca` | RCA→CAPA link |
| DS-39-WP9 | FS-39-WP9 | `capas/service.ts` verified transition(:394–415), closure gate(:424–434) | E-sig on verified; extend close gate to `capa_action_items` | existing closure e-sig(:416); `completeEffectivenessCheck:557` (3-way, keep) | `capa_action_items` completeness; verified e-sig col |
| DS-39-WP10 | FS-39-WP10 | `findings/service.ts transitionStatus:559–675`; new link migration | CAPA-required gate for major/critical; **add `withAuthority({requiresEsign:true})` on close/defer + `validateEsignatureForRecord` (WP-4)**; emit linkage events | authority gate at `:596–615`; e-sig ref `oos-oot:710–733` | `finding_capa_links` (migration); bound `electronic_signatures` ref |
| DS-39-WP12 | FS-39-WP12 | `inspection-readiness/routes.ts` (add `GET /:id/export`); new package/manifest migration; PDF lib (W1 decision) | Build export → package + per-artifact+package SHA-256 + manifest + watermark; JSON+PDF; reproducible; wire WP-10/WP-2 emission | e-signed close at `:183–189` (keep); shared PDF approach with WP-13 | export package + integrity manifest tables |
| DS-39-WP11 | FS-39-WP11 | `training/service.ts createTrigger:773–820`; WP-2 `document_effective` consumer | Create training assignment on effective (manual acceptable) | — | `training_triggers`/assignment read model |
| DS-39-WP13 | FS-39-WP13 | AI gateway guardrail paths; AI-evidence-pack export; trio UX components; DLQ | Enforce 4 guardrails; PDF export; labelled+logged+human-accepted trio | gateway chokepoint, validated-model gate (Mig 227), RAG provenance, HITL (keep) | guardrail-event tables + DLQ; AI pack PDF |
| DS-39-WP14 | FS-39-WP14 | dashboard backend (reuse); new FE scorecard view | Read-only scorecard; aggregate score + drill-down + read-ack % | `dashboard` backend (executive/tactical/operational, KPI engine) | read-side model only (no GxP write) |
| DS-39-V7 | FS-39-V7 | (governance, not code) provider pack; consumes WP-13/WP-13b hooks | Document IU/PU, EU-AI-Act provider position, thresholds, monitoring, change-control | URS-32 §22 | `ai_model_config`/`model_registry`, `llm_audit_log` |

**Architect note:** DS rows are proposals to accelerate the Claude Code handoff; they do **not** approve audit-trail/e-sig adequacy (→ Data Integrity Expert), AI governance adequacy (→ AI Expert), tenant-isolation adequacy (→ Security/Privacy Expert), or validation strategy (→ CSV/CSA Expert). Final schema/index/infra design is engineering's, at build.

---

## 3D. Wiring Flows, Sequence & State Models (Mermaid — code-vetted)

> Every node/edge below is grounded in the §7B code-validated references. Mermaid renders in GitHub, GitLab, VS Code (Mermaid plugin), Obsidian, and mermaid.live. Status of the depicted *target* wiring: PLANNED; the *current-state* anchors are validated.

### 3D.1 Pilot build — module / service map (which WP touches what + dependencies)
```mermaid
flowchart TB
  subgraph PLAT["Platform foundation — senior devs (agent-assisted)"]
    WP4["WP-4 e-sig verify<br/>change-control / rca / batch"]
    WP13b["WP-13b fail-closed AI audit<br/>ai-gateway.service.ts"]
    WP2["WP-2 event-spine subset<br/>event-bus + subscribers"]
    WP1["WP-1 single-tenant lock<br/>context-gate"]
    WP5["WP-5 verifyRange<br/>audit-log/service.ts"]
  end
  subgraph WF["Workflows"]
    WP6["WP-6 Document Control core"]
    WP7["WP-7 Deviation"]
    WP8["WP-8 RCA"]
    WP9["WP-9 CAPA"]
    WP10["WP-10 Findings gate"]
    WP12["WP-12 Inspection export<br/>+1 build hand"]
  end
  subgraph AIG["MIRA / AI"]
    WP13["WP-13 guardrails + PDF"]
    V7["MIRA V7 provider pack"]
    WP11["WP-11 training (manual)"]
    WP14["WP-14 scorecard (read-only)"]
  end
  WP4 --> WP7
  WP4 --> WP8
  WP4 --> WP9
  WP2 --> WP6
  WP2 --> WP10
  WP2 --> WP12
  WP10 --> WP12
  WP13b --> WP13
  WP13b --> V7
  WP11 --> WP6
```
*Source: §7B validated module list. Edges = build dependencies (e.g., WP-12 depends on WP-2 + WP-10; WP-13 depends on WP-13b).*

### 3D.2 WP-4 — e-signature substrate verification (sequence)
```mermaid
sequenceDiagram
  actor U as Approver
  participant R as "Route withAuthority requiresEsign:true"
  participant S as "Service (change-control:964 / rca:787 / batch:256)"
  participant V as "validateEsignatureForRecord hitl/esig.service.ts:650"
  participant ES as "electronic_signatures (substrate)"
  participant A as auditTrailService
  U->>R: approve / close (signature_id)
  R->>S: authorized request
  S->>V: verify(signature_id, record)
  V->>ES: read signature row
  ES-->>V: signer, entity_type/id, meaning, created_at
  alt valid - signer=actor, entity bound, meaning=approved, fresh
    V-->>S: OK
    S->>S: transition + persist bound electronic_signatures ref
    S->>A: audit event
  else invalid / forged / expired / cross-tenant
    V-->>S: fail
    S-->>R: ESIG_VERIFICATION_FAILED (no mutation)
    S->>A: audit event (failure)
  end
```
*Reference pattern (KEEP): oos-oot/service.ts:710–733. Fix sites: change-control:964, rca:787/826, batch:256 (remove auto-mint fallback :297).*

### 3D.3 WP-13b — AI gateway fail-closed audit (sequence)
```mermaid
sequenceDiagram
  participant C as "Caller plugin (gdp:92 / document-library:32 / hardening:155)"
  participant G as "AiGatewayService:100 (regulated mode)"
  participant P as "LLM provider"
  participant L as "llmAudit -> llm_audit_log"
  alt llmAudit absent in regulated mode
    C->>G: construct / invoke
    G-->>C: FAIL (no audit sink)
  else llmAudit present
    C->>G: inference request
    G->>P: callProvider
    P-->>G: output
    G->>L: logCall (model, version, input hash, output, confidence, userId)
    alt audit write fails
      L-->>G: error
      G-->>C: FAIL request (no un-audited inference)
    else audit written
      L-->>G: ok
      G-->>C: result
    end
  end
```
*Anchors: ai-gateway.service.ts:100 (`llmAudit?`), gated logging :228/:429; coarse ai_requests write :210. The 3 plugins currently omit the logger.*

### 3D.4 WP-2 — event-spine linkage wiring (emitters → bus → consumers)
```mermaid
flowchart LR
  subgraph EMIT["Emitters (validated)"]
    DE["document_effective<br/>documents/service.ts:1061"]
    RCC["rca_conclusion_created<br/>rca/service.ts:670"]
    RCL["rca_capa_linked<br/>:1545 / :1587"]
    OBS["inspection observation"]
    FIN["finding<br/>findings/service.ts"]
    DEV["deviation closed / OOS confirmed"]
  end
  BUS["core/event-bus.ts:430<br/>(singleton)"]
  subgraph CONS["Consumers"]
    TRN["training assignment (WP-11)"]
    CAPA["CAPA (linkCapaToRca:1473 / WP-9)"]
    NOTE["notifications/event-subscriber.ts"]
  end
  DE --> BUS
  RCC --> BUS
  RCL --> BUS
  DEV --> BUS
  OBS -->|emit NEW inspection_observation_finding_created| FIN
  FIN -->|emit NEW finding_capa_linked| BUS
  BUS --> TRN
  BUS --> CAPA
  BUS --> NOTE
```
*Validated: `finding_capa_linked` and `inspection_observation_finding_created` do NOT exist yet (0 matches) → NEW. Pilot wires only in-scope linkage events, not all 18 orphans.*

### 3D.5 WP-12 — inspection readiness export (flow)
```mermaid
flowchart TD
  REQ["GET /inspection-readiness/:id/export (NEW)"] --> AUTH{access control}
  AUTH -->|denied| DEN["403 + audit"]
  AUTH -->|allowed| GATHER["gather: evidence + dispositions + scorecard"]
  GATHER --> H1["per-artifact SHA-256"]
  H1 --> MAN["manifest + package SHA-256"]
  MAN --> WM["watermark"]
  WM --> OUT["package: JSON + PDF"]
  OUT --> AUD["audit export event"]
  OUT --> RE{re-export same dispositions?}
  RE -->|yes| SAME["identical package hash (reproducible)"]
```
*Validated: e-signed close exists at inspection-readiness/routes.ts:183–188; NO export route / NO sha256/manifest/watermark today.*

### 3D.6 State-model deltas (only the pilot changes; full machines live in parent URS)
**CAPA (WP-9) — `capas/workflow.ts:7–14`:**
```mermaid
stateDiagram-v2
  [*] --> draft
  draft --> open
  open --> assigned
  assigned --> in_progress
  in_progress --> completed
  completed --> effectiveness_check
  effectiveness_check --> in_progress: rework loop (exists)
  effectiveness_check --> verified: NEW WP-9 requires e-sig
  verified --> closed: NEW WP-9 blocked if open action items CAPA_OPEN_ACTIONS
  closed --> [*]
```
**Deviation (WP-7):**
```mermaid
stateDiagram-v2
  investigating --> closed: closure e-sig exists + NEW critical exec co-sign verified
  note right of closed: reopen OUT of pilot intended use (raise new record)
```
**RCA (WP-8):**
```mermaid
stateDiagram-v2
  open --> approved: NEW substrate-verified approve e-sig
  approved --> closed: mandatory CAPA link via linkCapaToRca (exists)
```
**Findings (WP-10):**
```mermaid
stateDiagram-v2
  open --> closed: NEW major/critical blocked without linked acceptable CAPA
  note right of closed: minor unaffected
```

### 3D.7 Cross-module change-impact (which modules each WP touches)
```mermaid
flowchart TD
  WP4["WP-4"] --> M1["change-control/service.ts"]
  WP4 --> M2["rca/service.ts"]
  WP4 --> M3["batch/service.ts"]
  WP2["WP-2"] --> M4["core/event-bus.ts"]
  WP2 --> M5["notifications/event-subscriber.ts"]
  WP2 --> M6["config/workflow-auto-spawn.subscriber.ts"]
  WP2 --> M7["documents / reviews / findings / inspection-readiness"]
  WP13b["WP-13b"] --> M8["ai-gateway.service.ts + gdp/document-library/hardening plugins"]
  WP6["WP-6"] --> M9["documents + DocumentAuthoring.tsx + new migrations"]
  WP12["WP-12"] --> M10["inspection-readiness/routes.ts + export/manifest migrations"]
```
*Use for change-impact / regression scoping (CSV/CSA). Shared substrate: `electronic_signatures` (WP-4/7/8/9), `event-bus` (WP-2/6/10/12), `ai-gateway` (WP-13b/13).*

### 3D.8 Workflow Wiring Matrix (key flows)
| Flow | Frontend | Backend | Data/record | Permission | Audit event | Failure path |
|---|---|---|---|---|---|---|
| WP-4 signed transition | Controlled approval modal | verify vs substrate → transition | bound `electronic_signatures` ref | `withAuthority requiresEsign` | sign + transition | `ESIG_VERIFICATION_FAILED`, no mutation |
| WP-13b inference | AI surface (labelled) | gateway requires audit sink | `llm_audit_log` | gateway access | inference logged | fail request if un-audited |
| WP-2 SOP→training | SOP effective | consume `document_effective` | training assignment | training:assign | assignment created | none (manual fallback pilot) |
| WP-10 finding close | close action + e-sign modal | block without linked CAPA + verify e-sig vs substrate | `finding_capa_links` + bound `electronic_signatures` | `finding_disposition:<sev>` + `requiresEsign` | finding closed + signed | blocked if no CAPA; `ESIG_VERIFICATION_FAILED` if invalid e-sig |
| WP-12 export | export button | gather+hash+manifest+PDF | export package + manifest | export authority | export event | 403 + audit if unauthorized |

---

## 4. Traceability Matrix (URS-39 → FS-39 → DS-39 → parent URS → tests)

| URS-39 ID | Parent URS | Current-state verdict | Acceptance | Test cases | Risk | Priority |
|---|---|---|---|---|---|---|
| URS-39-WP4-01..03 | URS-04 §21 (→13/17/18) | gaps CONFIRMED; verifier exists | AC-39-WP4-1..3 | TC-39-WP4-1..5 | HIGH | MUST |
| URS-39-WP13b-01..03 | URS-32 §22 GUARD-02 | CONFIRMED (optional logger) | AC-39-WP13b-1..3 | TC-39-WP13b-1..4 | HIGH | MUST |
| URS-39-WP2-01..03 | URS-30 §21 | CONFIRMED (18 orphans) | AC-39-WP2-1..3 | TC-39-WP2-1..3 | MED | MUST |
| URS-39-WP1-01..04 | URS-02/03/05 §21 | CONFIRMED (no eligibility) | AC-39-WP1-1..3 | TC-39-WP1-1..3 | HIGH→LOW | MUST |
| URS-39-WP5-01 | URS-35/06 | PARTIALLY CONFIRMED | AC-39-WP5-1 | TC-39-WP5-1 | MED | SHOULD |
| URS-39-WP6-01..04 | URS-12 §21/22/23 | CONFIRMED (content dropped) | AC-39-WP6-1..3 | TC-39-WP6-1..4 | HIGH | MUST |
| URS-39-WP7-01..03 | URS-16 §21 | CONFIRMED (gates exist) | AC-39-WP7-1..2 | TC-39-WP7-1..3 | HIGH | MUST |
| URS-39-WP8-01..02 | URS-17 §21 | CONFIRMED (dead handoff) | AC-39-WP8-1..2 | TC-39-WP8-1..3 | HIGH | MUST |
| URS-39-WP9-01..02 | URS-18 §21 | CONFIRMED (3-way exists) | AC-39-WP9-1..2 | TC-39-WP9-1..3 | HIGH | MUST |
| URS-39-WP10-01..03 | URS-21 §21 | CONFIRMED (no gate); WP10-03 e-sig (close+defer) = target-state | AC-39-WP10-1..3 | TC-39-WP10-1..6 | HIGH | MUST |
| URS-39-WP12-01..04 | URS-22 §22 | CONFIRMED (no export) | AC-39-WP12-1..3 | TC-39-WP12-1..4 | HIGH | MUST |
| URS-39-WP11-01..02 | URS-28 §21 | CONFIRMED (dormant) | AC-39-WP11-1 | TC-39-WP11-1 | MED (assignment evidence MUST) | SHOULD (engine) |
| URS-39-WP13-01..03 | URS-32 §22 | CONFIRMED (declared) | AC-39-WP13-1..4 | TC-39-WP13-1..5 | HIGH | MUST |
| URS-39-WP14-01 | URS-38 | REUSE backend | AC-39-WP14-1 | TC-39-WP14-1 | LOW | SHOULD |
| URS-39-V7-01..04 | URS-32 §22 | governance | AC-39-V7-1..4 | TC-39-V7-1..4 | HIGH | MUST |

*(Phase-1 demo requirements URS-39A-DEMO-1..10 are traced in URS-39A, not here.)*

**Orphan check:** every URS-39 requirement traces to a parent URS + acceptance + ≥1 test. No orphan requirements. Detailed test-case authoring → Validation Test Architect (handoff).

---

## 5. Developer Handoff (build order)
1. **W1:** decide PDF lib; stand up CI verification-gate (auto evidence). 2. **W2 (senior devs):** WP-4, WP-13b. 3. **W3:** WP-2 subset, WP-1 lock. 4. **W6–W7:** WP-6, WP-7, WP-8, WP-9; **WP-10 by W7**. 5. **W7–W8 (build hand):** WP-12 export, WP-13 guardrails. 6. **W8/9→W12:** MIRA guardrail verification. 7. WP-11 manual (pilot), WP-14 read-only (deferrable).

## 6. QA / Validation Handoff
Risk-based CSA: HIGH-risk functions (e-sig/approval/closure, audit trail, RLS/tenant isolation, MIRA-to-record, inspection-export hash) get **direct test evidence**; MEDIUM scripted/targeted; LOW review/automated. Capture verification evidence **continuously from W7** into **G-7**. No high-risk function ships without direct test evidence. Detailed protocols → Validation Test Architect; final QA disposition → Head of QA.

## 7. Inspection Readiness Gate (this addendum)
| Gate | Result |
|---|---|
| Every requirement atomic + testable | Pass |
| Current-state evidence cited (file:line, audit verdict) | Pass (line numbers `re-confirm at build`) |
| No unsupported compliance claim / no "validated" | Pass |
| Acceptance + tests for every requirement | Pass |
| AI advisory-only + Annex 22 prohibition stated | Pass |
| Implementation status marked Unknown until executed | Pass |
| **Overall** | **`Draft — not validation-ready`** (build spec; evidence is generated during build) |

## 7B. Code-Validation Record (against `dev-vimal-audit-2`, 2026-05-31)

Every current-state file:line reference in this addendum was re-audited read-only against the repo. **Result: 16 of 17 reference families ACCURATE, 0 drifted, 0 not-found, 1 corrected.** No fabricated symbols, files, or behaviours.

| Ref family | Verdict | Confirmed at |
|---|---|---|
| WP-4 OOS verify reference | ACCURATE | `oos-oot/service.ts:710–733` (signer/entity/meaning/freshness) |
| WP-4 canonical verifier | ACCURATE | `hitl/esig.service.ts:650 validateEsignatureForRecord` |
| WP-4 change-control gap | ACCURATE | `change-control/service.ts:964–965` stores esig_id/hash, zero substrate reads; `closeChangeRequest:1526` no esig |
| WP-8 RCA gaps | **CORRECTED** | approve `:787`/reject `:826` store `approval_esig_id` unverified; **method is `linkCapaToRca` at `:1473`** (was mis-named/`~1456`); CAPA-at-close `:1037–1063`; SoD `:1026–1035`; reopen `:910`; emits `rca_conclusion_created:670`, `rca_capa_linked:1545/1587` |
| WP-4 batch optional verify | ACCURATE | `batch/service.ts:256 if(input.esig_id)`; auto-mint fallback `:297→:300` |
| WP-13b optional logger | ACCURATE | `ai/ai-gateway.service.ts:100 llmAudit?`; gated `:228/:429`; coarse write `:210–213` |
| WP-13b unwired plugins | ACCURATE | `gdp/plugin.ts:92`, `document-library/plugin.ts:32`, `hardening/plugin.ts:155` (6-arg, no llmAudit) |
| WP-2 bus + missing events | ACCURATE | `core/event-bus.ts:430`; `finding_capa_linked` + `inspection_observation_finding_created` = **0 matches codebase-wide** |
| WP-2 orphaned emits | ACCURATE | `documents/service.ts:1061/1144/1261`; `reviews/service.ts:622/679` |
| WP-1 scope switch | ACCURATE | `context-gate/routes.ts:88 /switch` log-only; `service.ts:432`; `CROSS_CONTEXT_DENIED` = **0 matches** |
| WP-5 verifyRange | ACCURATE | `audit-log/service.ts:278–285` throws non-audit_log; `jobs/audit-checkpoint-table-specs.ts:8–13` 4-table list |
| WP-6 doc gates + dropped content | ACCURATE | `documents/routes.ts` approve `:516`, effective `:607`, retire `:721`, supersede `:817`; `DocumentAuthoring.tsx:31` content omitted from mutate payload; `lifecycle.ts` no `withdrawn` |
| WP-7 deviation gates | ACCURATE | `deviations/service.ts` closed-block `:588`, root-cause `:592–600`, SoD `:616–618`, severity CAPA `:622–637`, closure e-sig `:646–649`, single approver `:682–702` |
| WP-9 CAPA | ACCURATE | `capas/service.ts` SoD `:207/320/394`, closure e-sig `:416–419`, 3-way `completeEffectivenessCheck:554–557`, close blocks cascades `:424–433` (not action items); `workflow.ts:7–14` 8-state, rework `:28` |
| WP-10 findings | ACCURATE | `findings/service.ts:559 transitionStatus`; major/critical gate `:596–615`; **0 `capa` matches in module** |
| WP-12 inspection export | ACCURATE | `inspection-readiness/routes.ts:183–188` e-signed close; **no export route, 0 sha256/manifest/watermark** |
| WP-11 training dormant | ACCURATE | `training/service.ts:773–792 createTrigger` inserts `training_triggers` read by nothing; no eventBus; no `/qualification` |

**Caveat retained:** line numbers are audit-observed 2026-05-31 and **must be re-confirmed at build time** (the codebase is on a live branch). The single PARTIAL (WP-8 method name) is corrected above and throughout this document.

---

## 7C. Validation-Package Gap (this is a build-delta spec, NOT a validation package)

URS-39 is strong as a **build-delta URS** (URS/FS/DS/acceptance/test/handoff). It is **NOT** a validation package. The following validation artifacts are **`Unknown — evidence required`** and must be authored/executed by the validation team (CSV/CSA contractor + 2 QA) before any validation-readiness or G-7-issuance claim:

| Validation artifact | Status | Owner |
|---|---|---|
| Evidence Map (per requirement → evidence ID) | `Unknown — evidence required` | CSV/CSA + QA |
| Synthetic Test Data Manifest | `Unknown — evidence required` | Validation Test Architect |
| Executable Synthetic Dataset (seed/fixtures) | `Unknown — evidence required` | Eng + Validation |
| OQ test cases (executed, with results) | `Unknown — evidence required` | Validation Test Architect → QA |
| Data Depth Addendum | `Unknown — evidence required` | Validation |
| Addendum-to-Dataset-to-OQ Reconciliation Matrix | `Unknown — evidence required` | Validation |
| Test Team Handoff | `Unknown — evidence required` | QA |
| First-Time Execution Runbook | `Unknown — evidence required` | Eng + QA |

**G-7 ISSUANCE IS BLOCKED until every artifact above exists, is executed, and is QA-dispositioned.** No release-readiness, Part 11, or production-verified claim may be made before then.

**Disposition:** Draft / build-spec only / not executed / not approved. Draft and evidence-gap reports do **not** prove compliance. This document supports **engineering build planning, work-package assignment, Claude/Cursor handoff drafting, and QA/CSV test-design planning** — it does **not** support validation execution, G-7 issuance, Part 11 control claim, release-readiness claim, or a "production-verified" claim. Detailed test protocols → Validation Test Architect; validation strategy/RTM/VSR → CSV/CSA Expert; final QA disposition → Head of QA.

---

## 8. Plain-English Glossary
See §0.7. Domain terms (CAPA, deviation, RCA, finding, e-signature, audit trail, ALCOA+, HITL, SoD) carry their standard GxP meanings; this addendum adds the build-specific terms (TDAL, RLS, e-sig substrate, G-7/G-8).

---

## Boundary Check — URS Expert
| Boundary Check | Result |
|---|---|
| Primary skill used | verixa-full-gxp-ai-eqms-urs-expert |
| Owned deliverable | Target-state build-delta URS addendum (URS-39) + engineering/QA handoff + Claude Code handoff blocks |
| Other skills consulted | Product/Engineering Architect (sequencing/feasibility), CSV/CSA Expert (risk-based test strategy), AI Validation & Governance (MIRA V7), Head of QA (disposition) |
| Out-of-scope items avoided | Validation strategy/RTM design → CSV/CSA; detailed test protocols → Validation Test Architect; Part 11/Annex 11 control adequacy → Data Integrity Expert; final QA approval → Head of QA; technical class/schema design → Product/Engineering Architect |
| Final status | **Draft — not validation-ready** / Draft within skill boundary (build-ready spec; human review + executed evidence required) |

## Source Ledger
| Source type | Source | Date | Claim supported | Limitations |
|---|---|---|---|---|
| Skill | verixa-full-gxp-ai-eqms-urs-expert (loaded) | 2026-05-31 | URS template + structure + boundary | Workbench; human review required |
| Repo audit | `dev-vimal-audit-2 @ 3bd2fe47` (read-only) | 2026-05-31 | All current-state file:line + verdicts | Static audit; line numbers `re-confirm at build` |
| Package | Master Build Issue + URS §21/§22/§23 addenda | 2026-05-29 | WP definitions + parent-URS mapping | Self-described draft |
| Governance | `Verixa_Pilot_Execution_Plan_v3_MASTER.md` | 2026-05-31 | Scope, sequencing, go-live rule, language guard | Advisory |
| Regulatory | 21 CFR Part 11; Annex 11; Annex 22 (Draft); EU AI Act 2024/1689; FDA CSA (03-Feb-2026) | verified | Applicability/risk drivers | Interpretation, not legal opinion |

*Draft — not validation-ready. Verixa verifies; the design partner validates intended use — never "validated." Read-only analysis — no Verixa repo files modified. Line numbers are audit-observed (2026-05-31) and must be re-confirmed at build time.*
