# Verixa — User Requirements Specification

# Module 6: Audit Trail / Hash-Chain / Tamper-Evident Substrate

| Field | Value |
|---|---|
| Document ID | VRX-URS-06 |
| Version | 1.0 |
| Status | Final — ready for QA, Validation, Regulatory Affairs, Information Security, and Founder approval. URS approval is separate from validation execution. This document becomes "Approved Controlled URS — released for engineering implementation and validation planning" only after signature capture in the Document Approval block. It becomes "Released for validation execution" only after the module migration evidence gate (URS-06-VAL-008) and validation evidence pack are satisfied. |
| Document Type | User Requirements Specification (URS) |
| GAMP 5 Category | Category 5 — Custom Application |
| Regulatory Classification | Critical infrastructure substrate — operates the universal append-only audit log, the hash chain (per-entity, per-tenant, global), the integrity verifier, the retention and cold-archive policy engine, the audit read / export / integrity surfaces, and the periodic audit-trail review apparatus. Module 6 is the regulatory record of who did what, when, where, why, and on what authority across the entire Verixa platform. The audit substrate is the inspector's primary evidentiary surface. |
| Date of Issue | 2026-05-06 |
| Module Owner (Engineering) | Audit Substrate / Storage Squad |
| Module Owner (Quality Validation) | CSV / CSA Lead — Audit Substrate |
| Module Owner (Compliance) | Information Security, Quality Assurance, Regulatory Affairs |
| Approving Authority | Founder / Chairman & MD; QA Head; Validation Head; RA Head; Information Security Head |

## Document Approval

| Role | Name | Signature | Date |
|---|---|---|---|
| Author — Platform Architecture | _____________________ | _____________________ | __________ |
| Reviewer — Engineering Lead | _____________________ | _____________________ | __________ |
| Reviewer — QA / Validation Lead | _____________________ | _____________________ | __________ |
| Reviewer — Information Security Lead | _____________________ | _____________________ | __________ |
| Reviewer — Regulatory Affairs Lead | _____________________ | _____________________ | __________ |
| Approving Authority — Founder, Chairman & MD | _____________________ | _____________________ | __________ |

## Version History

| Version | Date | Summary |
|---|---|---|
| 1.0 | 2026-05-06 | First issued user requirements specification for Module 6. |

---

## 0. Document Framing

### 0.1 Purpose of this document

This URS defines the target expected state for Verixa's Audit Trail / Hash-Chain / Tamper-Evident Substrate module (Module 6). It is the binding contract between product, engineering, quality validation, regulatory affairs, information security, and the executive authority for the design, implementation, validation, release, and on-going periodic review of the universal audit substrate that captures every regulatory-significant action across the entire Verixa platform: the append-only WORM (Write Once, Read Many) audit log, the SHA-256 hash chain at three scopes (per-entity, per-tenant, global), the atomic write contract that binds every audit row to its originating database mutation and (where applicable) electronic-signature row, the retention policy engine, the cold-archive bridge to URS-35, the audit read / export / integrity surfaces, the periodic audit-trail review apparatus, and the WORM-storage posture that protects the audit log from any application-layer mutation. Compliance with this URS is mandatory.

### 0.2 Audience

Engineering, QA, Validation, Regulatory Affairs, Information Security, executive authority, the platform's Implementation team, internal and external auditors, and inspectors from regulatory bodies including the United States Food and Drug Administration, the European Medicines Agency / national competent authorities, the Medicines and Healthcare products Regulatory Agency, Health Canada, the Central Drugs Standard Control Organisation of India, and Pharmaceutical Inspection Co-operation Scheme members. The plain-language primer (§0.4) and worked examples (§3.5) make Module 6 accessible to non-domain engineers, product owners, validation engineers, and forensic / SOC analysts who have not previously specified WORM-protected hash-chained audit substrates for regulated GxP platforms.

### 0.3 How to read this document

Each requirement has a unique identifier. "MUST" denotes a mandatory requirement; "SHOULD" denotes a strong recommendation; "MAY" denotes an option. The document is self-contained: front end (§5), back end (§6), data model (§6.2), application programming interface (§6.3), workflow (§6.4), business rules (§6.5), audit (§6.6 — Module 6 is itself the audit substrate), security (§12), regulatory mapping (§14), test cases (§16), and validation evidence (§17) are all in this single file.

### 0.4 Plain-language primer for non-domain readers

Every regulator who inspects a pharmaceutical-quality computerised system asks the same two questions: **"Show me what was done"** and **"Prove to me the record has not been altered."** The audit trail answers the first question; the hash chain proves the second. Module 6 owns both.

The audit trail is a chronological list of every regulatory-significant action — every record creation, every state transition, every electronic signature, every authority assignment, every export, every login, every break-glass override, every workflow template change. Each row in the audit log captures who did the action (`userId`, `tenantId`), what they did (`action`, `resourceType`, `resourceId`), when they did it (server-set `timestamp`), where they did it from (`ipAddress`, `userAgent`), what the relevant context was (`details`), and what authority they had to do it (linkage to the electronic signature and to Module 5's authority snapshot).

The hash chain is what makes the audit log **tamper-evident**. Tamper-evident means: any post-hoc edit, deletion, insertion, or reordering of audit rows is detectable through cryptographic verification, even if the attacker has full database privileges. The technique: every audit row stores `previous_hash` (the hash of the previous row in its chain) and `record_hash` (the SHA-256 hash of its own content plus `previous_hash`). To re-write history, an attacker would need to recompute every subsequent hash all the way to the current row — and we periodically pin the current hash externally (regulator-readable manifest, customer-readable manifest, optional time-stamped third-party notarisation) so the attacker would also need to alter every external pin. With external anchoring this becomes computationally and operationally infeasible.

Three chain scopes are maintained: per-entity (one chain per regulated record — e.g., one chain for CAPA-2026-0044), per-tenant (one chain for events not bound to a single entity, e.g., authority assignments, catalogue changes), and global (one chain for platform-level events). Per-entity chains are protected by a PostgreSQL advisory lock scoped to `(tenant_id, entity_type, target_record_id)` per URS-04 BR-04-16, which prevents concurrent inserts from re-ordering the chain; the per-tenant chain uses a per-tenant lock; the global chain uses a global lock. Locking is fine-grained so unrelated activity does not contend.

The audit log is **append-only WORM**. Append-only means: rows can only be inserted, never updated or deleted. WORM (Write Once, Read Many) means the storage layer enforces this immutability beyond the application — through database-level controls (column-level CHECK constraints, no UPDATE / DELETE permissions on the table for application roles) and storage-layer controls (object-store object-lock for archived rows, immutable retention period). Even the platform administrator cannot edit a historical row; only an infrastructure superuser at the database layer (controlled outside Verixa application code, audited at the cloud provider) can — and any such access is itself a Security Operations Centre incident.

The audit substrate is **the inspector's primary evidentiary surface**. When the FDA, the EMA, the MHRA, Health Canada, or the CDSCO walks in, the first request is "show me your audit trail for batch ABC-2026-0145" or "show me everyone who held the Authority Profile `qp_eu` in the last 12 months." Module 6's read surface, integrity manifest, and exports are how the platform answers those questions in inspection time. Module 6's retention policy ensures the records are still there 7 to 25 years after the original action — and after the original employee, the original tenant administrator, the original software version, and possibly the original Verixa deployment have all changed.

**Module 6 is consumed by every other module.** Every Verixa module that mutates data calls the Module 6 write path; failure to write the audit row rolls back the originating action (URS-04 BR-04-15). Module 6 owns the write contract, the chain integrity, the retention engine, and the read / export surface; consuming modules own only the **content** of their own audit events.

### 0.5 Audit substrate flow diagram (write + read path)

```mermaid
flowchart TD
  A[Originating module mutates data] --> B[Module 6 write path: appendAuditRow]
  B --> C[Compute previous_hash from chain HEAD via advisory lock]
  C --> D[Compose audit row with canonical JSON content]
  D --> E[Compute record_hash = SHA-256 previous_hash plus content]
  E --> F[Insert audit row in same transaction as originating mutation and snapshot row]
  F --> G{All inserts succeed?}
  G -- no --> X1[Rollback all]
  G -- yes --> H[Release advisory lock]
  H --> I[Update chain HEAD pointer]
  I --> J[HTTP 200 to caller]

  K[Auditor or inspector opens read surface] --> L[Read API: filter by tenant entity user date range action]
  L --> M[Module 6 returns rows with verdict trail and hash badges]
  M --> N{Auditor requests integrity verification?}
  N -- yes --> O[Run integrity verifier scoped to entity or tenant or global]
  O --> P[Walk chain from genesis to HEAD recomputing record_hash at each step]
  P --> Q{All hashes valid?}
  Q -- yes --> R[Verifier returns valid badge with manifest]
  Q -- no --> S[Verifier returns INTEGRITY_VIOLATION; SOC alert; Founder escalation]
  N -- no --> T[Auditor exports rows with electronic signature]
```

Diagram 0.5-A — Module 6 write path is atomic with the originating mutation and snapshot row write; failure rolls everything back. Module 6 read path supports filtered query, on-demand integrity verification, and electronically signed export with integrity manifest.

### 0.6 Glossary of key terms used in this document

| Term | Definition |
|---|---|
| Append-only | A database table or storage class on which only INSERT operations are permitted; UPDATE and DELETE are forbidden by database-level grants and / or column-level constraints. |
| Audit row | A single record in the universal audit log capturing one regulatory-significant action with full attribution, context, and chain linkage. |
| Canonical JSON | A deterministic JSON serialisation (sorted keys, fixed numeric formatting, no whitespace ambiguity) used as input to the SHA-256 hash so that the same logical content always produces the same hash. |
| Chain HEAD | The most recently inserted audit row in a given chain; its `record_hash` is the value the next inserted row uses as its `previous_hash`. |
| Cold archive | Long-term storage tier for audit rows older than the hot retention window (default 2 years). Archived rows remain query-accessible but with higher latency; URS-35 owns the storage class and immutability period. |
| External anchoring | Periodic publication of a chain HEAD hash to a regulator-readable / customer-readable / optional third-party time-stamped manifest, so the chain integrity becomes externally verifiable without trusting Verixa. |
| Genesis row | The first audit row inserted in a chain. Its `previous_hash` is a fixed deterministic value (e.g., SHA-256 of the chain identifier + tenant onboarding timestamp) so the chain has a unique anchor. |
| Hash chain | A sequence of audit rows where each row's `record_hash` cryptographically depends on the previous row's `record_hash`, making the sequence tamper-evident. |
| Integrity manifest | A signed export bundle that contains the chain HEAD hash, a sample of intermediate hashes, the verifier's verdict, and a counter-signed timestamp; produced by Module 6's export surface. |
| Integrity verifier | The Module 6 service that walks a chain from genesis (or from a specified offset) to HEAD recomputing each `record_hash` and reporting `valid` or `INTEGRITY_VIOLATION`. Runs scheduled (monthly), on every export, and on demand. |
| Per-entity chain | One hash chain per regulated record, identified by `(tenant_id, entity_type, target_record_id)`. The launch chain scope for record-bound events. |
| Per-tenant chain | One hash chain per tenant, identified by `tenant_id`, used for events not bound to a single entity (e.g., authority-assignment lifecycle, catalogue changes, periodic-review attestations). |
| Global chain | One hash chain for the entire platform, used for events that are not tenant-bound (e.g., platform-administrator actions on the global Tier 1 catalogue, platform-level Operational events). |
| Tamper-evident | Any unauthorised post-insert change to the audit log is detectable by integrity verification, even by an attacker with full database privileges. |
| Time anomaly detection | A scheduled job that compares server clock readings across recent audit rows against expected NTP-synchronised drift bounds and flags any violation as a potential time-tampering event. |
| WORM | Write Once, Read Many. Storage posture that enforces immutability of inserted records through database-level grants, column constraints, and storage-layer object-lock. |

### 0.7 Module 6 architectural picture

```mermaid
graph LR
  subgraph M6 [Module 6 — Audit Substrate]
    APPEND[Append Audit Row]
    CHAINS[Per-entity / Per-tenant / Global chains]
    VERIFIER[Integrity Verifier]
    READ[Read / Export Surface]
    REVIEW[Periodic Audit-Trail Review]
    ARCHIVE[Hot to Cold Archive Bridge]
  end

  M1[URS-01] --> APPEND
  M2[URS-02] --> APPEND
  M3[URS-03] --> APPEND
  M4[URS-04] --> APPEND
  M5[URS-05] --> APPEND
  M12[URS-12..URS-34 regulated modules] --> APPEND
  APPEND --> CHAINS
  CHAINS --> VERIFIER
  VERIFIER --> READ
  READ --> EXPORT[Electronically Signed Exports]
  ARCHIVE <--> M35[URS-35 Backup / Restore / Cold Storage]
  REVIEW --> READ
  M30[URS-30 Notifications] --> REVIEW
```

Diagram 0.7-A — Module 6 receives writes from every consuming module, maintains the three chain scopes, hosts the integrity verifier, surfaces the read / export / review apparatus, and bridges to URS-35 for hot-to-cold archival.

---

## 1. Module Purpose

Module 6 establishes the universal audit substrate for Verixa: the append-only WORM audit log, the SHA-256 hash chain at per-entity / per-tenant / global scopes, the atomic write contract that binds every audit row to its originating mutation and (where applicable) electronic-signature row, the integrity verifier, the retention and archival policy engine, the audit read / export surfaces, the periodic audit-trail review apparatus, and the WORM-storage posture that protects the audit log from any application-layer mutation. Module 6 is consumed by every other module that mutates data; failure to write the audit row rolls back the originating action. Module 6 is the regulatory record of every action across the platform and the inspector's primary evidentiary surface.

Module 6's correctness is existential to Verixa's regulatory posture. A break in chain integrity, a missing audit row, a time-tampered timestamp, or a successful application-layer modification of a historical record is a **critical data-integrity incident** and a potential 21 CFR Part 11 §11.10(e), EU GMP Annex 11 §9, MHRA data-integrity finding, or FDA 483 observation **unless investigated, root-caused, and resolved with documented evidence** (e.g., recoverable storage corruption restored from URS-35 with hash equivalence demonstrated; verifier-defect engineering correction with no actual chain corruption). Module 6 is engineered to make such a break impossible at the application layer and detectable in finite time at every other layer; when a break occurs the regulatory posture depends on the speed and rigour of the response (chain quarantine, SOC alert, executive authority escalation, customer notification, root-cause analysis with evidence) per §12.9 and §11.

---

## 2. Scope

### 2.1 In scope

- The universal audit log: a single append-only WORM table that captures every regulatory-significant action across every Verixa module, with a fixed immutable launch schema (DEC-06-04) including `id`, `tenant_id`, `chain_scope`, `entity_type`, `target_record_id`, `actor_user_id`, `acting_on_behalf_of_user_id` (for delegations), `action_code`, `details_jsonb`, `ip_address`, `user_agent`, `correlation_id`, `e_sig_id` (nullable), `authority_snapshot_id` (nullable), `ai_advisory` (boolean), `timestamp` (server-set TIMESTAMPTZ), `previous_hash`, `record_hash`, `chain_sequence` (monotonic per chain).
- Three chain scopes (DEC-06-02): per-entity (`(tenant_id, entity_type, target_record_id)`), per-tenant (`tenant_id`), and global (no tenant binding). Every audit row is bound to exactly one chain scope determined by the originating action. Per-entity chains are protected by a PostgreSQL advisory lock scoped to `(tenant_id, entity_type, target_record_id)` per URS-04 BR-04-16; per-tenant chains by a per-tenant lock; global chain by a global lock.
- The atomic write contract: every consuming module's mutation MUST go through Module 6's `appendAuditRow` API in the same database transaction as the originating mutation and (where applicable) the URS-04 electronic-signature row + URS-05 authority-snapshot row. Failure to write the audit row rolls back all (URS-04 BR-04-15).
- The hash function and canonical serialisation: SHA-256 over the canonical JSON representation of the audit row content concatenated with `previous_hash`. Canonical JSON is deterministic (sorted keys, no whitespace ambiguity, fixed numeric formatting per RFC 8785 / JCS). Genesis rows have a fixed deterministic `previous_hash` derived from the chain identifier + chain genesis timestamp.
- The integrity verifier: a service that walks a chain from genesis (or from a specified offset) to HEAD recomputing each `record_hash` and reporting `valid` or `INTEGRITY_VIOLATION`. Runs (a) scheduled (monthly per chain), (b) on every export (the export bundle's manifest carries the verifier verdict), (c) on demand from auditor or platform-administrator surfaces, and (d) on every backup / restore drill per URS-35.
- External anchoring: periodic publication of every chain's HEAD hash to a regulator-readable manifest (signed by Founder), a customer-readable manifest (signed by Verixa platform), and optional third-party RFC 3161 time-stamping where the tenant elects. Anchoring frequency: weekly minimum for per-tenant and global chains; per-entity chain HEADs anchored at significant events (signature insert, periodic-review close, customer-requested) and weekly aggregate.
- Retention policy engine: per-chain-scope retention rules with launch defaults of seven years for non-snapshot rows and twenty-five years for `approval_authority_snapshots` references and override events; tenants may configure shorter intervals; tenants may not extend beyond the default without controlled regulatory justification and approved change control (more retention) but not upward (less retention) by tenant administrators within validated bounds. Retention enforced at archival time, not deletion time — rows are moved to cold storage but never deleted before retention expiry.
- Cold archive bridge: hot-to-cold archival after two years per DEC-06-07, performed by URS-35 with object-lock immutability. Archived rows remain query-accessible with higher latency; integrity verification continues to function across hot + cold.
- Audit read / export surfaces: filtered read API by tenant / entity / user / date range / action code / chain scope; integrity manifest viewer per chain; export with electronic signature, signed download URL with 15-minute TTL, integrity manifest accompanying every export.
- Periodic audit-trail review apparatus: per URS-01 §12.11 and URS-04 §12.8, a designated reviewer triages high-risk events within one business day; Module 6 owns the review queue, the reviewer surface, the attestation log, the escalation rules, and the export pack.
- Time source and time-anomaly detection: server clock UTC; NTP synchronised; scheduled comparison job flags clock drift beyond bounds; suspect rows are quarantined for forensic review without being mutated.
- WORM-storage posture: database-level (no UPDATE / DELETE grants on the audit table for any application role); column-level (CHECK constraints prevent post-insert mutation); storage-layer (object-lock immutability period on archived rows); even platform identity cannot edit historical rows from inside the application.
- AI / LLM-output segregation per CLAUDE.md QS-21: every audit row carries `ai_advisory` (boolean); rows produced by AI suggestion paths are flagged; the read surface visually distinguishes them; no AI suggestion is written to a regulated record without explicit human electronic signature recorded as a separate audit row.
- Cross-module reconciliation: audit row references the URS-04 electronic-signature row (`e_sig_id`) and the URS-05 authority snapshot row (`authority_snapshot_id`); the snapshot row references the audit row by id; bidirectional referential integrity preserved across hot + cold.
- Front-end: filtered audit viewer, integrity manifest viewer, periodic-review reviewer surface, export wizard.
- Cross-module wiring: every URS-01..URS-35 module that mutates data calls Module 6's write path; URS-35 owns the storage durability, replication, backup, and restore that preserve the chain hashes verbatim; URS-30 delivers periodic-review and integrity-violation notifications.

### 2.2 Out of scope

- Authentication, multi-factor authentication, password policy, session lifecycle (URS-01).
- Permission matrix and base role catalogue (URS-02).
- Active context and approval-scope check (URS-03).
- Workflow templates, the workflow runtime, the Controlled Approval Modal, the e-signature ceremony, the slot-to-signature linkage (URS-04).
- The Authority Profile catalogue, assignments, delegations, SoD, and resolver functions (URS-05).
- The qualification register (URS-28).
- Master data CRUD for tenants, sites, products, studies, suppliers (URS-07/08/09/10/11).
- Domain-specific decision semantics for any regulated entity (every domain module owns its own state model; Module 6 owns only the audit write path and the chain).
- The backup / restore implementation (URS-35 owns durability, replication, restore drills; Module 6 specifies the chain-preservation contract).
- AI-driven decision-making (explicitly prohibited; AI suggestion-only paths flow through MIRA / URS-32 with human electronic signature; Module 6 flags AI-advisory rows in metadata).

### 2.3 Closed launch decisions

| Identifier | Closed launch decision |
|---|---|
| DEC-06-01 | The universal audit log is **append-only WORM**. UPDATE and DELETE are forbidden at the application layer for every role including platform identities. Database-level grants prohibit UPDATE and DELETE on the `audit_log` table for every application role; column-level CHECK constraints guard the `record_hash` and `previous_hash` columns; storage-layer object-lock with retention period applies to archived rows. The only path to alter a historical row is through an infrastructure superuser at the database layer outside Verixa application code, which is itself a SOC incident. |
| DEC-06-02 | Three chain scopes are maintained at launch: **per-entity** keyed by `(tenant_id, entity_type, target_record_id)` for record-bound events; **per-tenant** keyed by `tenant_id` for events not bound to a single entity; **global** keyed by null tenant_id for platform-level events. Every audit row is bound to exactly one chain scope determined by the originating action. Adding a chain scope is a Class 1 change. |
| DEC-06-03 | The hash function is **SHA-256**. Input is the **canonical JSON** serialisation of the audit row content concatenated with `previous_hash`, per RFC 8785 (JSON Canonicalization Scheme). Canonical JSON is deterministic: sorted keys, fixed numeric formatting, no whitespace ambiguity. Hash function changes are Class 1 changes and require a documented chain migration with parallel old-and-new hashes during the migration window. |
| DEC-06-04 | The audit row schema is fixed at launch and immutable through Class 1 change governance: `id`, `tenant_id` (nullable for global chain), `chain_scope` (`per_entity` / `per_tenant` / `global`), `entity_type` (nullable except for `per_entity` scope), `target_record_id` (nullable except for `per_entity` scope), `actor_user_id` (nullable for system actors with explicit named system identity), `acting_on_behalf_of_user_id` (nullable), `action_code`, `details_jsonb`, `ip_address` (nullable for system-generated), `user_agent` (nullable for system-generated), `correlation_id`, `e_sig_id` (nullable), `authority_snapshot_id` (nullable), `ai_advisory` (boolean default false), `timestamp` (TIMESTAMPTZ; server-set), `previous_hash`, `record_hash`, `chain_sequence` (bigint monotonic per chain). Adding a column is a Class 1 change with chain-extension migration. |
| DEC-06-05 | Every consuming module's regulated mutation MUST go through Module 6's `appendAuditRow` **as an in-process library call or PostgreSQL stored procedure executed on the same database connection and within the same transaction as the originating mutation** (and, where applicable, the URS-04 electronic-signature row + URS-05 authority-snapshot row). Atomic rollback on audit-write failure is achievable only because the audit insert is part of the same SQL transaction; a remote HTTP / service-to-service audit endpoint cannot guarantee atomicity with the caller's database transaction without distributed-transaction infrastructure that this URS does not assume. A remote audit-event ingestion endpoint MAY exist for non-transactional system events (e.g., periodic-job heartbeats, infrastructure-level events emitted by URS-35 or external monitoring) that do not require atomic rollback with a regulated mutation; such events MUST be clearly labelled in the source code path and MUST NOT be used for any regulated mutation. There is no fire-and-forget audit for regulated mutations, no asynchronous audit for regulated mutations, no eventual-consistency audit for regulated mutations. |
| DEC-06-06 | Retention defaults at launch: seven years for the standard audit row; twenty-five years for `approval_authority_snapshots` rows referenced by audit (URS-05 owns the row; URS-06 owns the audit-row reference). **Tenants may increase retention beyond the launch defaults; tenants may never reduce retention below the launch defaults.** Retention is enforced at archival time — rows move to cold storage but are never deleted before retention expiry. After retention expiry, rows are eligible for storage-layer release (where the storage layer supports controlled deletion of expired immutable objects); otherwise they remain immutable in cold storage indefinitely. The distinct case of GDPR / DPDP cryptographic erasure of PII fields is a different operation governed by DEC-06-13 (key destruction or read-time overlay; the historical `audit_log` row itself is never modified). |
| DEC-06-07 | The `audit_log` table is a **logical view** that spans (a) hot partitions in PostgreSQL holding rows from the most recent two years and (b) cold immutable storage (URS-35 object-lock-protected) holding older rows. Hot-to-cold movement is implemented as **controlled partition archival or WORM-preserving storage migration, NOT as application DELETE**. The application layer never issues DELETE on `audit_log`. The archival process: (1) older partitions are sealed against further INSERT (no new rows can be added to a sealed partition); (2) sealed partitions are copied to URS-35 cold storage with object-lock immutability for the configured retention period; (3) URS-35 confirms persistence and re-verifies `record_hash` and `previous_hash` verbatim against the source; (4) only after URS-35 confirmation, the sealed partition in PostgreSQL is detached as a partition (PostgreSQL `ALTER TABLE ... DETACH PARTITION CONCURRENTLY`) and physically dropped at the storage layer (which is a partition operation, not a row-level DELETE). The logical `audit_log` view continues to span hot + cold so every audit row remains query-accessible with higher latency for cold rows. **No audit row may become unavailable before retention expiry.** Integrity verification operates across the logical view; the verifier transparently fetches cold rows when traversing chains that cross the boundary. The cold tier MUST preserve `record_hash` and `previous_hash` verbatim; any compression / serialisation transformation during archive MUST be hash-preserving and re-verified post-migration. |
| DEC-06-08 | The integrity verifier runs (a) scheduled monthly per chain (sliding window — chains with recent activity are verified more frequently up to weekly), (b) on every export (the export's manifest carries the verifier verdict), (c) on demand from auditor or platform-administrator surfaces, and (d) on every URS-35 backup / restore drill. Verifier output is itself audited as `INTEGRITY_VERIFIER_RUN` with verdict and the chain-scope identifier. Any `INTEGRITY_VIOLATION` triggers immediate SOC alert, executive authority escalation, automatic chain quarantine (read-only with banner), and incident-response per URS-04 §11. |
| DEC-06-09 | Audit read access at launch: `auditor`, `admin` (within own tenant), `quality_lead` (read-only of own tenant for high-risk-event review), `platform_admin` and `super_admin` under the controlled support / break-glass posture per URS-02 §3.6.1. Reads are audited at three dispositions to balance forensic visibility against log-volume explosion: (a) **per-row reads are NOT audited** — paginated table queries do not produce one audit row per row read; (b) **session-level coarse audit** — opening the audit-viewer surface emits exactly one `AUDIT_LOG_VIEW_OPENED` row per user-session per tenant scope (idempotent within the session) capturing who opened the audit log and from where; (c) **PII-unmasking access IS audited** — every successful unmasking of a PII field by a caller holding `audit:read_pii` emits one `AUDIT_PII_ACCESSED` row capturing the affected `audit_log_id` set and the field paths revealed; (d) **exports ARE audited** as `AUDIT_LOG_EXPORTED`. Filtered reads apply PII masking per the reader's permission level; full PII visibility requires the additional permission `audit:read_pii`. |
| DEC-06-10 | Every audit export goes through the URS-04 Controlled Approval Modal with electronic signature; output is a signed download URL with 15-minute TTL plus an integrity manifest. The manifest contains: (a) the **per-entity chain HEAD hash** for every entity in the export footprint, (b) the **Merkle proof** path linking each per-entity HEAD to the per-tenant Merkle root, (c) the **per-tenant Merkle root** at export time, (d) the **per-tenant chain HEAD hash** at export time, (e) the **global chain HEAD hash** at export time, (f) the **external anchor reference** (regulator-manifest URL, customer-manifest URL, optional RFC 3161 token) under which the per-tenant Merkle root and global chain HEAD were last published, (g) a sample of intermediate hashes, (h) the verifier verdict, (i) the export's content fingerprint, and (j) the exporter's electronic-signature reference. The manifest is countersigned by the platform's signing key and (where the tenant elects) by an RFC 3161 time-stamp authority. An external party verifying the export reproduces each per-entity HEAD's Merkle path to the per-tenant root and compares the reproduced root against the published external anchor; equality proves the per-entity chain HEAD has not been altered since the anchor was published. |
| DEC-06-11 | Concurrency control on chain inserts uses PostgreSQL advisory locks: per-entity chains use `pg_advisory_xact_lock(hash(tenant_id, entity_type, target_record_id))`; per-tenant chains use `pg_advisory_xact_lock(hash(tenant_id))`; the global chain uses `pg_advisory_xact_lock(GLOBAL_CHAIN_LOCK_KEY)`. Locks are transaction-scoped (released on commit / rollback). The lock guarantees that no two concurrent inserts to the same chain interleave and produce a non-deterministic chain. |
| DEC-06-12 | The audit log itself is unmodifiable through every application path. Even platform identity under controlled support / break-glass posture cannot UPDATE or DELETE a historical audit row. The only legitimate paths are (a) INSERT new rows (regular write path), (b) read for inspection / export, (c) annotate via a separate `audit_annotations` table that is itself append-only and chain-linked but does NOT mutate the original row. Annotations are clearly visually distinguished in the read surface and never substitute for the original row. |
| DEC-06-13 | PII handling: certain `details_jsonb` fields and `ip_address` may contain personal data subject to regulations (GDPR, India DPDP, HIPAA where applicable). PII fields are tagged in the row schema (`pii_fields[]` jsonb-path array); tenant data residency from URS-08 applies; the read surface masks PII unless the reader has the explicit `audit:read_pii` permission; PII access is itself audited as `AUDIT_PII_ACCESSED`. **Cryptographic erasure of PII MUST NOT mutate any historical `audit_log` row.** PII fields stored in `audit_log.details_jsonb` are persisted as either (a) **subject-level-key encrypted ciphertext** at write time (the launch implementation) where each user has a per-subject data-encryption key registered at account creation; cryptographic erasure on right-to-erasure invocation destroys the per-subject key, rendering the ciphertext permanently undecryptable while leaving the `audit_log` row, its `record_hash`, and its chain linkage completely unchanged; or (b) **append-only redaction overlay** in the separate `pii_redaction_overlays` table (DEC-06-13b) which controls what is rendered / exported at read time after erasure authorisation. Either mechanism preserves chain integrity by construction because the original `audit_log` content (which is what the hash chain commits over) is never altered. The system MUST never produce a "tombstone" by re-writing a historical row; any such design is forbidden because it would imply either a SHA-256 collision (computationally infeasible by design) or a custom hash-indirection that is not specified by this URS. |
| DEC-06-13b | The append-only redaction overlay is a separate `pii_redaction_overlays` table with rows referencing the original `audit_log_id` plus jsonb-path of the redacted field, the regulatory basis (`gdpr_art_17`, `dpdp_section_12`, etc.), the DPO-signed `requested_e_sig_id`, the executed-at timestamp, and the redaction action (`mask` / `tombstone_text` / `key_destruction_reference`). At read time, the read surface joins `audit_log` with active overlay rows and renders the redacted representation; the underlying `audit_log` row is never modified. The overlay rows are themselves append-only WORM and chain-linked to a parallel `pii_redaction_overlays_chain`. |
| DEC-06-14 | Periodic audit-trail review per URS-01 §12.11: high-risk events are triaged within one business day. The Module 6 review queue surfaces every event tagged `severity = 'high'` or `severity = 'critical'` (by event-code policy) within the past 24 hours; the reviewer (independent of the actor) attests review completion through the Controlled Approval Modal; cluster-detection rules emit `HIGH_RISK_EVENT_CLUSTER_DETECTED` and escalate to Founder where thresholds are crossed. |
| DEC-06-15 | AI / LLM output segregation per CLAUDE.md §QS-21: every audit row carries `ai_advisory` boolean; rows produced by AI suggestion paths (e.g., MIRA copilot, AI scoring) MUST set `ai_advisory = true`. The read surface visually flags AI-advisory rows. AI-advisory rows MUST NOT be written directly to a regulated record field; the human acceptance is itself a separate audit row with `ai_advisory = false` and the human's electronic signature. |
| DEC-06-16 | Time source: server clock UTC, NTP-synchronised against a stratum-1 / stratum-2 reference (cloud-provider time service). Client-supplied timestamps are dropped at the API boundary. A scheduled time-anomaly detection job compares `timestamp` deltas across recent rows against expected NTP drift bounds (default ±100 ms across the cluster); violations trigger `TIME_ANOMALY_DETECTED` and SOC alert. Suspect rows are quarantined for forensic review without being mutated. |
| DEC-06-17 | Genesis row per chain: when a chain is first opened (tenant onboarding for the per-tenant chain; new entity creation for a per-entity chain; platform initialisation for the global chain), Module 6 inserts a `CHAIN_GENESIS` row with `previous_hash` set to a deterministic value derived from the chain identifier and the chain genesis timestamp. The genesis row is the chain's anchor and is itself append-only WORM. |
| DEC-06-18 | Cross-chain referential integrity: an audit row that records an electronic signature carries `e_sig_id` referencing URS-04's `electronic_signatures.id`; the URS-04 row and the URS-05 `approval_authority_snapshots` row both carry `audit_log_id` referencing the audit row. Bidirectional referential integrity is enforced and preserved across hot + cold. The export integrity manifest verifies the bidirectional consistency for the exported window. **The circular reference is resolved by preallocating all three UUIDs at the start of the regulated-decision transaction** (one UUID for the prospective `audit_log` row, one for the `electronic_signatures` row, one for the `approval_authority_snapshots` row); the three rows are then inserted in the same transaction with foreign-key constraints declared `INITIALLY DEFERRED` so the cross-references resolve at COMMIT time. The transaction commits only if all three rows are present and the cross-references match; on commit the constraints fire and verify referential integrity, rolling back the transaction if any cross-reference is missing or mismatched. |
| DEC-06-18a | An equivalent stored-procedure path is provided where consuming modules prefer encapsulated atomicity: `audit_e_sig_snapshot_append_atomic(...)` receives the three preallocated UUIDs and the row contents, performs all three inserts plus consistency check inside the procedure, and returns the three identifiers; the procedure encapsulates the deferred-constraint resolution. |
| DEC-06-19 | URS-35 backup / restore preserves chain hashes verbatim. Restore drills MUST produce the same chain HEAD hash as the source for every chain scope. Any divergence is a release blocker. URS-35 owns durability and replication; Module 6 owns the chain-preservation contract that URS-35 MUST honour. |
| DEC-06-20 | The audit log is append-only at the application layer; system-actor writes (e.g., scheduled jobs, integrity verifier itself, archival process) use named system identities (e.g., `audit-archival@verixa.internal`) with `actor_user_id` set to the named system identity. System actors MAY write audit rows but MAY NOT sign regulated decisions per URS-04 §6.7 / URS-05 BR-05-19. |
| DEC-06-21 | The `audit_event_policy_registry` (DEC-06-04 schema entry; §6.2 row) is the **canonical per-`action_code` policy** that drives default `severity`, periodic-review queue eligibility, cluster-detection rule binding, PII schema enforcement at the read surface, retention class, AI-source enforcement (where `ai_source_required = true` the `appendAuditRow` library refuses inserts that lack `ai_advisory = true` with `400 AI_ADVISORY_FLAG_REQUIRED`), and export permission. Every audit event code in the platform vocabulary MUST have exactly one active policy version. Policy changes are versioned, electronically signed, and audited via `AUDIT_EVENT_POLICY_PUBLISHED` / `AUDIT_EVENT_POLICY_RETIRED`. |
| DEC-06-22 | `chain_id` derivation rules are deterministic and unique per chain: per-entity chain `chain_id = SHA-256(tenant_id || ':' || entity_type || ':' || target_record_id)`; per-tenant chain `chain_id = SHA-256(tenant_id || ':PER_TENANT')`; global chain `chain_id = SHA-256('GLOBAL')`. The same inputs always produce the same `chain_id`. The hash form keeps `chain_id` opaque to consumers (no information leakage about tenant identifiers in cross-tenant manifests where the chain id is published). |
| DEC-06-23 | The `CHAIN_GENESIS` row is a **separate explicit anchor row** inserted at chain initialisation (tenant onboarding for `per_tenant`; new entity creation for `per_entity`; platform initialisation for `global`). It is distinct from the first domain event in the chain — for example, a `per_entity` chain for a CAPA has its `CHAIN_GENESIS` row at sequence 1, then the domain `CAPA_CREATED` event at sequence 2. The genesis row's `previous_hash` is deterministically derived from `chain_id || genesis_timestamp` per DEC-06-17. The genesis row's `details_jsonb` records the chain genesis inputs for inspection. There is no duplicate genesis-plus-created event; the pattern is exactly one `CHAIN_GENESIS` followed by the first domain event. |

---

## 3. User Roles and Permissions

### 3.1 Architecture

Module 6 consumes Layer 1 (base role) and Layer 2 (permission matrix) from URS-02; consumes the active context from URS-03; consumes the resolver from URS-05 for read-PII permission gating. Module 6 owns three administrative surfaces: (a) the audit read / export surface for tenant administrators and auditors, (b) the periodic-review reviewer surface, and (c) the integrity manifest viewer. Every authenticated user has access to read their own audit history through the "My activity" self-view, scoped to actions where the user is the actor or the acting-on-behalf-of party.

### 3.2 Role definitions

The five tenant-level base roles defined by URS-02 (`admin`, `quality_lead`, `reviewer`, `auditor`, `viewer`) and the two cross-tenant platform identities (`platform_admin`, `super_admin`) apply unchanged. A new permission `audit:read_pii` is introduced (consumed from URS-02) which gates access to PII fields in audit rows; without this permission, PII fields are masked at read time. External identities (URS-01 §3.2.3) MAY read audit rows scoped to their own activity (in the "My activity" self-view) but MAY NOT access tenant-wide audit reads.

### 3.3 Permission requirements consumed by Module 6

| Permission key | Module 6 surface gated |
|---|---|
| `audit:read` | Filtered audit read within own tenant; permission held by `auditor`, `quality_lead`, `admin` by default. |
| `audit:read_pii` | Unmasking PII fields in audit reads; permission held only by named auditor or `tenant_admin_authority` holder; access itself audited as `AUDIT_PII_ACCESSED`. |
| `audit:export` | Trigger export with electronic signature; permission held by `tenant_admin_authority` holder. |
| `audit:integrity_run` | Trigger on-demand integrity verifier; permission held by `tenant_admin_authority` holder and `auditor`. |
| `audit:periodic_review` | Periodic-review reviewer surface; permission held by `tenant_admin_authority` holder; reviewer cannot be the actor of the rows under review (BR-06-12). |
| `audit:annotate` | Append annotation to an audit row (separate `audit_annotations` chain); permission held by `tenant_admin_authority` holder. |
| `audit:platform_break_glass` | Cross-tenant audit read under controlled support / break-glass posture; permission held only by platform identity. |

### 3.4 Worked examples

#### Worked example A — A tenant administrator answers an inspector's question

An FDA inspector visits TenantCo and asks "show me everyone who held `qp_eu` for product family Alpha in the last 12 months and every release decision they signed." The tenant administrator opens the audit read surface, filters by `action_code IN ('AUTHORITY_PROFILE_ASSIGNED','AUTHORITY_PROFILE_REVOKED','ESIG_CREATED','APPROVAL_AUTHORITY_SNAPSHOT_WRITTEN')` AND `details->>'authority_profile_key' = 'qp_eu'` AND date range, exports the result through the Controlled Approval Modal with electronic signature, and receives a signed PDF + JSON bundle with an integrity manifest. The inspector verifies the manifest's chain HEAD hash matches the platform's published hash for the relevant chain. No further trust required.

#### Worked example B — Integrity verifier detects an INTEGRITY_VIOLATION

A scheduled monthly integrity run on the per-entity chain for batch BAT-2026-0145 detects that a recomputed `record_hash` at sequence 47 does not match the stored value. The verifier emits `INTEGRITY_VIOLATION`. Module 6 immediately quarantines the chain (read-only with banner), emits SOC alert, escalates to Founder, opens an incident per URS-04 §11. Forensic investigation begins. The tenant's batch records are flagged with the integrity-violation badge. Until the investigation closes, no signed export referencing the affected entity may be issued. The investigation determines whether the violation was a storage corruption (recoverable from URS-35 backup), an infrastructure-level access (incident-response per URS-04 §11.3), or a verifier defect (engineering correction).

#### Worked example C — AI-advisory row segregation

A MIRA copilot suggests a deviation root cause to the investigator. The suggestion is recorded as an audit row with `action_code = 'AI_SUGGESTION_GENERATED'`, `ai_advisory = true`, `details_jsonb = {suggestion: '...', confidence: 0.83, model: 'claude-opus-4-7', model_version: '...'}`. The investigator reviews the suggestion, modifies it, and electronically signs the deviation field. This produces a separate audit row with `action_code = 'DEVIATION_FIELD_UPDATED'`, `ai_advisory = false`, `e_sig_id = ...`, `details_jsonb = {field: 'root_cause', new_value: '...', source: 'human_modified_ai'}`. The read surface visually distinguishes the AI-advisory row from the human-signed row. The regulatory record never attributes the field value to the AI.

#### Worked example D — Cold-archive cross-window query

An auditor needs CAPA closure decisions from 2022. The hot audit log holds rows from the last 2 years; the 2022 rows are in cold storage. The auditor's filtered query reaches both tiers; cold rows return with higher latency and a tier badge. Integrity verification works seamlessly across both tiers. The audit row schema and chain hashes are preserved verbatim in cold storage.

#### Worked example E — Periodic audit-trail review of high-risk events

The weekly periodic-review queue surfaces 18 events tagged `severity = 'high'` or `'critical'`: three `AUTHORITY_OVERRIDE_USED`, two `SOD_EXCEPTION_APPROVED`, one `INTEGRITY_VERIFIER_RUN` with verdict `valid`, and twelve `PLATFORM_TENANT_ACCESS_USED` (a customer-support spike). The QA Director (independent of all the actors) opens each row, reviews the context including the linked electronic signature and the authority snapshot, attests review completion through the Controlled Approval Modal, and closes the queue for the week. The attestation pack is exported with electronic signature and integrity manifest.

#### Worked example F — Time-anomaly detection

A scheduled job detects that two recent audit rows from one Verixa application node have timestamps that drift 350 ms backward relative to the cluster's NTP reference. Module 6 emits `TIME_ANOMALY_DETECTED` with the node identifier, drift amount, and affected row identifiers. SOC investigates; the cause is a transient NTP synchronisation issue on that node. The affected rows are flagged for forensic review but not mutated; the chain remains intact.

#### Worked example G — Cryptographic erasure on GDPR right-to-erasure (key destruction; no row mutation)

A user invokes their GDPR right-to-erasure. Their `email` and `display_name` fields in past audit `details_jsonb` are subject to erasure; the `actor_user_id`, `e_sig_id`, `record_hash`, and `previous_hash` are NOT subject to erasure (they are required for regulatory record integrity per Article 17(3)(e) GDPR — "establishment, exercise, or defence of legal claims"). Module 6 performs erasure through **subject-key destruction**: every PII field in `audit_log.details_jsonb` was originally written as ciphertext encrypted under the user's per-subject data-encryption key. On right-to-erasure invocation, the tenant DPO authorises destruction through the Controlled Approval Modal; Module 6 destroys the per-subject key in the URS-key-management substrate; the ciphertext in every historical `audit_log` row remains in place but becomes permanently undecryptable. The historical `audit_log` rows are NOT modified; their `record_hash`, `previous_hash`, and chain linkage are completely unchanged; the integrity verifier continues to validate the chain end-to-end. A new `audit_log` row is appended with `action_code = 'PII_FIELD_ERASED'`, `details_jsonb` recording the regulatory basis, the DPO's `requested_e_sig_id`, the destroyed key reference, and the count of affected rows. The user's identifying information is no longer recoverable from the audit log, but the regulatory record of every action they performed persists with full chain integrity.

Where subject-key destruction is not technically feasible for a given field (e.g., very old rows written before per-subject encryption was introduced; cross-tenant aggregations), Module 6 uses the **append-only redaction overlay** mechanism per DEC-06-13b: a row is appended to `pii_redaction_overlays` referencing the affected `audit_log_id` and field paths; at read time, the read surface renders the redacted representation by joining the overlay; the original row is never modified.

### 3.5 Role-permission matrix (Module 6 surface only)

| Action (within Module 6) | viewer | reviewer | quality_lead | auditor | admin | platform_admin | super_admin | Permission |
|---|:-:|:-:|:-:|:-:|:-:|:-:|:-:|---|
| Read own activity ("My activity") | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | self |
| Read tenant audit log (filtered) | — | — | ✓ | ✓ | ✓ | ✓ | ✓ | `audit:read` |
| Read PII fields unmasked | — | — | — | per role | per role | per role | per role | `audit:read_pii` |
| Export tenant audit log | — | — | — | — | ✓ + sign | ✓ + sign | ✓ + sign | `audit:export` |
| Run on-demand integrity verifier | — | — | — | ✓ | ✓ | ✓ | ✓ | `audit:integrity_run` |
| Open periodic-review queue | — | — | — | — | ✓ + sign | ✓ + sign | ✓ + sign | `audit:periodic_review` (independent of actor) |
| Append annotation to audit row | — | — | — | — | ✓ + sign | ✓ + sign | ✓ + sign | `audit:annotate` |
| Cross-tenant audit read (break-glass) | — | — | — | — | — | ✓ + sign + business justification | ✓ + sign + business justification | `audit:platform_break_glass` |
| Read integrity manifest (own tenant) | — | — | — | ✓ | ✓ | ✓ | ✓ | `audit:read` |
| Initiate cryptographic erasure (GDPR / DPDP) | — | — | — | — | ✓ + sign + DPO authority | ✓ + sign | ✓ + sign | tenant DPO authority + `audit:annotate` |

External identities (URS-01 §3.2.3) MAY access only the "My activity" self-view of their own actions; they cannot reach the tenant-wide audit read surface or the integrity manifest viewer.

#### 3.5.1 Platform-identity tenant actions — controlled support / break-glass posture

Per URS-02 §3.6.1, platform identities (`platform_admin`, `super_admin`) MAY perform tenant-scoped Module 6 reads only under a controlled support / break-glass posture: target tenant identifier, business-justification reason, support-ticket / customer-reference identifier, electronic signature, `PLATFORM_TENANT_ACCESS_USED` audit emit (in the global chain AND a notification audit row in the target tenant's per-tenant chain), Security Operations Centre alert, customer notification within 24 hours per privacy policy. Use outside the envelope returns `PLATFORM_TENANT_ACCESS_DENIED`.

---

## 4. End-to-End User Journeys

### J-01 — Module mutation triggers atomic audit write

- Trigger: any URS-01..URS-35 module mutates a record.
- Steps: consuming module begins transaction; performs the originating mutation; calls `appendAuditRow` with the audit row content (action code, entity, details, e_sig_id, authority_snapshot_id, ai_advisory flag); Module 6 acquires the appropriate advisory lock, reads the chain HEAD `record_hash`, composes the audit row with `previous_hash`, computes `record_hash` from canonical JSON, inserts the row, releases the lock on commit. Failure to insert rolls back the originating mutation.
- Audit: the audit row itself is the audit; reads of the row are not audited (DEC-06-09); export is.

```mermaid
sequenceDiagram
  autonumber
  participant CM as Consuming Module
  participant DB as Database (transaction)
  participant M6 as Module 6 appendAuditRow
  participant LOCK as Advisory Lock
  participant CHAIN as Chain HEAD

  CM->>DB: BEGIN TRANSACTION
  CM->>DB: INSERT / UPDATE originating record
  CM->>M6: appendAuditRow(content)
  M6->>LOCK: pg_advisory_xact_lock for chain scope
  M6->>CHAIN: read HEAD record_hash
  M6->>M6: compose canonical JSON; compute record_hash
  M6->>DB: INSERT audit row
  M6-->>CM: row id
  CM->>DB: COMMIT
  DB-->>CM: success (lock released)
```

### J-02 — Auditor filtered read

- Trigger: auditor opens audit viewer.
- Steps: auditor enters filters (tenant scope inherited; action_code, entity, user, date range); Module 6 returns paginated rows; PII masked unless the auditor holds `audit:read_pii`; reads are not themselves audited.
- Audit: none for read; `AUDIT_LOG_VIEW_OPENED` is emitted as a coarse-grain forensic indicator with no per-row capture.

### J-03 — Auditor electronically signed export

- Trigger: auditor decides to export the filtered query result.
- Steps: auditor clicks "Export"; Controlled Approval Modal requires electronic signature; Module 6 runs integrity verifier scoped to the export's chain footprint; verdict captured in manifest; export bundle composed (PDF + machine-readable JSON); signed download URL with 15-minute TTL returned; integrity manifest accompanies the bundle, countersigned by the platform's signing key.
- Audit: `AUDIT_LOG_EXPORTED` with the manifest reference.

```mermaid
flowchart TD
  A[Auditor clicks Export] --> B[Controlled Approval Modal opens]
  B --> C[Auditor enters password meaning reason]
  C --> D[Run integrity verifier scoped to export footprint]
  D --> E{All chains valid?}
  E -- no --> X[Block export; emit INTEGRITY_VIOLATION; SOC alert]
  E -- yes --> F[Compose export bundle PDF + JSON]
  F --> G[Compose integrity manifest with chain HEAD hashes verifier verdict content fingerprint]
  G --> H[Countersign manifest with platform signing key and optional RFC 3161 timestamp]
  H --> I[Issue signed download URL TTL 15 minutes]
  I --> J[Emit AUDIT_LOG_EXPORTED]
```

### J-04 — On-demand integrity verifier run

- Trigger: tenant administrator or auditor wants to verify a chain.
- Steps: opens integrity manifest viewer; enters chain identifier (entity / tenant / global); clicks "Verify"; Module 6 walks the chain from genesis (or specified offset) to HEAD; reports row-by-row verdicts and overall verdict; output is itself audited.
- Audit: `INTEGRITY_VERIFIER_RUN` with verdict, chain identifier, sequence range.

### J-05 — Scheduled monthly integrity run

- Trigger: scheduled job at month-end.
- Steps: Module 6 enumerates all chains with activity in the past 31 days; runs the verifier on each; emits `INTEGRITY_VERIFIER_RUN` per chain. `INTEGRITY_VIOLATION` triggers SOC alert + executive authority escalation + chain quarantine.
- Audit: per-chain `INTEGRITY_VERIFIER_RUN`.

### J-06 — INTEGRITY_VIOLATION incident response

- Trigger: verifier detects a hash mismatch.
- Steps: Module 6 immediately marks the chain `quarantined = true` (read-only banner); emits `INTEGRITY_VIOLATION` to URS-30 SOC channel; escalates to Founder within one business hour; opens incident per URS-04 §11; affected entity records get visual integrity-violation badges; signed exports referencing the affected chain are blocked; investigation begins. Investigation determines: (a) storage corruption (restore from URS-35; re-verify), (b) unauthorised infrastructure access (incident response; customer notification), or (c) verifier defect (engineering correction; chain not actually corrupted).
- Audit: `INTEGRITY_VIOLATION` + `CHAIN_QUARANTINED` + downstream incident codes.

### J-07 — Hot-to-cold archival run

- Trigger: scheduled archival job.
- Steps: Module 6 enumerates audit rows older than two years; copies them to URS-35 cold storage with object-lock immutability; the cold copy preserves `record_hash` and `previous_hash` verbatim; the hot copy is removed only after URS-35 confirms successful archival and re-verifies the hash; cold rows remain query-accessible.
- Audit: `AUDIT_ROW_ARCHIVED_TO_COLD` (aggregate per archival run).

### J-08 — Periodic audit-trail review

- Trigger: weekly review window opens.
- Steps: reviewer opens periodic-review queue; system enumerates events tagged `severity in ('high','critical')` from the past 7 days; reviewer attests each row through the Controlled Approval Modal; cluster-detection rules emit `HIGH_RISK_EVENT_CLUSTER_DETECTED` and escalate to Founder where thresholds are crossed; at window close, attestation pack is electronically signed and exported.
- Audit: `PERIODIC_AUDIT_REVIEW_OPENED`, `PERIODIC_AUDIT_REVIEW_ROW_ATTESTED`, `PERIODIC_AUDIT_REVIEW_CLOSED`, `PERIODIC_AUDIT_REVIEW_ATTESTATION_EXPORTED`.

### J-09 — Cluster detection escalates to Founder

- Trigger: three `AUTHORITY_OVERRIDE_USED` events from the same tenant within 7 days.
- Steps: cluster-detection rule fires; URS-30 escalates to Founder within one business day; Founder opens the underlying authority-of-record case (URS-05 J-23); decision recorded.
- Audit: `HIGH_RISK_EVENT_CLUSTER_DETECTED`.

### J-10 — User self-view ("My activity")

- Trigger: user wants to see their own activity history.
- Steps: user opens "My activity"; system filters audit log by `actor_user_id = self OR acting_on_behalf_of_user_id = self`; PII masked unless the user holds `audit:read_pii` (which they would not for other users' rows; their own rows are unmasked by default). Useful for self-service explanation of "what did I do?" and for forensic discovery.
- Audit: read is not audited.

### J-11 — Audit annotation appended

- Trigger: tenant administrator notices an audit row needs additional context (e.g., "this override was approved per CC-2026-0098").
- Steps: administrator opens the row; selects "Annotate"; Controlled Approval Modal; administrator enters annotation text; Module 6 inserts a row in `audit_annotations` (separate append-only chain) referencing the original audit row by id; annotation never mutates the original.
- Audit: `AUDIT_ANNOTATION_APPENDED`.

### J-12 — External anchoring publication

- Trigger: scheduled weekly anchoring job.
- Steps: Module 6 reads the HEAD `record_hash` of every chain (or per-tenant aggregate of per-entity chains where the tenant has many records); publishes the manifest to (a) regulator-readable platform manifest endpoint signed by Founder, (b) customer-readable tenant manifest endpoint signed by Verixa platform, (c) optional RFC 3161 time-stamp authority where the tenant elects.
- Audit: `EXTERNAL_ANCHOR_PUBLISHED`.

### J-13 — Time-anomaly detection

- Trigger: scheduled job.
- Steps: Module 6 compares `timestamp` of recent rows against the cluster's NTP reference; drifts beyond bounds emit `TIME_ANOMALY_DETECTED`; SOC investigates; suspect rows are flagged for forensic review without mutation.
- Audit: `TIME_ANOMALY_DETECTED`.

### J-14 — Cryptographic erasure on right-to-erasure request (no row mutation)

- Trigger: GDPR / DPDP / other applicable jurisdiction right-to-erasure invocation.
- Steps: tenant Data Protection Officer (or equivalent) authorises the erasure through the Controlled Approval Modal; Module 6 selects the erasure mechanism per DEC-06-13: **(a) subject-key destruction** (default): the user's per-subject data-encryption key is destroyed in the URS-key-management substrate; ciphertext in historical `audit_log` rows becomes permanently undecryptable while the rows themselves remain unmodified; or **(b) append-only redaction overlay** (fallback): a row is appended to `pii_redaction_overlays` referencing the affected `audit_log_id` and field paths so that the read surface renders the redacted representation at query time. **In neither case is any historical `audit_log` row updated or deleted.** A new `audit_log` row is appended with `action_code = 'PII_FIELD_ERASED'` capturing the regulatory basis, the DPO's `requested_e_sig_id`, the mechanism used, and the affected row count. Chain integrity is preserved by construction because the rows that the chain commits over are never modified.
- Audit: `PII_FIELD_ERASED` (new row) with affected row count, field paths, and erasure mechanism (no PII content in the audit row itself).

### J-15 — Cross-tenant break-glass read by platform identity

- Trigger: customer-support escalation.
- Steps: platform identity opens the controlled-support surface; selects target tenant; provides business-justification reason and customer-reference identifier; signs through the Controlled Approval Modal; emits `PLATFORM_TENANT_ACCESS_USED` (in global chain) and a notification row in the tenant's per-tenant chain; performs filtered read; customer notification within 24 hours per privacy policy.
- Audit: `PLATFORM_TENANT_ACCESS_USED` (global) + `PLATFORM_TENANT_ACCESS_NOTIFIED` (tenant).

### J-16 — Backup-restore drill chain integrity

- Trigger: scheduled URS-35 disaster-recovery drill.
- Steps: URS-35 restores a snapshot to a non-production environment; Module 6 runs the integrity verifier on every chain in the restored database; verdict MUST be `valid` and chain HEAD MUST match the source chain HEAD verbatim; mismatch is a release blocker.
- Audit: `INTEGRITY_VERIFIER_RUN` (in the restore environment; not in production audit log).

### J-17 — Inspector requests historical audit pack

- Trigger: regulatory inspection.
- Steps: tenant administrator opens audit read surface; filters by inspector's criteria (date range, entity types, users, action codes); runs integrity verification on the result footprint; exports with electronic signature; receives signed PDF + JSON bundle with integrity manifest; provides the bundle plus the platform's published external anchor for the relevant period; the inspector verifies that the manifest's chain HEAD matches the platform's anchor at the time of inspection.
- Audit: `AUDIT_LOG_EXPORTED`.

### J-18 — Audit row tagged AI-advisory

- Trigger: AI suggestion produced.
- Steps: the AI-emitting module (e.g., MIRA) calls `appendAuditRow` with `action_code = 'AI_SUGGESTION_GENERATED'`, `ai_advisory = true`, model details in `details_jsonb`. The human acceptance path produces a separate audit row with `ai_advisory = false` and the human's `e_sig_id`. The read surface visually distinguishes both rows.
- Audit: `AI_SUGGESTION_GENERATED` (advisory) + `AI_SUGGESTION_ACCEPTED` or domain-specific signature row (non-advisory).

### J-19 — Tenant administrator initiates retention extension

- Trigger: tenant determines they need 10 years retention instead of 7 for a specific tenant scope (e.g., long-term clinical study).
- Steps: tenant administrator opens retention configuration; selects scope and increases retention to 10 years (longer than launch default; allowed); signs through the Controlled Approval Modal; configuration takes effect for new rows and for existing rows that have not yet aged out of the original 7-year window.
- Audit: `RETENTION_POLICY_UPDATED`.

### J-20 — Genesis row at tenant onboarding

- Trigger: new tenant onboarded.
- Steps: URS-08 onboarding completes; Module 6 inserts the `CHAIN_GENESIS` row in the new per-tenant chain with `previous_hash` = SHA-256(tenant_id || onboarding_timestamp); the chain is now anchored.
- Audit: `CHAIN_GENESIS`.

### J-21 — Genesis row at new entity creation

- Trigger: a new regulated entity (e.g., a CAPA) is created.
- Steps: the consuming module emits its `<ENTITY>_CREATED` event; Module 6 inserts a `CHAIN_GENESIS` row for the per-entity chain with `previous_hash` = SHA-256(tenant_id || entity_type || target_record_id || creation_timestamp); the chain is now anchored.
- Audit: `CHAIN_GENESIS` (entity-scope).

### J-22 — Auditor verifies external anchor

- Trigger: external auditor wants to confirm a chain HEAD has not been altered since publication.
- Steps: auditor reads the platform's external manifest (regulator endpoint or customer endpoint); compares the published HEAD `record_hash` for the chain against the on-platform integrity manifest exported with electronic signature; if equal, the chain has not been altered since the anchor was published.
- Audit: `INTEGRITY_VERIFIER_RUN` if the auditor also runs the verifier on demand.

### J-23 — Audit row referenced by URS-04 electronic signature

- Trigger: any electronic signature.
- Steps: URS-04 begins signature ceremony; calls Module 6 `appendAuditRow` for the `ESIG_CREATED` event; the audit row id is returned; URS-04 stores `audit_log_id` on the `electronic_signatures` row and `audit_log_id` on the `approval_authority_snapshots` row; bidirectional referential integrity established. The export integrity manifest can verify that for every `ESIG_CREATED` audit row, the referenced `electronic_signatures.audit_log_id` matches.
- Audit: `ESIG_CREATED` (URS-04 owns the writer; Module 6 owns the chain insert path).

### J-24 — Audit query timeout / pagination

- Trigger: auditor runs an unbounded date-range query.
- Steps: query executor enforces pagination with a hard limit (e.g., 10,000 rows per page); query exceeding overall scan budget (e.g., > 30 seconds) returns partial result with a continuation token and `QUERY_PARTIAL_RESULTS` warning; auditor refines filter or paginates; cold-tier queries are flagged with higher latency badge.
- Audit: not applicable.

### J-25 — Annotation cannot mutate original

- Trigger: an attacker attempts to "edit" an audit row via the annotation API by submitting an annotation that overwrites the original.
- Steps: API rejects with `403 ANNOTATION_CANNOT_MUTATE_ORIGINAL`; the annotation API only inserts to the separate `audit_annotations` table; the original row is untouched.
- Audit: rejection is logged at API layer for forensic.

### J-26 — Cluster detection cooldown to avoid alert storms

- Trigger: a single root cause produces 50 high-severity events within an hour.
- Steps: cluster-detection rule fires once on the first cluster threshold cross; subsequent events of the same kind from the same tenant within a cooldown window (default 30 minutes) are aggregated into the same incident; cooldown configurable per rule.
- Audit: `HIGH_RISK_EVENT_CLUSTER_DETECTED` once per cooldown window.

### J-27 — Forensic chain-rebuild from URS-35 backup

- Trigger: production storage corruption suspected for an entity chain.
- Steps: SOC restores the relevant portion of the database from URS-35 backup to a forensic environment; Module 6 verifier runs on the restored chain; if valid, the production chain is replaced from backup (this is itself a controlled change-management event with Founder approval); if invalid in both production and backup, the violation is escalated to a regulatory disclosure decision.
- Audit: per the change-management event; Module 6 emits `CHAIN_RESTORED_FROM_BACKUP` upon completion.

### J-28 — Tenant offboarding chain finalisation

- Trigger: tenant terminates service; URS-08 offboarding workflow runs.
- Steps: per-tenant and per-entity chains are sealed (no further inserts); chain HEAD hashes are anchored externally one final time; chain content is exported with electronic signature for the tenant's records; data is retained per residency / contract terms (typically 7-25 years) in cold storage with object-lock immutability; the tenant retains read access through a designated archive surface.
- Audit: `TENANT_CHAINS_SEALED_AT_OFFBOARDING`.

---

## 5. Front-End Expected State

### 5.1 Routes (registered in the application router)

| Route | Surface | Role / Authority gate | Notes |
|---|---|---|---|
| `/audit/inbox` | Audit viewer with filters | `audit:read` | tenant-scoped |
| `/audit/integrity` | Integrity manifest viewer | `audit:read` | per-chain |
| `/audit/integrity/run` | On-demand integrity verifier surface | `audit:integrity_run` | electronically signed action |
| `/audit/export` | Export wizard | `audit:export` | electronically signed |
| `/audit/periodic-review` | Periodic-review reviewer surface | `audit:periodic_review` | independent of actor |
| `/audit/me` | "My activity" self-view | self | scoped to caller |
| `/audit/annotation/:rowId` | Annotation surface | `audit:annotate` | electronically signed |
| `/admin/audit/retention` | Retention configuration | `tenant_admin_authority` + electronic signature | tenant-scoped |
| `/admin/audit/erasure` | GDPR / DPDP erasure surface | tenant DPO authority + `audit:annotate` + electronic signature | tenant-scoped |
| `/platform/audit/break-glass` | Cross-tenant break-glass read | platform identity + electronic signature + business justification | controlled support posture |
| `/platform/audit/external-anchors` | External anchoring management | platform identity | global manifest publication |

### 5.2 Component requirements

- **Audit viewer** — high-density paginated table with filter chips (action_code, entity_type, user, date range, severity, ai_advisory flag, chain_scope, integrity_status); each row shows compact summary + click-to-expand detail panel with full `details_jsonb`, `ip_address`, `user_agent`, `e_sig_id` link, `authority_snapshot_id` link, `previous_hash`, `record_hash`, `chain_sequence`, integrity badge (valid / quarantined). PII fields masked unless `audit:read_pii` held.
- **Integrity manifest viewer** — input: chain identifier; output: chain HEAD hash, last verifier-run timestamp and verdict, sample of intermediate hashes, badge (valid / quarantined / never-verified). Sub-action: "Verify now" runs the on-demand verifier (gated by `audit:integrity_run`).
- **On-demand integrity verifier** — submission form with chain scope selector, optional offset and end-sequence; Controlled Approval Modal; output: verifier result rendered as a streaming table (one row per audit row verified); summary verdict.
- **Export wizard** — filter selection → review of result count → integrity-pre-check (verifier runs scoped to footprint) → Controlled Approval Modal → signed download URL with TTL; integrity manifest accompanies the bundle.
- **Periodic-review reviewer surface** — wizard-like row-by-row attestation; each row: compact event summary + linked context (e_sig, authority snapshot, original record); reviewer decision (attested / requires-investigation / escalate-to-founder); progress indicator; final attestation export.
- **"My activity" self-view** — sections: Recent activity (last 90 days), High-risk activity (any with `severity = 'high'`), Authority-related activity (assignments, delegations), Signature activity (every signature the user produced or received).
- **Annotation surface** — text input for annotation; Controlled Approval Modal; annotation appears as a separate distinguished row appended to a parallel `audit_annotations` chain referencing the original.
- **Retention configuration** — per-scope retention sliders / pickers; minimum retention is the launch default; longer retention permitted; shorter forbidden.
- **Erasure surface** — shows the candidate fields that would be erased; confirms regulatory basis (GDPR Art 17 / DPDP / etc.); Controlled Approval Modal; mechanism selection (subject-key destruction default, redaction-overlay fallback per DEC-06-13); execution leaves every historical `audit_log` row unmodified.
- **Cross-tenant break-glass surface** — target tenant selector + business-justification + customer-reference identifier + Controlled Approval Modal with multi-factor step-up; clear visual indication that the action is platform-level.

### 5.3 Accessibility and internationalisation

- WCAG 2.1 Level AA across every Module 6 surface.
- Every event-code description translated; the `action_code` itself stays canonical English.
- Date / time displayed in user time zone; stored UTC; ISO 8601.
- Hash values displayed as truncated by default (first 8 + last 8 chars) with click-to-expand full hex; copy-to-clipboard supported.

---

## 6. Back-End Expected State

### 6.1 Domain entities

- `audit_log` — the universal append-only WORM table.
- `audit_chain_heads` — current HEAD pointer per chain (per-entity / per-tenant / global) with `chain_id`, `chain_scope`, `head_audit_log_id`, `head_record_hash`, `chain_sequence`, `last_verified_at`, `last_verified_verdict`, `quarantined_at`, `quarantine_reason`.
- `audit_annotations` — append-only annotation chain (separate from `audit_log`); annotations reference the original audit row by id.
- `audit_chain_genesis` — per-chain genesis row metadata (the genesis row itself lives in `audit_log`; this table records the deterministic `previous_hash` derivation inputs for inspection).
- `external_anchors` — per-anchoring-event manifest containing per-tenant Merkle root (over all active per-entity chain HEADs for the tenant), per-tenant chain HEAD hash, and global chain HEAD hash, published to regulator / customer / RFC 3161 endpoints.
- `tenant_merkle_aggregates` — per-tenant per-anchor-cycle Merkle aggregation: stores the Merkle tree leaves (active per-entity chain HEADs at aggregation time), the intermediate node hashes, and the computed root; supports Merkle-proof generation for export manifests.
- `audit_event_policy_registry` — canonical per-`action_code` policy registry that drives default `severity`, periodic-review eligibility, cluster-detection rule binding, PII schema, retention class, AI-source enforcement, and export permission. Every audit event code in the platform vocabulary has exactly one active policy version. Policy changes are versioned, electronically signed, and audited.
- `integrity_verifier_runs` — log of verifier runs (scheduled + on-demand) with verdict, sequence range, and any violation details.
- `retention_policy_configs` — per-tenant per-scope retention configuration (immutable per version with electronic signature).
- `time_anomaly_detections` — log of detected clock-drift events (for SOC review).
- `pii_field_erasures` — log of erasure events (no row mutation; index of when and by what mechanism erasure was performed).
- `pii_redaction_overlays` — append-only read-time redaction overlay table that drives read-time PII redaction without modifying any `audit_log` row (DEC-06-13b).
- `cold_archive_manifest` — per-archival-run manifest of rows moved hot-to-cold (URS-35 owns the cold storage; Module 6 owns the manifest).

### 6.1.1 Diagram 6.1-A — Module 6 entity-relationship overview

```mermaid
erDiagram
  AUDIT_LOG ||--o{ AUDIT_ANNOTATIONS : annotated_by
  AUDIT_LOG }o--o| ELECTRONIC_SIGNATURES : referenced_by_e_sig_id
  AUDIT_LOG }o--o| APPROVAL_AUTHORITY_SNAPSHOTS : referenced_by_authority_snapshot_id
  AUDIT_CHAIN_HEADS ||--|| AUDIT_LOG : head_points_to
  AUDIT_CHAIN_GENESIS ||--|| AUDIT_LOG : genesis_row_in
  EXTERNAL_ANCHORS }o--|| AUDIT_CHAIN_HEADS : anchors_head_at_publish_time
  INTEGRITY_VERIFIER_RUNS }o--|| AUDIT_CHAIN_HEADS : verifies_chain
  RETENTION_POLICY_CONFIGS ||--o{ AUDIT_LOG : applied_to
  TIME_ANOMALY_DETECTIONS }o--o{ AUDIT_LOG : flags_rows
  PII_FIELD_ERASURES }o--o{ AUDIT_LOG : erases_fields_in
  COLD_ARCHIVE_MANIFEST }o--o{ AUDIT_LOG : archives_rows
```

The `ELECTRONIC_SIGNATURES` and `APPROVAL_AUTHORITY_SNAPSHOTS` entities are owned by URS-04 and URS-05 respectively; this diagram shows the cross-module references. Bidirectional referential integrity per DEC-06-18 means `AUDIT_LOG.id` is referenced by `ELECTRONIC_SIGNATURES.audit_log_id` and `APPROVAL_AUTHORITY_SNAPSHOTS.audit_log_id`, while `AUDIT_LOG.e_sig_id` and `AUDIT_LOG.authority_snapshot_id` reference the corresponding URS-04 / URS-05 rows.

### 6.1.2 Diagram 6.1-B — Hash-chain insert path with advisory lock

```mermaid
sequenceDiagram
  autonumber
  participant CALLER as Consuming Module
  participant M6 as Module 6 appendAuditRow
  participant LOCK as pg_advisory_xact_lock
  participant HEAD as audit_chain_heads
  participant LOG as audit_log

  CALLER->>M6: appendAuditRow tenant_id, chain_scope, entity_type, target_record_id, content
  M6->>M6: derive lock_key from chain_scope + tenant + entity
  M6->>LOCK: acquire pg_advisory_xact_lock(lock_key)
  M6->>HEAD: SELECT head_record_hash, chain_sequence FOR UPDATE
  M6->>M6: compose canonical JSON of content
  M6->>M6: record_hash = SHA-256(previous_hash || canonical_json)
  M6->>LOG: INSERT row id, content, previous_hash, record_hash, chain_sequence+1, timestamp
  M6->>HEAD: UPDATE head_audit_log_id, head_record_hash, chain_sequence
  M6-->>CALLER: row id
  Note over LOCK: Lock released on transaction COMMIT or ROLLBACK
```

### 6.1.3 Diagram 6.1-C — Three chain scopes

```mermaid
graph TD
  subgraph PER_ENTITY [Per-entity chains]
    PE1[capa-2026-0044 chain]
    PE2[deviation-2026-0145 chain]
    PE3[batch-bat-2026-0998 chain]
    PE4[CAPA-2026-0044 events sequence 1 .. n]
    PE1 --> PE4
  end
  subgraph PER_TENANT [Per-tenant chain]
    PT1[tenant-A chain]
    PT2[Authority assignments / catalogue changes / periodic-review events]
    PT1 --> PT2
  end
  subgraph GLOBAL [Global chain]
    G1[global chain]
    G2[Tier-1 catalogue changes / platform admin actions / external anchors]
    G1 --> G2
  end
  PE1 -.tenant binding.-> PT1
  PE2 -.tenant binding.-> PT1
```

### 6.1.4 Diagram 6.1-D — Integrity verifier walk

```mermaid
flowchart TD
  S[Start verifier scope chain_id, start_sequence default 1, end_sequence default HEAD] --> R[Read genesis row at sequence start_sequence]
  R --> CMP1{Compute SHA-256(previous_hash, canonical_json) equal stored record_hash?}
  CMP1 -- no --> X[INTEGRITY_VIOLATION at this sequence; emit alert]
  CMP1 -- yes --> NEXT[Advance to next sequence]
  NEXT --> END{End reached?}
  END -- no --> CMP2{prev_record_hash equal current row's previous_hash AND SHA-256 matches stored record_hash?}
  CMP2 -- no --> X
  CMP2 -- yes --> NEXT
  END -- yes --> V[Verdict valid, emit INTEGRITY_VERIFIER_RUN with valid]
```

### 6.1.5 Diagram 6.1-E — Hot-to-cold archival bridge

```mermaid
flowchart LR
  HOT[Hot partitions postgres rows newer than 2 years] --> SCAN[Archival scanner selects partition older than 2 years]
  SCAN --> SEAL[Seal partition no new INSERT allowed]
  SEAL --> COPY[Copy sealed partition to URS-35 cold storage object-lock immutable]
  COPY --> VERIFY[URS-35 re-computes record_hash from cold copy and compares to hot]
  VERIFY -->|equal| DETACH[ALTER TABLE DETACH PARTITION CONCURRENTLY]
  VERIFY -->|mismatch| ALERT[ARCHIVAL_HASH_MISMATCH; SOC alert; abort detach]
  DETACH --> DROP[Drop detached partition at storage layer; never row-level DELETE]
  DROP --> VIEW[Logical audit_log view continues to span hot + cold; queries on archived rows reach cold tier with latency badge]
```

### 6.2 Data model requirements

| Entity | Purpose | Key fields | Required | Unique | Tenant isolation | Versioning | Retention | Soft-delete | Audit | E-sig link |
|---|---|---|---|---|---|---|---|---|---|---|
| `audit_log` | Universal append-only WORM audit log | `id`, `tenant_id` (nullable for global chain), `chain_scope` (`per_entity` / `per_tenant` / `global`), `chain_id` (composite identifier deterministic from scope + tenant + entity), `chain_sequence` (bigint monotonic per chain), `entity_type` (nullable), `target_record_id` (nullable), `actor_user_id` (nullable; named system identity allowed), `acting_on_behalf_of_user_id` (nullable), `action_code`, `details_jsonb`, `ip_address` (nullable for system), `user_agent` (nullable for system), `correlation_id`, `e_sig_id` (nullable), `authority_snapshot_id` (nullable), `ai_advisory` (boolean default false), `severity` (enum: `informational` / `warning` / `high` / `critical`), `pii_fields` (string array of jsonb paths within `details_jsonb` that contain PII), `timestamp` (TIMESTAMPTZ; server-set DEFAULT NOW()), `previous_hash` (bytea / hex), `record_hash` (bytea / hex) | all per-state required: id, tenant_id (nullable per scope), chain_scope, chain_id, chain_sequence, action_code, timestamp, previous_hash, record_hash always; `entity_type` and `target_record_id` required for `per_entity`; per-permission fields optional | unique(`chain_id`, `chain_sequence`); unique(`record_hash`) | RLS on `tenant_id` (NULL for global chain row visible only to platform identity) | append-only; immutable; database-level grants prohibit UPDATE / DELETE for all application roles; storage object-lock on archived | seven years standard / twenty-five years where `authority_snapshot_id` is non-null | not applicable | self | yes (where applicable) |
| `audit_chain_heads` | Current HEAD pointer per chain | `chain_id`, `chain_scope`, `tenant_id` (nullable), `head_audit_log_id`, `head_record_hash`, `chain_sequence`, `last_verified_at` (nullable), `last_verified_verdict` (nullable; `valid` / `INTEGRITY_VIOLATION` / `pending`), `quarantined_at` (nullable), `quarantine_reason` (nullable), `created_at` | core required (genesis populates) | unique(`chain_id`) | RLS via tenant where applicable | mutable HEAD pointer (the row is updated as new audit rows are inserted, transactionally with the corresponding `audit_log` insert per BR-06-22) | retain | not applicable | **HEAD-pointer updates as part of normal `appendAuditRow` execution are NOT separately audited per insert** (BR-06-22) — the chain HEAD's authoritative history is reconstructable from `audit_log.chain_sequence` ordering, which avoids recursive self-audit. Administrative changes to `audit_chain_heads` (chain quarantine, chain repair, chain restoration from backup) ARE audited via `CHAIN_QUARANTINED`, `CHAIN_RESTORED_FROM_BACKUP`. | not applicable |
| `audit_annotations` | Append-only annotation chain | `id`, `tenant_id`, `audit_log_id` (FK), `annotator_user_id`, `annotation_text`, `annotation_e_sig_id`, `created_at`, `previous_hash`, `record_hash`, `chain_sequence` (separate annotation chain per audit row's chain) | all | unique(`record_hash`); unique(`tenant_id`, `audit_log_id`, `chain_sequence`) | RLS on `tenant_id` | append-only | seven years | not applicable | yes | yes |
| `audit_chain_genesis` | Per-chain genesis metadata | `chain_id`, `chain_scope`, `genesis_audit_log_id`, `genesis_previous_hash_inputs_jsonb` (records the deterministic inputs: tenant_id / entity_type / target_record_id / genesis_timestamp), `created_at` | all | unique(`chain_id`) | RLS via tenant where applicable | append-only | retain | not applicable | yes | not applicable |
| `external_anchors` | Per-anchoring-event manifest | `id`, `anchored_at`, `chain_scope` (`global` / `per_tenant` / `per_tenant_merkle_root`), `chain_id` (nullable for `global`; tenant_id for `per_tenant` and `per_tenant_merkle_root`), `head_record_hash` (chain HEAD for `global`/`per_tenant`; Merkle root for `per_tenant_merkle_root`), `head_chain_sequence` (nullable for `per_tenant_merkle_root`), `tenant_merkle_aggregate_id` (nullable; FK to `tenant_merkle_aggregates` for `per_tenant_merkle_root`), `regulator_manifest_url`, `customer_manifest_url`, `rfc3161_token` (nullable), `signed_by_e_sig_id` (Founder-level for regulator manifest; platform-level for customer manifest) | all | none | scope-appropriate | append-only | retain (long-term) | not applicable | yes | yes |
| `tenant_merkle_aggregates` | Per-tenant per-anchor-cycle Merkle aggregation | `id`, `tenant_id`, `aggregated_at`, `leaf_count`, `leaves_jsonb` (jsonb array of `{chain_id, head_record_hash, head_chain_sequence}` for every active per-entity chain at aggregation time, in deterministic order), `intermediate_nodes_jsonb` (Merkle tree intermediate hashes), `merkle_root_hash`, `previous_aggregate_hash` (nullable; SHA-256 chain across consecutive aggregates per tenant), `record_hash` | all | unique(`tenant_id`, `aggregated_at`); unique(`record_hash`) | RLS on `tenant_id` | append-only | retain (long-term) | not applicable | yes | not applicable |
| `integrity_verifier_runs` | Verifier run log | `id`, `chain_id`, `chain_scope`, `start_sequence`, `end_sequence`, `verdict` (`valid` / `INTEGRITY_VIOLATION`), `violation_at_sequence` (nullable), `violation_details_jsonb` (nullable), `triggered_by` (`scheduled` / `on_demand` / `export_pre_check` / `restore_drill`), `triggered_by_user_id` (nullable), `started_at`, `completed_at`, `duration_ms` | all | none | scope-appropriate | append-only | seven years | not applicable | yes | not applicable |
| `retention_policy_configs` | Per-tenant per-scope retention configuration | `id`, `tenant_id`, `scope` (e.g., `audit_default` / `authority_snapshot` / `per_entity_capa`), `retention_years`, `effective_from`, `effective_to` (nullable), `set_by_user_id`, `set_e_sig_id`, `created_at` | all | unique active(`tenant_id`, `scope`) | RLS on `tenant_id` | versioned | retain | not applicable | yes | yes |
| `time_anomaly_detections` | Clock-drift event log | `id`, `detected_at`, `node_identifier`, `drift_milliseconds`, `affected_audit_log_ids` (jsonb array), `status` (`open` / `investigated` / `closed`), `closed_by` (nullable), `closure_notes` (nullable) | core required | none | global | append-only | seven years | not applicable | yes | not applicable |
| `pii_field_erasures` | Erasure-event log (no row mutation; index of erasure events) | `id`, `tenant_id`, `target_user_id`, `regulatory_basis` (`gdpr_art_17` / `dpdp_section_12` / `other`), `mechanism` (`subject_key_destruction` / `redaction_overlay`), `affected_audit_log_count`, `affected_field_paths_jsonb`, `destroyed_key_reference` (nullable; populated for `subject_key_destruction`), `overlay_chain_head_at_erasure` (nullable; populated for `redaction_overlay`), `requested_by_dpo_user_id`, `requested_e_sig_id`, `executed_at`, `executed_by_system_actor` | all | unique(`tenant_id`, `target_user_id`, `requested_e_sig_id`) | RLS on `tenant_id` | append-only | retain (long-term) | not applicable | yes | yes |
| `pii_redaction_overlays` | Append-only read-time redaction overlay (DEC-06-13b) | `id`, `tenant_id`, `audit_log_id` (FK), `redacted_field_paths_jsonb` (jsonb-path strings within the original `details_jsonb`), `regulatory_basis`, `requested_e_sig_id`, `executed_at`, `executed_by_system_actor`, `chain_sequence` (parallel overlay chain), `previous_hash`, `record_hash` | all | unique(`tenant_id`, `audit_log_id`, `redacted_field_paths_jsonb`); unique(`record_hash`) | RLS on `tenant_id` | append-only | retain (long-term) | not applicable | yes | yes |
| `cold_archive_manifest` | Per-archival-run manifest | `id`, `archival_run_id`, `tenant_id` (nullable), `chain_scope`, `chain_id`, `archived_sequence_start`, `archived_sequence_end`, `archived_row_count`, `archive_started_at`, `archive_completed_at`, `urs35_storage_reference`, `verifier_verdict_post_archive` (`valid` / `INTEGRITY_VIOLATION`), `triggered_by_system_actor` | all | none | scope-appropriate | append-only | retain | not applicable | yes | not applicable |
| `audit_event_policy_registry` | Per-`action_code` policy registry driving severity, review queue, clustering, PII masking, AI flag enforcement, retention class, export permission | `id`, `action_code`, `originating_module`, `version` (integer monotonic per action_code), `default_severity` (`informational` / `warning` / `high` / `critical`), `review_required` (boolean; whether the row appears in the periodic-review queue), `cluster_rule_id` (nullable; FK to `cluster_detection_rules` if applicable), `pii_schema_jsonb` (jsonb-paths within `details_jsonb` that contain PII), `retention_class` (`standard_7y` / `authority_snapshot_25y` / `long_term`), `ai_source_required` (boolean; if true, the writer MUST set `ai_advisory = true`), `export_allowed` (boolean), `effective_from`, `effective_to` (nullable), `published_by`, `published_e_sig_id`, `previous_hash`, `record_hash` | all per-state required (initial draft permits nullable signature fields until publish) | unique(`action_code`, `version`); unique(`record_hash`) | platform-context (registry is global) | versioned | retain (long-term) | not applicable | yes | yes (per version) |
| `cluster_detection_rules` | Per-rule cluster threshold and cooldown configuration | `id`, `rule_key`, `pattern_action_codes` (jsonb array of action codes that count toward the cluster), `threshold_count`, `threshold_window`, `cooldown_window`, `severity_on_fire`, `effective_from`, `effective_to` (nullable), `published_by`, `published_e_sig_id`, `previous_hash`, `record_hash` | all | unique(`rule_key`, `effective_from`); unique(`record_hash`) | platform-context | versioned | retain | not applicable | yes | yes |

### 6.2.1 PostgreSQL grants and constraints

- The application role MUST have only INSERT (and SELECT) on `audit_log`. No UPDATE, no DELETE, no TRUNCATE.
- Database-level CHECK constraints enforce that `record_hash`, `previous_hash`, `chain_sequence`, `chain_id`, `timestamp`, and `action_code` are NOT NULL once inserted; column-level GENERATED ALWAYS or CHECK constraints prevent post-insert mutation of `record_hash` and `previous_hash`.
- Triggers reject any UPDATE or DELETE attempt on `audit_log` regardless of role; the trigger is itself owned by the database superuser at provisioning time and cannot be removed by application roles.
- The `audit_chain_heads` table is the only mutable Module 6 table from the application layer; it is updated transactionally with the corresponding `audit_log` insert.
- `audit_log` rows that have been archived are moved to URS-35 cold storage with object-lock immutability for the configured retention period; the cold storage layer enforces immutability beyond the database layer.

### 6.3 API requirements

#### 6.3.1 Internal write API (consumed by every other module)

The Module 6 write surface for **regulated mutations** is exposed as an **in-process library call** (TypeScript / Node.js entry-point) AND a **PostgreSQL stored procedure** with identical contract. Both forms execute on the caller's database connection within the caller's transaction so that atomic rollback (BR-06-01, DEC-06-05) is structurally achievable. Consuming modules choose the form that fits their existing transaction-management style. There is no remote HTTP endpoint for regulated-mutation audit writes.

| Form | Signature | Caller | Transaction model | Audit | Error codes |
|---|---|---|---|---|---|
| In-process library | `audit.appendAuditRow(db: TransactionContext, content: AuditRowContent): {id, chainSequence, recordHash}` | back-end consuming module within its existing transaction | caller's transaction; shared connection | self (the inserted row IS the audit) | `CHAIN_SCOPE_INVALID`, `LOCK_ACQUISITION_TIMEOUT`, `CHAIN_HEAD_INCONSISTENT`, `CHAIN_QUARANTINED`, `HASH_COMPUTATION_FAILED`, `AI_ADVISORY_FLAG_REQUIRED` |
| Stored procedure | `CALL audit_append_audit_row(...) RETURNS (id, chain_sequence, record_hash)` | back-end consuming module within its `BEGIN; ... COMMIT;` block | caller's transaction; shared connection | self | same |

A separate **non-transactional system-event ingestion endpoint** is provided for events that do not require atomic rollback with a regulated mutation:

| Method | Endpoint | Actor | Request | Response | Permission | Audit | Use restriction |
|---|---|---|---|---|---|---|---|
| POST | `/internal/audit/system-event` | named system identity (e.g., `cron@verixa.internal`, `archival@verixa.internal`, `monitoring@verixa.internal`) | system-event payload | `{id, chainSequence, recordHash}` | back-end-only; named system-actor scoped | self | MUST NOT be used for any regulated mutation; system-event audit rows are written through the same chain semantics but the originating "mutation" is a named system-actor heartbeat, not a regulated decision |

Failure of the in-process library call or the stored procedure during a regulated mutation rolls back the caller's entire transaction including the originating record change. The non-transactional system-event endpoint does not roll back any caller because it has no caller transaction; failure of that endpoint emits an internal alert.

#### 6.3.2 Read APIs

| Method | Endpoint | Actor | Request | Response | Permission | Audit | Error codes |
|---|---|---|---|---|---|---|---|
| GET | `/audit/log` | tenant-scoped | filter parameters (action_code, entity_type, target_record_id, actor_user_id, date range, severity, ai_advisory, chain_scope) + pagination cursor | paginated `AuditRow[]` with PII masked unless `audit:read_pii` | `audit:read` | none per-row; `AUDIT_LOG_VIEW_OPENED` once per session | `QUERY_PARTIAL_RESULTS` (warning, not error) |
| GET | `/audit/log/:id` | tenant-scoped | none | full audit row | `audit:read` | none | `NOT_FOUND` |
| GET | `/audit/me` | authenticated | filter parameters | paginated `AuditRow[]` scoped to caller as actor or acting_on_behalf_of | self | none | none |
| GET | `/audit/chains/:chainId` | tenant-scoped | none | chain HEAD info + last verifier verdict | `audit:read` | none | `NOT_FOUND` |
| GET | `/audit/chains/:chainId/integrity-manifest` | tenant-scoped | none | integrity manifest with HEAD hash, sample intermediate hashes, last verified-at, last verdict | `audit:read` | none | `NOT_FOUND` |

#### 6.3.3 Verifier and export APIs

| Method | Endpoint | Actor | Request | Response | Permission | Audit | Error codes |
|---|---|---|---|---|---|---|---|
| POST | `/audit/integrity/run` | tenant-scoped administrator / auditor | `{chainId, startSequence?, endSequence?, reason}` (electronic-signed) | `IntegrityVerifierRun` | `audit:integrity_run` | `INTEGRITY_VERIFIER_RUN` (with verdict) | `CHAIN_NOT_FOUND`, validation |
| POST | `/audit/export` | administrator | filter parameters + `{format}` (electronic-signed) | signed download URL with TTL + integrity manifest | `audit:export` | `AUDIT_LOG_EXPORTED` | `EXPORT_BLOCKED_INTEGRITY_VIOLATION`, `EXPORT_TOO_LARGE`, validation |
| POST | `/audit/annotation` | administrator | `{auditLogId, annotationText}` (electronic-signed) | `201` | `audit:annotate` | `AUDIT_ANNOTATION_APPENDED` | `AUDIT_ROW_NOT_FOUND`, `ANNOTATION_CANNOT_MUTATE_ORIGINAL` |
| POST | `/admin/audit/erasure` | tenant DPO | `{targetUserId, regulatoryBasis, scope}` (electronic-signed) | `PiiFieldErasure` | tenant DPO authority + `audit:annotate` | `PII_FIELD_ERASED` | `ERASURE_BASIS_REQUIRED`, `TARGET_USER_NOT_FOUND` |
| POST | `/admin/audit/retention` | administrator | `{scope, retentionYears, reason}` (electronic-signed) | `RetentionPolicyConfig` | `tenant_admin_authority` | `RETENTION_POLICY_UPDATED` | `RETENTION_BELOW_MINIMUM`, validation |

#### 6.3.4 Periodic-review APIs

| Method | Endpoint | Actor | Request | Response | Permission | Audit | Error codes |
|---|---|---|---|---|---|---|---|
| GET | `/audit/periodic-review/queue` | reviewer | filters (severity, age) | `ReviewRow[]` | `audit:periodic_review` | none | none |
| POST | `/audit/periodic-review/queue/:rowId/attest` | reviewer | `{decision: 'attested' / 'requires_investigation' / 'escalate_to_founder', notes}` (electronic-signed) | `200` | `audit:periodic_review` | `PERIODIC_AUDIT_REVIEW_ROW_ATTESTED` | `REVIEWER_CANNOT_REVIEW_OWN_ACTION`, `STATE_NOT_OPEN` |
| POST | `/audit/periodic-review/close` | administrator | `{exportFormat}` (electronic-signed) | signed download URL + integrity manifest | `audit:periodic_review` | `PERIODIC_AUDIT_REVIEW_CLOSED`, `PERIODIC_AUDIT_REVIEW_ATTESTATION_EXPORTED` | `UNRESOLVED_ROWS_AT_CLOSE` |

#### 6.3.5 Audit-event-policy registry APIs (platform-scoped)

| Method | Endpoint | Actor | Request | Response | Permission | Audit | Error codes |
|---|---|---|---|---|---|---|---|
| GET | `/platform/audit/event-policies` | platform identity / auditor | filters | `AuditEventPolicy[]` | platform identity / `audit:read` | none | none |
| POST | `/platform/audit/event-policies` | platform identity | policy fields (electronic-signed + MFA) | `201` | platform identity | `AUDIT_EVENT_POLICY_PUBLISHED` | `ACTION_CODE_DUPLICATE`, validation |
| POST | `/platform/audit/event-policies/:actionCode/retire` | platform identity | reason (electronic-signed + MFA) | `200` | platform identity | `AUDIT_EVENT_POLICY_RETIRED` | `STATE_NOT_ACTIVE` |
| GET | `/platform/audit/cluster-rules` | platform identity / auditor | filters | `ClusterDetectionRule[]` | platform identity | none | none |
| POST | `/platform/audit/cluster-rules` | platform identity | rule fields (electronic-signed + MFA) | `201` | platform identity | `CLUSTER_DETECTION_RULE_PUBLISHED` | validation |
| POST | `/platform/audit/cluster-rules/:ruleKey/retire` | platform identity | reason (electronic-signed + MFA) | `200` | platform identity | `CLUSTER_DETECTION_RULE_RETIRED` | `STATE_NOT_ACTIVE` |

#### 6.3.6 Platform-only APIs

| Method | Endpoint | Actor | Request | Response | Permission | Audit | Error codes |
|---|---|---|---|---|---|---|---|
| GET | `/platform/audit/external-anchors` | platform identity | filters | `ExternalAnchor[]` | platform identity | none | none |
| POST | `/platform/audit/external-anchors/publish` | platform identity | `{chainScope, chainId?, regulatorEndpoint?, customerEndpoint?, rfc3161Endpoint?}` (electronic-signed + executive authority co-sign for regulator manifest) | `ExternalAnchor` | platform identity | `EXTERNAL_ANCHOR_PUBLISHED` | validation |
| POST | `/platform/audit/break-glass-read` | platform identity | `{targetTenantId, businessJustification, customerReference, filterParams}` (electronic-signed + MFA) | paginated `AuditRow[]` | `audit:platform_break_glass` | `PLATFORM_TENANT_ACCESS_USED` (global chain) + `PLATFORM_TENANT_ACCESS_NOTIFIED` (target tenant chain) | validation |
| POST | `/platform/audit/restore-from-backup` | platform identity (with Founder approval) | `{chainId, backupReference, reason}` (electronic-signed + executive authority co-sign) | restored chain manifest | platform identity + executive authority | `CHAIN_RESTORED_FROM_BACKUP` | `BACKUP_NOT_FOUND`, `RESTORE_VALIDATION_FAILED` |

### 6.4 Workflow / lifecycle requirements

| Workflow | Step | Time-to-live or timer | Auto-action | Reminder |
|---|---|---|---|---|
| Scheduled integrity verifier | Per-chain monthly run | continuous (sliding window) | run verifier; emit run event | none |
| Scheduled archival | Hot-to-cold for rows older than 2 years | nightly | copy + verify + mark archived | none |
| External anchor publication | Weekly per-tenant + global | weekly | publish manifest | none |
| Time-anomaly detection | Continuous monitoring | every 5 minutes | flag suspect rows; SOC alert | none |
| Periodic audit-trail review | Weekly window | 7 days from open | auto-close at boundary; escalate unresolved | T-1 day reminder |
| INTEGRITY_VIOLATION incident | from detection | immediate | quarantine chain; SOC alert; Founder escalation within 1 business hour | continuous SOC tracking |
| Cluster detection cooldown | per rule | 30 minutes default | aggregate to single incident | none |

### 6.5 Business rules

- **BR-06-01** — Module 6's `appendAuditRow` MUST be called in the same database transaction as the originating mutation. Failure to write the audit row rolls back the originating mutation per URS-04 BR-04-15.
- **BR-06-02** — `record_hash = SHA-256(previous_hash || canonical_json(content))`. Canonical JSON per RFC 8785. Any deviation from this formula at any layer is a Class 1 change.
- **BR-06-03** — The advisory lock per chain scope MUST be acquired before reading the chain HEAD; the lock is transaction-scoped and released on commit / rollback.
- **BR-06-04** — Genesis row `previous_hash` is deterministically derived from the chain identifier and chain genesis timestamp; no random material is permitted in genesis.
- **BR-06-05** — UPDATE and DELETE on `audit_log` MUST be forbidden by database-level grants AND by trigger AND by storage-layer object-lock (post-archive). Any one of these protections being absent in production is a release blocker.
- **BR-06-06** — Client-supplied timestamps MUST be dropped at the API boundary; server clock UTC is authoritative.
- **BR-06-07** — Integrity verifier runs MUST be deterministic: walking the same chain segment with the same data MUST produce the same verdict; non-determinism is a defect.
- **BR-06-08** — `INTEGRITY_VIOLATION` triggers immediate chain quarantine (read-only banner), SOC alert, and Founder escalation within one business hour; signed exports referencing the affected chain are blocked until investigation closes.
- **BR-06-09** — The cold-archive bridge MUST preserve `record_hash` and `previous_hash` verbatim; any compression / serialisation transformation MUST be hash-preserving and re-verified after archive. Hot partitions are sealed before migration; URS-35 confirms persistence and hash equivalence; sealed partitions are physically detached at the partition level only after URS-35 confirmation; the application layer NEVER issues DELETE on `audit_log` rows. The logical `audit_log` view spans hot + cold so query continuity is preserved; no audit row becomes unavailable before retention expiry.
- **BR-06-10** — External anchors are published as follows: (a) the **global chain HEAD** is anchored directly weekly; (b) **per-tenant chain HEADs** are anchored directly weekly per tenant; (c) **per-entity chain HEADs are aggregated under a per-tenant Merkle root** computed over all active per-entity chain HEADs for the tenant; only the per-tenant Merkle root is anchored externally (weekly). This makes anchoring scale to thousands or millions of regulated records per tenant without one anchor publication per record. The per-tenant Merkle root is recomputed at every anchor cycle from the current state of all per-entity chain HEADs in the tenant; the export integrity manifest includes the Merkle proof path for every per-entity chain in scope so an external verifier can reproduce the path to the tenant Merkle root and compare against the published anchor.
- **BR-06-11** — Time-anomaly detection MUST NOT mutate suspect audit rows; suspect rows are flagged in a separate `time_anomaly_detections` table for forensic review.
- **BR-06-12** — Periodic-audit-trail-review reviewer MUST NOT be the actor of the rows under review (`REVIEWER_CANNOT_REVIEW_OWN_ACTION`); the surface enforces and the back-end re-asserts.
- **BR-06-13** — Cryptographic erasure MUST NOT mutate any historical `audit_log` row. Erasure is performed through (a) destruction of the per-subject data-encryption key that was used to encrypt the PII fields in `details_jsonb` at write time, rendering the ciphertext permanently undecryptable while the row itself remains unmodified, OR (b) append-only redaction overlay rows in `pii_redaction_overlays` that drive read-time redaction without touching the original row. Every erasure action MUST append a new `PII_FIELD_ERASED` row to `audit_log`. Chain integrity is preserved by construction because the rows the chain commits over are never altered. Any design that would re-write a historical row (including hash-substitution tombstones) is forbidden because it would imply a SHA-256 collision (computationally infeasible by design) or an unspecified hash-indirection mechanism.
- **BR-06-13a** — The `audit_log` table is the regulatory record. It is INSERT-only at every layer (application + database grants + trigger + storage object-lock). UPDATE and DELETE are forbidden for every operational and privacy purpose without exception, including erasure.
- **BR-06-14** — Audit-log retention MUST NEVER be reduced below the launch defaults (7 years standard / 25 years authority snapshot). Tenants MAY increase retention beyond the launch defaults.
- **BR-06-15** — System-actor writes use named system identities (e.g., `audit-archival@verixa.internal`); system actors MAY write but MAY NOT sign regulated decisions per URS-04 §6.7 / URS-05 BR-05-19.
- **BR-06-16** — AI-advisory rows MUST set `ai_advisory = true`; the read surface visually distinguishes them; no AI suggestion is written to a regulated record without a separate human electronic-signature audit row.
- **BR-06-17** — Tenant offboarding seals the tenant's chains: no further inserts; chain HEAD anchored externally one final time; data retained per residency / contract terms in cold storage.
- **BR-06-18** — Cross-tenant break-glass read by platform identity emits one row in the global chain (`PLATFORM_TENANT_ACCESS_USED`) AND one row in the target tenant's per-tenant chain (`PLATFORM_TENANT_ACCESS_NOTIFIED`); customer notification within 24 hours per privacy policy.
- **BR-06-19** — Regulator-facing external anchor manifests MUST be executive-authority-co-signed.
- **BR-06-20** — Annotations MUST NOT mutate the original audit row; annotations live in a separate `audit_annotations` table that is itself append-only and chain-linked.
- **BR-06-21** — For regulated-signature events, the three IDs (`audit_log.id`, `electronic_signatures.id`, `approval_authority_snapshots.id`) MUST be UUIDs allocated by the caller **before any insert**. The three rows MUST be inserted in the same transaction with foreign-key constraints declared `INITIALLY DEFERRED`, OR through the `audit_e_sig_snapshot_append_atomic` stored procedure. The transaction MUST fail (rollback) if any of the three cross-references is missing or mismatched at COMMIT time. The integrity verifier and the export-manifest job MUST verify bidirectional consistency for every signed event in their scope; mismatch is `INTEGRITY_VIOLATION`.
- **BR-06-22** — Updates to the `audit_chain_heads` HEAD-pointer row that occur as part of normal `appendAuditRow` execution are NOT separately audited per insert, to avoid recursion. The chain HEAD's authoritative history is reconstructable from `audit_log.chain_sequence` ordering. Administrative changes to `audit_chain_heads` (chain quarantine, chain repair, chain restoration from backup) ARE audited as `CHAIN_QUARANTINED`, `CHAIN_RESTORED_FROM_BACKUP`, etc.

### 6.6 Audit trail requirements (events Module 6 emits about itself)

Module 6 governance event vocabulary (canonical launch list; every code MUST have at least one writer and one regression test; adding a code is a Class 3 change):

`CHAIN_GENESIS`, `CHAIN_QUARANTINED`, `CHAIN_RESTORED_FROM_BACKUP`, `INTEGRITY_VERIFIER_RUN`, `INTEGRITY_VIOLATION`, `EXTERNAL_ANCHOR_PUBLISHED`, `TENANT_MERKLE_AGGREGATE_COMPUTED`, `AUDIT_LOG_VIEW_OPENED` (coarse; once per session per tenant), `AUDIT_LOG_EXPORTED`, `AUDIT_PII_ACCESSED`, `AUDIT_ANNOTATION_APPENDED`, `RETENTION_POLICY_UPDATED`, `PII_FIELD_ERASED`, `TIME_ANOMALY_DETECTED`, `AUDIT_PARTITION_SEALED`, `AUDIT_PARTITION_ARCHIVED_TO_COLD`, `AUDIT_PARTITION_DETACHED_AND_DROPPED`, `ARCHIVAL_HASH_MISMATCH` (forensic), `PERIODIC_AUDIT_REVIEW_OPENED`, `PERIODIC_AUDIT_REVIEW_ROW_ATTESTED`, `PERIODIC_AUDIT_REVIEW_CLOSED`, `PERIODIC_AUDIT_REVIEW_ATTESTATION_EXPORTED`, `HIGH_RISK_EVENT_CLUSTER_DETECTED`, `TENANT_CHAINS_SEALED_AT_OFFBOARDING`, `PLATFORM_TENANT_ACCESS_USED` (global chain), `PLATFORM_TENANT_ACCESS_NOTIFIED` (target tenant chain), `PLATFORM_TENANT_ACCESS_DENIED`, `AI_SUGGESTION_GENERATED` (AI-advisory annotation; consumed from URS-32), `AI_SUGGESTION_ACCEPTED` (human-signed acceptance; consumed from URS-32 + URS-04), `AUDIT_EVENT_POLICY_PUBLISHED`, `AUDIT_EVENT_POLICY_RETIRED`, `CLUSTER_DETECTION_RULE_PUBLISHED`, `CLUSTER_DETECTION_RULE_RETIRED`.

Module 6 also receives every event emitted by every other URS-01..URS-35 module; the canonical event vocabulary across the platform is owned by the originating modules and consumed by Module 6 as opaque content with `action_code` and `details_jsonb`.

### 6.7 Record versioning and class-of-change governance

- Append-only WORM (truly immutable post-insert): `audit_log`, `audit_annotations`, `audit_chain_genesis`, `external_anchors`, `integrity_verifier_runs`, `time_anomaly_detections`, `pii_field_erasures`, `cold_archive_manifest`.
- Mutable HEAD pointer (transactionally updated with each insert): `audit_chain_heads`. The HEAD pointer's history is reconstructable from `audit_log`'s `chain_sequence` ordering.
- Versioned: `retention_policy_configs`.
- No soft-delete on Module 6 tables. Cryptographic erasure of PII in `audit_log.details_jsonb` uses subject-level encryption-key destruction (default) or append-only redaction overlay (fallback) per DEC-06-13. The historical `audit_log` row is never modified; chain integrity is preserved by construction.

---

## 7. Cross-Module Wiring and Change-Impact

### 7.1 Cross-module wiring

#### Diagram 7-A — Module 6 substrate consumed by every other module

```mermaid
graph LR
  subgraph M6 [Module 6 — Audit Substrate]
    APPEND[appendAuditRow]
    CHAINS[Per-entity / Per-tenant / Global chains]
    VERIFIER[Integrity verifier]
    READ[Read / export surface]
    ARCHIVE[Hot to cold archival]
    ANCHOR[External anchoring]
  end

  M1[URS-01 Auth] --> APPEND
  M2[URS-02 RBAC] --> APPEND
  M3[URS-03 Context] --> APPEND
  M4[URS-04 Workflow / E-Sign] --> APPEND
  M5[URS-05 Authority] --> APPEND
  M7[URS-07 Study Management] --> APPEND
  M8[URS-08 Tenant Management / Tenant Lifecycle] --> APPEND
  M12[URS-12..URS-34 Regulated modules] --> APPEND
  M30[URS-30 Notifications] --> READ
  ARCHIVE <--> M35[URS-35 Backup / Cold storage]
  ANCHOR --> EXT[Regulator / Customer / RFC 3161 endpoints]
```

Module 6 is the universal write-path for every regulated module. Every state change anywhere in Verixa flows through `appendAuditRow`. URS-04 owns the workflow / e-signature ceremony and writes the `ESIG_CREATED` event through Module 6; URS-05 owns the authority resolver and writes `APPROVAL_AUTHORITY_VALIDATED` / `APPROVAL_AUTHORITY_SNAPSHOT_WRITTEN` through Module 6. URS-07 (Study Management) and URS-08 (Tenant Management / Tenant Lifecycle) write their own domain events through Module 6 — URS-08 in particular drives the `CHAIN_GENESIS` row insertion at tenant onboarding (DEC-06-17) and the `TENANT_CHAINS_SEALED_AT_OFFBOARDING` event at tenant offboarding (BR-06-17). URS-35 owns the cold storage class and the durability / replication that preserve chain hashes verbatim. URS-30 delivers periodic-review and integrity-violation notifications.

### 7.2 Change-Impact Matrix (CIM)

Every change to Module 6 that affects external behaviour MUST be classified per the four-class change impact taxonomy. Class 1 changes require Founder + QA + RA approval and trigger full revalidation; Class 2 changes require QA approval and trigger targeted regression; Class 3 changes require Engineering Lead approval and unit / integration regression; Class 4 changes are non-functional and require code-review approval.

| Change | Class | Impact on (modules) | Required revalidation |
|---|---|---|---|
| Change hash function (DEC-06-03) | 1 | every module that writes audit | Full regression + chain migration |
| Change canonical JSON serialisation | 1 | every module | Full regression + chain migration |
| Change audit row schema (DEC-06-04) | 1 | every module that writes audit; URS-04, URS-05 cross-module references | Full regression including chain extension migration |
| Add chain scope (DEC-06-02) | 1 | every module that decides chain scope | Full regression |
| Change atomic write contract (DEC-06-05) | 1 | every module | Full regression |
| Change advisory lock scope (DEC-06-11) | 1 | URS-04 BR-04-16 | Full concurrency regression |
| Change retention defaults (DEC-06-06) | 1 | URS-35, regulatory mapping | Full regression and regulatory review |
| Change cold-archive policy (DEC-06-07) | 2 | URS-35 | Targeted regression of archival path |
| Change verifier schedule | 3 | none external | Unit regression |
| Add audit event code | 3 | originating module owns the writer | Writer-presence regression |
| Change PII masking policy | 2 | UI components, GDPR / DPDP evidence pack | Targeted regression of read surface |
| Change external anchor frequency | 3 | regulator manifest / customer manifest endpoints | Unit regression |
| Change time-anomaly threshold | 3 | none external | Unit regression |
| UI copy or layout change | 4 | none | Visual regression |

Every change above is classified at design time and recorded in the URS-13. Class 1 changes require Founder electronic signature.

### 7.3 Cross-module dependencies (consumed by Module 6)

| Dependency | Source | Impact | Blocking? |
|---|---|---|---|
| Authentication and MFA step-up | URS-01 | Controlled Approval Modal pre-condition for export / annotation / erasure | Blocking |
| Effective permissions | URS-02 | Read / export / integrity-run / periodic-review gates | Blocking |
| Active scope | URS-03 | Tenant-scope binding for reads | Blocking |
| Workflow / e-sig ceremony | URS-04 | `e_sig_id` cross-references | Blocking |
| Authority resolver | URS-05 | `authority_snapshot_id` cross-references; `audit:read_pii` permission gating | Blocking |
| Tenant lifecycle (onboarding / offboarding) | URS-08 | Genesis row insertion / chain sealing | Blocking |
| Notifications | URS-30 | Periodic-review reminders, integrity-violation alerts, cluster-detection escalations | Non-blocking (direct e-mail fallback) |
| Backup / restore / cold storage | URS-35 | Hash-preserving archival; restore drill verification | Blocking for PQ |

---

## 8. AI / Automation / Human-in-the-Loop Controls

Module 6 contains **no AI / ML components in its core path**. The audit substrate is rule-based and deterministic. The integrity verifier is a deterministic SHA-256 walker; the time-anomaly detector is a deterministic threshold comparator; the cluster detector applies fixed threshold rules. Module 6 does not consume any LLM provider, does not run inference, and contains no probabilistic logic in the write or read path.

Module 6 receives events from AI-emitting modules (URS-32 MIRA / advisory copilots; any module that surfaces AI suggestions). Per CLAUDE.md §QS-21 and DEC-06-15, every audit row whose content originates from an AI suggestion MUST set `ai_advisory = true`. Module 6 enforces this through schema (the column exists on every row) and through read-path UX (advisory rows are visually distinguished). Module 6 never writes an AI-advisory row to a regulated record; the human acceptance is a separate audit row with `ai_advisory = false` and the human's electronic signature.

The HITL lifecycle is owned by URS-04. Module 6's role is to be the substrate that captures every step of the HITL lifecycle through `appendAuditRow`.

Static analysis MUST verify zero references to LLM SDKs in Module 6 source code per QS-21.

---

## 9. Reports, Dashboards, and Exports

| Report | Purpose | Audience | Format |
|---|---|---|---|
| Filtered audit query export | Inspection / forensic / customer-requested | Auditor, administrator, inspector | PDF (electronically signed) + JSON + integrity manifest |
| Integrity manifest (per chain) | Chain HEAD verification | Auditor, administrator, inspector | PDF (electronically signed) + JSON |
| Periodic audit-trail review attestation pack | Annual / weekly review evidence | Administrator, auditor, inspector | PDF (electronically signed) |
| External anchor manifest (regulator) | Public proof of chain HEAD published | Inspector, public | Founder-signed JSON; URL endpoint |
| External anchor manifest (customer) | Tenant proof of chain HEAD published | Tenant administrator, auditor | Platform-signed JSON; tenant endpoint |
| Cross-tenant break-glass usage report | SOC and Founder oversight | Founder, SOC, Information Security | CSV + PDF |
| Time-anomaly detection report | SOC review | SOC, Information Security | CSV |
| PII erasure log | DPO evidence | Tenant DPO, Information Security | CSV + PDF |
| Cold-archival manifest | URS-35 reconciliation | Platform, QA | CSV + JSON |
| Integrity verifier run history | Operational evidence | Administrator, auditor | CSV + JSON |

Every export routes through the Controlled Approval Modal. Signed download URLs with fifteen-minute TTL. Integrity manifest accompanies every export.

---

## 10. Notifications and Queues

| Trigger | Recipient | Channel | Latency |
|---|---|---|---|
| `INTEGRITY_VIOLATION` | SOC + executive authority + tenant administrator | URS-30 SOC chat + e-mail + executive authority e-mail | within 60 seconds |
| `HIGH_RISK_EVENT_CLUSTER_DETECTED` | Founder + tenant administrator | URS-30 e-mail | within one business day |
| `TIME_ANOMALY_DETECTED` | SOC | URS-30 SOC chat | within 60 seconds |
| `PLATFORM_TENANT_ACCESS_USED` | tenant administrator + customer privacy contact | URS-30 in-app + e-mail | within 24 hours per privacy policy |
| Periodic-review window opening | tenant administrator | URS-30 in-app + e-mail | at window open |
| Periodic-review window approaching close | tenant administrator | URS-30 in-app + e-mail | T-1 day, T-1 hour |
| `EXTERNAL_ANCHOR_PUBLISHED` | tenant administrator (informational digest) | URS-30 e-mail digest weekly | post-publication |
| `ARCHIVAL_HASH_MISMATCH` | platform on-call + SOC | URS-30 SOC chat + on-call page | within 60 seconds |
| `RETENTION_POLICY_UPDATED` | tenant administrator + tenant DPO | URS-30 in-app + e-mail | within 60 seconds |
| `PII_FIELD_ERASED` | tenant DPO + Information Security | URS-30 in-app + e-mail | within 60 seconds |

---

## 11. Error Handling and Negative Paths

### 11.1 Error envelope

All error responses follow the envelope: human message, machine-readable code in upper-snake-case, optional structured details, correlation identifier.

### 11.2 Error-code catalogue

| Code | HTTP | Path | UI behaviour |
|---|---|---|---|
| CHAIN_SCOPE_INVALID | 400 | internal append | back-end forensic; rolls back originating mutation |
| LOCK_ACQUISITION_TIMEOUT | 503 | internal append | back-end retries with backoff; surfaced as `503` to caller after retries exhausted |
| CHAIN_HEAD_INCONSISTENT | 500 | internal append | back-end forensic; SOC alert; investigation |
| CHAIN_QUARANTINED | 409 | internal append + read / export | banner for read surface; export refused |
| HASH_COMPUTATION_FAILED | 500 | internal append | back-end forensic; on-call page |
| QUERY_PARTIAL_RESULTS | 200 (warning header) | filtered read | banner indicating pagination needed |
| EXPORT_BLOCKED_INTEGRITY_VIOLATION | 409 | export | block + SOC alert |
| EXPORT_TOO_LARGE | 413 | export | inline message indicating filter refinement needed |
| AUDIT_ROW_NOT_FOUND | 404 | annotation | inline error |
| ANNOTATION_CANNOT_MUTATE_ORIGINAL | 403 | attempted mutation via annotation API | inline error; forensic |
| ERASURE_BASIS_REQUIRED | 400 | erasure | inline error |
| TARGET_USER_NOT_FOUND | 404 | erasure | inline error |
| RETENTION_BELOW_MINIMUM | 400 | retention configuration | inline error citing minimum |
| REVIEWER_CANNOT_REVIEW_OWN_ACTION | 403 | periodic-review attestation | inline error |
| UNRESOLVED_ROWS_AT_CLOSE | 409 | periodic-review close | inline error listing unresolved |
| BACKUP_NOT_FOUND | 404 | restore | inline error |
| RESTORE_VALIDATION_FAILED | 422 | restore | inline error citing validator output |
| AUDIT_TRAIL_WRITE_FAILED | 500 | the originating action did NOT commit | toast on the originating UI; forensic |
| PLATFORM_TENANT_ACCESS_DENIED | 403 | platform identity outside support envelope | inline error; SOC alert |
| AI_ADVISORY_FLAG_REQUIRED | 400 | internal append where caller is AI-emitting module | back-end forensic; rolls back |

### 11.3 Negative-path catalogue

| Scenario | Detection | Response | UI behaviour |
|---|---|---|---|
| Audit-write fails mid-decision | back end | `500 AUDIT_TRAIL_WRITE_FAILED`; rolls back originating action | toast on consuming UI; the regulated decision did NOT commit |
| Concurrent insert collision | advisory lock | second writer blocks until first commits / rolls back; ordering preserved | not surfaced; transparent |
| Lock acquisition exceeds timeout | back end | `503 LOCK_ACQUISITION_TIMEOUT` after retries | banner; user retries |
| Chain HEAD inconsistent (e.g., missing row) | back end | `500 CHAIN_HEAD_INCONSISTENT`; SOC alert; investigation | banner; immediate SOC follow-up |
| Hash computation fails | back end | `500 HASH_COMPUTATION_FAILED`; rolls back; on-call page | banner; SOC follow-up |
| Integrity verifier finds violation | scheduled / on-demand | `INTEGRITY_VIOLATION` audit event; chain quarantined | read surface shows banner; signed exports blocked |
| Export attempted on quarantined chain | back end | `409 EXPORT_BLOCKED_INTEGRITY_VIOLATION` | inline error |
| Audit query exceeds scan budget | back end | `200` with `QUERY_PARTIAL_RESULTS` warning | banner; user paginates / refines filter |
| Audit query exceeds export size limit | back end | `413 EXPORT_TOO_LARGE` | inline error |
| Annotation API used to attempt mutation | back end | `403 ANNOTATION_CANNOT_MUTATE_ORIGINAL` | inline error; forensic |
| Retention configured below minimum | back end | `400 RETENTION_BELOW_MINIMUM` | inline error |
| Reviewer attempts to attest own action | back end | `403 REVIEWER_CANNOT_REVIEW_OWN_ACTION` | inline error |
| Time-anomaly detected (clock drift) | scheduled | `TIME_ANOMALY_DETECTED`; suspect rows flagged; SOC review | not surfaced to end-user; SOC chat |
| Cold-archive hash mismatch | scheduled | `ARCHIVAL_HASH_MISMATCH`; abort archival run; on-call page | not surfaced to end-user; SOC chat |
| URS-35 unreachable during archival | back end | retries with backoff; abort with alert if persistent | SOC chat |
| AI-emitting module fails to set `ai_advisory = true` | back end | `400 AI_ADVISORY_FLAG_REQUIRED`; rolls back | back-end forensic; engineering follow-up on the emitting module |
| Cross-tenant break-glass attempted outside posture | back end | `403 PLATFORM_TENANT_ACCESS_DENIED`; SOC alert | inline error |

---

## 12. Security, Privacy, and Tenant Isolation

### 12.1 Authentication dependency

URS-06 read / export / integrity-run / periodic-review / annotation / erasure / break-glass surfaces are reached only through an authenticated session established by URS-01. Every Module 6 mutation surface (export, annotation, erasure, retention update, integrity-run, break-glass) goes through the Controlled Approval Modal with electronic signature; high-risk mutations (export, break-glass, erasure) additionally require multi-factor step-up.

### 12.2 Authorisation pipeline

`authenticate hook → tenant hook → rbac hook → context gate hook → module6 hook → esigService.createSignature where applicable → module6 surface action`. Module 6 owns the module6 hook position (audit read / export / integrity-run / periodic-review / annotation / erasure / retention).

### 12.3 Tenant isolation

Every audit-log query routes through TDAL with tenant context bound. RLS on `audit_log.tenant_id` enforces tenant scope; rows in the global chain (`tenant_id IS NULL`) are visible only to platform identity and only under controlled support / break-glass posture. Cross-tenant break-glass reads emit notifications to the affected tenant within 24 hours per privacy policy.

### 12.4 Encryption

At rest: `audit_log.details_jsonb` may contain regulated identifiers and PII; protected by RLS plus KMS at the storage layer; PII fields tagged via `pii_fields` array for masking in reads. In transit: TLS 1.2 or higher with HSTS preload. Cold storage: encrypted at rest with object-lock immutability.

### 12.5 Logging hygiene

Application logs (separate from the audit log) scrub passwords, MFA tokens, and any field tagged sensitive. Structured logs carry the correlation identifier on every request. The audit log itself is the regulatory record; application logs are operational support and have shorter retention (90 days hot; 13 months total).

### 12.6 Privacy and data residency

Inherits tenant data-residency configuration from URS-08. PII fields in `details_jsonb` respect tenant residency. Cryptographic erasure on `details_jsonb` PII fields per DEC-06-13 and J-14.

### 12.7 Periodic access review

Per URS-05 Module 5: the Module 6 read / export permissions are reviewed annually under URS-05's periodic access review apparatus. Reviewer enumerates every user holding `audit:read`, `audit:read_pii`, `audit:export`, `audit:integrity_run`, `audit:periodic_review`, `audit:annotate`, `audit:platform_break_glass` and attests continuation.

### 12.8 Periodic audit-trail review

Owned by Module 6 (DEC-06-14). Weekly window; `severity in ('high','critical')` events triaged within one business day; cluster detection escalates to Founder.

### 12.9 Security-operations alert thresholds

| Pattern | Threshold | Severity | Channel |
|---|---|---|---|
| `INTEGRITY_VIOLATION` | any single event | critical | SOC chat + executive authority e-mail + on-call page |
| `ARCHIVAL_HASH_MISMATCH` | any single event | critical | SOC chat + on-call page |
| `TIME_ANOMALY_DETECTED` | any single event with drift > 100ms | high | SOC chat |
| `TIME_ANOMALY_DETECTED` cluster | three nodes affected within 5 minutes | critical | SOC chat + on-call page |
| `PLATFORM_TENANT_ACCESS_USED` | any single event | informational (real-time) | SOC chat + customer notification within 24 hours |
| `PLATFORM_TENANT_ACCESS_DENIED` | any single event | high | SOC chat |
| `LOCK_ACQUISITION_TIMEOUT` cluster | ten in five minutes (same chain) | high | SOC chat |
| `CHAIN_HEAD_INCONSISTENT` | any single event | critical | SOC chat + on-call page |
| `HASH_COMPUTATION_FAILED` | any single event | critical | on-call page |
| `EXPORT_BLOCKED_INTEGRITY_VIOLATION` | any single event | high (correlated with INTEGRITY_VIOLATION) | SOC chat |
| `HIGH_RISK_EVENT_CLUSTER_DETECTED` | per cluster rule | critical | Founder e-mail + SOC chat |
| `PII_FIELD_ERASED` | any single event | informational | SOC e-mail digest |
| `AUDIT_PII_ACCESSED` cluster | five accesses by same user in one hour | medium | SOC e-mail digest |

### 12.10 Self-modification block — scope

A user MUST NOT review their own audit rows in the periodic review (BR-06-12). The reviewer surface refuses with `REVIEWER_CANNOT_REVIEW_OWN_ACTION`. A user MUST NOT initiate a cryptographic erasure of their own audit history without DPO authority co-sign; the erasure surface refuses self-erasure for regulatory-significant events.

### 12.11 Secure export

Every export routes through the Controlled Approval Modal. Signed download URLs with fifteen-minute TTL. Integrity manifest accompanies every export and includes the chain HEAD hash, sample intermediate hashes, verifier verdict, content fingerprint, and platform countersignature.

### 12.12 WORM storage posture

The audit log is append-only at the application layer (DEC-06-01) AND at the database layer (no UPDATE / DELETE grants for application roles; CHECK / trigger guards) AND at the storage layer (object-lock immutability period on archived rows). Any one of these protections being absent is a release blocker. The only legitimate path to alter a historical row is through an infrastructure superuser at the database layer, which is itself a Security Operations Centre incident.

---

## 13. Data Integrity and ALCOA+ Controls

| Principle | Module 6 control | Requirement | Verification |
|---|---|---|---|
| Attributable | Every audit row carries `actor_user_id` (or named system identity); system actors prohibited as regulated signers | URS-06-AUD-001 | Integration test |
| Legible | Audit rows render in structured detail; exports in PDF + JSON | URS-06-REP-001 | Export test |
| Contemporaneous | Server-set `timestamp`; client-supplied dropped; NTP-synchronised; time-anomaly detection | URS-06-AUD-002 | Concurrency test |
| Original | Append-only WORM; database / column / storage-layer protections; no UPDATE / DELETE grants | URS-06-AUD-003 | Validation test |
| Accurate | Hash chain detects tamper; integrity verifier scheduled and on-demand; external anchoring | URS-06-DATA-001 | Concurrency test + verifier test |
| Complete | Atomic write contract (BR-06-01); failure rolls back originating mutation | URS-06-AUD-004 | Validation test |
| Consistent | Per-chain advisory lock prevents reordering; chain sequence monotonic; bidirectional cross-references | URS-06-AUD-005 | Concurrency test |
| Enduring | Retention defaults (7y / 25y); cold archive with object-lock immutability; URS-35 backup / restore preserves verbatim | URS-06-DATA-002 | Migration test + DR drill |
| Available | Read paths administrator / auditor / inspector accessible; cold tier query-accessible with latency badge | URS-06-REP-002 | End-to-end test |

---

## 14. Regulatory Mapping

| Identifier | Control | Regulation / Guidance | Clause | Applicable | Implementation expectation |
|---|---|---|---|---|---|
| RG-06-001 | Audit trail of operator actions | 21 CFR Part 11 | §11.10(e) | Yes | Universal append-only WORM audit log + atomic write contract |
| RG-06-002 | Audit-trail tamper-evidence | 21 CFR Part 11 | §11.10(e) (implied) | Yes | SHA-256 hash chain + external anchoring + integrity verifier |
| RG-06-003 | Audit trail review | EU GMP Annex 11 | §9 | Yes | Periodic audit-trail review (DEC-06-14, BR-06-12) |
| RG-06-004 | Computer-system audit trail | EU GMP Annex 11 | §9 | Yes | Module 6 universal audit log |
| RG-06-005 | Records retention | EU GMP Annex 11 | §17 | Yes | 7 years standard / 25 years authority snapshot per DEC-06-06 |
| RG-06-006 | Validation of computerised systems | EU GMP Annex 11 | §4 | Yes | CSV / CSA pack per §17 |
| RG-06-007 | Risk-based assurance | FDA Computer Software Assurance for Production and Quality Management System Software, Final Guidance, February 2026 | applicable | Yes | Risk classification per validation pack |
| RG-06-008 | ALCOA+ data integrity | MHRA Data Integrity Guidance (2018) | nine principles | Yes | §13 mapping |
| RG-06-009 | Data governance | WHO Technical Report Series No. 996, Annex 5 | applicable | Yes | Atomic write contract; chain integrity |
| RG-06-010 | Identity-management standards | ISO/IEC 27001 | A.5.16, A.8.5 | Yes | Inherited from URS-01 |
| RG-06-011 | Information security event logging | ISO/IEC 27001 | A.8.15 | Yes | Universal audit log; SOC alerting |
| RG-06-012 | EU AI Act applicability | Regulation (EU) 2024/1689 | Article 12 (record keeping for high-risk AI) | Yes (consumed from URS-32 via `ai_advisory` flag) | Audit row segregation per DEC-06-15 |
| RG-06-013 | EU GMP Annex 22 (Draft 2025) | EU GMP Annex 22 | applicable forward-looking | Forward-looking only — no Module 6 control text depends on Annex 22 until incorporated through URS-13 | No Annex-22-dependent control |
| RG-06-014 | GDPR right to erasure | Regulation (EU) 2016/679 | Article 17 + Article 17(3)(e) (legal claims exemption) | Conditional per tenant operation | Cryptographic erasure via subject-level key destruction (default) or append-only redaction overlay (fallback) per DEC-06-13; historical `audit_log` row never modified |
| RG-06-015 | India DPDP Act 2023 | Digital Personal Data Protection Act 2023 | Section 12 (right to erasure) | Conditional per tenant operation | Same erasure mechanism as GDPR |
| RG-06-016 | Time-stamping | RFC 3161 | applicable (where tenant elects) | Optional | External anchoring with RFC 3161 token (DEC-06-10) |
| RG-06-017 | Canonical JSON | RFC 8785 (JSON Canonicalization Scheme) | applicable | Yes | DEC-06-03 |
| RG-06-018 | Hash function | NIST FIPS 180-4 | SHA-256 | Yes | DEC-06-03 |
| RG-06-019 | India audit-trail / data-integrity framework — D&C Act 1940 + Drugs Rules 1945 + Revised Schedule M (data integrity, electronic records, ALCOA expectations within GMP) + Schedule M-III (where distribution-record audit scope) + New Drugs and Clinical Trials Rules 2019 (where clinical-record audit scope) + Medical Devices Rules 2017 (where device-record audit scope) | India Drugs and Cosmetics Act 1940; Drugs Rules 1945; Revised Schedule M; Schedule M-III; New Drugs and Clinical Trials Rules 2019; Medical Devices Rules 2017 | Applicable per India tenant operation and jurisdictional regulatory assessment | Conditional per India tenant operation | URS-06 hash-chained audit substrate + ALCOA+ principles + per-tenant chain genesis + chain sealing at offboarding; external jurisdictional legal / RA confirmation required for clause applicability per India tenant scope |

### 14.1 Predicate-rule applicability matrix

| Record / artifact | Predicate-rule basis | Part 11 applicable? | Retention | Owner | Evidence |
|---|---|---|---|---|---|
| Audit log row | Operator-action evidence | Yes | seven years (twenty-five years where authority snapshot referenced) | QA / IS | Append-only WORM + chain integrity + electronic-signature reference |
| Hash chain | Tamper-evidence | Yes (implied by §11.10(e)) | per audit log | QA / IS | SHA-256 chain + external anchoring |
| Integrity manifest | Inspection / customer evidence | Yes | retain | QA / IS | Signed PDF + JSON + countersignature |
| External anchor manifest | Public proof of chain HEAD | Yes (operational evidence) | retain (long-term) | Founder + Platform | Founder-signed for regulator manifest; platform-signed for customer manifest |
| Periodic audit-trail review attestation | Periodic-review evidence | Yes | seven years | QA / IS | Reviewer electronic signature + attestation pack |
| Time-anomaly detection log | Forensic evidence | Yes | seven years | IS | Append-only log with linked audit-row references |
| Cryptographic erasure log | Privacy compliance evidence | Yes (operational evidence; not Part-11-protected content) | retain (long-term) | Tenant DPO + IS | DPO-signed authorisation + erasure-mechanism references (destroyed key reference for `subject_key_destruction`; overlay row references for `redaction_overlay`) |
| Cold-archive manifest | URS-35 reconciliation | Yes | retain | Platform / QA | URS-35 storage reference + post-archive verifier verdict |
| Integrity verifier run history | Operational evidence | Yes | seven years | IS / QA | Append-only verifier log |

---

## 15. URS Requirements Register

### 15.1 Front-end (FE)

- URS-06-FE-001 — The audit viewer MUST surface filter chips for action_code, entity_type, target_record_id, actor_user_id, date range, severity, ai_advisory, chain_scope, integrity_status. Priority MUST. Risk MEDIUM. Maps RG-06-001.
- URS-06-FE-002 — PII fields MUST be masked unless the caller holds `audit:read_pii`. Priority MUST. Risk HIGH. Maps RG-06-014, RG-06-015.
- URS-06-FE-003 — The integrity manifest viewer MUST render hash badges (valid / quarantined / never-verified). Priority MUST. Risk HIGH. Maps RG-06-002.
- URS-06-FE-004 — The export wizard MUST run the integrity verifier scoped to the export's footprint and refuse on `INTEGRITY_VIOLATION`. Priority MUST. Risk HIGH. Maps RG-06-002.
- URS-06-FE-005 — AI-advisory rows MUST be visually distinguished in the read surface. Priority MUST. Risk HIGH. Maps RG-06-012.
- URS-06-FE-006 — Periodic-review surface MUST refuse rows where the reviewer is the actor of the row under review. Priority MUST. Risk HIGH. Maps RG-06-003.
- URS-06-FE-007 — "My activity" self-view MUST be available to every authenticated user. Priority MUST. Risk LOW.
- URS-06-FE-008 — Hash values MUST display truncated by default with click-to-expand and copy-to-clipboard. Priority SHOULD. Risk LOW.
- URS-06-FE-009 — Cold-tier query results MUST display a tier badge indicating higher latency. Priority SHOULD. Risk LOW.
- URS-06-FE-010 — Every route in §5.1 MUST be registered in the application router before release. Priority MUST. Risk LOW.
- URS-06-FE-011 — All Module 6 surfaces MUST meet WCAG 2.1 Level AA. Priority MUST. Risk MEDIUM.

### 15.2 Back-end (BE)

- URS-06-BE-001 — `appendAuditRow` MUST execute in the same database transaction as the originating mutation; failure rolls back the originating mutation. Priority MUST. Risk CRITICAL. Maps RG-06-001.
- URS-06-BE-002 — `record_hash = SHA-256(previous_hash || canonical_json(content))` per RFC 8785; deviation is a Class 1 change. Priority MUST. Risk CRITICAL. Maps RG-06-002, RG-06-017, RG-06-018.
- URS-06-BE-003 — Per-chain advisory locks MUST serialise concurrent inserts (per-entity / per-tenant / global). Priority MUST. Risk CRITICAL.
- URS-06-BE-004 — Genesis row `previous_hash` MUST be deterministically derived from chain identifier and chain genesis timestamp. Priority MUST. Risk HIGH.
- URS-06-BE-005 — UPDATE and DELETE on `audit_log` MUST be forbidden by database grants AND by trigger AND by storage object-lock. Priority MUST. Risk CRITICAL. Maps RG-06-001.
- URS-06-BE-006 — Server-set `timestamp` only; client-supplied dropped. Priority MUST. Risk HIGH.
- URS-06-BE-007 — Integrity verifier MUST be deterministic. Priority MUST. Risk HIGH.
- URS-06-BE-008 — `INTEGRITY_VIOLATION` MUST quarantine the chain, emit SOC alert, escalate to Founder within one business hour. Priority MUST. Risk CRITICAL. Maps RG-06-002.
- URS-06-BE-009 — Cold-archive bridge MUST preserve `record_hash` and `previous_hash` verbatim and re-verify post-archive. Priority MUST. Risk HIGH.
- URS-06-BE-010 — External anchors MUST be published at minimum weekly for per-tenant and global chains. Priority MUST. Risk MEDIUM.
- URS-06-BE-011 — Time-anomaly detection MUST NOT mutate suspect rows. Priority MUST. Risk HIGH.
- URS-06-BE-012 — Periodic-audit-trail-review reviewer MUST NOT be the actor of rows under review. Priority MUST. Risk HIGH.
- URS-06-BE-013 — Cryptographic erasure MUST preserve chain integrity by leaving every historical `audit_log` row unmodified; erasure is implemented via subject-level encryption-key destruction (default) or append-only redaction overlay (fallback) per DEC-06-13; tombstone-with-same-hash substitution is forbidden because it would imply a SHA-256 collision. Priority MUST. Risk HIGH. Maps RG-06-014, RG-06-015.
- URS-06-BE-014 — Retention defaults MUST NOT be configurable below launch defaults. Priority MUST. Risk HIGH.
- URS-06-BE-015 — System-actor writes MUST use named system identities; system actors MUST NOT sign regulated decisions. Priority MUST. Risk HIGH.
- URS-06-BE-016 — AI-advisory rows MUST set `ai_advisory = true`; AI-advisory content MUST NOT be written directly to a regulated record without separate human signature row. Priority MUST. Risk HIGH. Maps RG-06-012.
- URS-06-BE-017 — Tenant offboarding MUST seal the tenant's chains and anchor externally one final time. Priority MUST. Risk MEDIUM.
- URS-06-BE-018 — Cross-tenant break-glass read MUST emit one row in the global chain AND one in the target tenant chain; customer notification within 24 hours. Priority MUST. Risk HIGH.
- URS-06-BE-019 — Regulator-facing external anchor manifests MUST be executive-authority-co-signed. Priority MUST. Risk HIGH.
- URS-06-BE-020 — Annotations MUST live in a separate `audit_annotations` table; the original row MUST NOT mutate. Priority MUST. Risk HIGH. Maps RG-06-001.
- URS-06-BE-021 — `audit_log` row schema (DEC-06-04) is fixed; adding a column is a Class 1 change with chain-extension migration. Priority MUST. Risk HIGH.
- URS-06-BE-022 — Cluster detection MUST apply cooldown (default 30 minutes per rule) to avoid alert storms. Priority SHOULD. Risk MEDIUM.

### 15.3 Workflow (WF)

- URS-06-WF-001 — Scheduled monthly verifier per chain. Priority MUST. Risk HIGH.
- URS-06-WF-002 — Hot-to-cold archival nightly for rows older than two years. Priority MUST. Risk HIGH.
- URS-06-WF-003 — External anchoring weekly for per-tenant and global chains. Priority MUST. Risk MEDIUM.
- URS-06-WF-004 — Time-anomaly detection every 5 minutes. Priority MUST. Risk MEDIUM.
- URS-06-WF-005 — Periodic audit-trail review weekly window. Priority MUST. Risk MEDIUM.

### 15.4 Data (DATA)

- URS-06-DATA-001 — `audit_log` schema fixed at launch per DEC-06-04. Priority MUST. Risk CRITICAL.
- URS-06-DATA-002 — Retention per §13. Priority MUST. Risk HIGH.
- URS-06-DATA-003 — `pii_fields` array on every row tagging PII paths within `details_jsonb`. Priority MUST. Risk HIGH.
- URS-06-DATA-004 — `chain_id` and `chain_sequence` are deterministic and monotonic per chain; bigint per chain. Priority MUST. Risk HIGH.

### 15.5 Security (SEC)

- URS-06-SEC-001 — Database-level grants prohibit UPDATE / DELETE on `audit_log` for all application roles. Priority MUST. Risk CRITICAL.
- URS-06-SEC-002 — Storage-layer object-lock immutability on archived rows for the configured retention period. Priority MUST. Risk HIGH.
- URS-06-SEC-003 — Trigger guard rejects any UPDATE / DELETE attempt on `audit_log`. Priority MUST. Risk CRITICAL.
- URS-06-SEC-004 — Tenant isolation via TDAL + RLS on every Module 6 tenant-scoped table. Priority MUST. Risk CRITICAL.
- URS-06-SEC-005 — PII access audited as `AUDIT_PII_ACCESSED`. Priority MUST. Risk HIGH.
- URS-06-SEC-006 — Multi-factor step-up required for export, break-glass, erasure. Priority MUST. Risk HIGH.

### 15.6 Audit (AUD)

- URS-06-AUD-001 — Every audit row MUST carry `actor_user_id` (or named system identity); attribution complete. Priority MUST. Risk CRITICAL.
- URS-06-AUD-002 — Server-set `timestamp`; NTP-synchronised; time-anomaly detection. Priority MUST. Risk HIGH.
- URS-06-AUD-003 — Append-only WORM at all three layers (database / column / storage). Priority MUST. Risk CRITICAL.
- URS-06-AUD-004 — Atomic write contract (BR-06-01); failure rolls back originating action. Priority MUST. Risk CRITICAL.
- URS-06-AUD-005 — Hash chain integrity verifiable per chain at any time. Priority MUST. Risk CRITICAL.

### 15.7 AI / HITL (AI)

- URS-06-AI-001 — Module 6 contains no AI / ML components in core path; static analysis MUST find zero LLM SDK references in Module 6 source. Priority MUST. Risk HIGH.
- URS-06-AI-002 — `ai_advisory = true` MUST be set on every audit row whose content originates from AI suggestion. Priority MUST. Risk HIGH.
- URS-06-AI-003 — AI suggestion MUST NOT be written directly to a regulated record without separate human electronic-signature audit row. Priority MUST. Risk CRITICAL.

### 15.8 Integration (INT)

- URS-06-INT-001 — Bidirectional referential integrity with URS-04 `electronic_signatures` and URS-05 `approval_authority_snapshots`. Priority MUST. Risk CRITICAL.
- URS-06-INT-002 — URS-35 backup / restore MUST preserve chain hashes verbatim. Priority MUST. Risk CRITICAL.
- URS-06-INT-003 — URS-30 delivers periodic-review / integrity-violation / cluster-detection notifications. Priority MUST. Risk MEDIUM.
- URS-06-INT-004 — URS-08 (Tenant Management / Tenant Lifecycle) onboarding triggers `CHAIN_GENESIS` row insertion for the per-tenant chain. Priority MUST. Risk HIGH.
- URS-06-INT-005 — URS-08 offboarding triggers `TENANT_CHAINS_SEALED_AT_OFFBOARDING`. Priority MUST. Risk HIGH.
- URS-06-INT-006 — URS-07 (Study Management) study creation creates the study-scope `per_entity` chain genesis when the study is itself the regulated record. Priority MUST. Risk MEDIUM.

### 15.9 Reporting (REP)

- URS-06-REP-001 — Every report listed in §9 MUST be exportable with electronic signature and integrity manifest. Priority MUST. Risk MEDIUM.
- URS-06-REP-002 — Cold-tier query MUST be supported with latency badge; integrity verification works across hot + cold. Priority MUST. Risk HIGH.
- URS-06-REP-003 — Signed download URL TTL MUST be 15 minutes. Priority MUST. Risk MEDIUM.

### 15.10 Notifications (NOTIF)

- URS-06-NOTIF-001 — Every notification listed in §10 MUST be delivered through URS-30 with the specified latency. Priority MUST. Risk MEDIUM.
- URS-06-NOTIF-002 — `INTEGRITY_VIOLATION` MUST escalate to Founder within one business hour. Priority MUST. Risk CRITICAL.

### 15.11 Validation (VAL)

- URS-06-VAL-001 — Test execution against this URS MUST cover IQ (schema, RLS, indexes, triggers, grants, advisory locks, genesis row, hash chain bootstrap), OQ (per URS-06-VAL-002), PQ (per URS-06-VAL-003), regression (per URS-06-VAL-004).
- URS-06-VAL-002 — OQ MUST validate every API endpoint, every error code path, every state transition, every audit event writer, hash chain insertion ordering, integrity verifier determinism.
- URS-06-VAL-003 — PQ MUST validate write path under representative concurrency (e.g., 1000 RPS sustained per tenant) with no chain-ordering anomaly and no lock starvation.
- URS-06-VAL-004 — Regression MUST run on every Class 1 / Class 2 change including chain-migration drills.
- URS-06-VAL-005 — Requirements-to-test traceability matrix per §16.4.
- URS-06-VAL-006 — Supplier qualification pack per §17.1.
- URS-06-VAL-007 — Inspection-ready evidence index per §17.2.
- URS-06-VAL-008 — Migration evidence gate: schema migrations are idempotent; migrations seed the global chain genesis row; the integrity verifier executes deterministically against the bootstrap state; restore drill verifies chain HEAD equality with source.

---

## 16. Acceptance Criteria and Test Cases

### 16.1 Plain-language test cases

- TC-PLAIN-001 — Every action in Verixa produces an audit row that the inspector can read back later.
- TC-PLAIN-002 — If the audit row cannot be written, the action does not happen.
- TC-PLAIN-003 — Once an audit row is written, it can never be modified or deleted by any user, including platform administrators.
- TC-PLAIN-004 — The hash chain detects any tampering; the verifier walks the chain and reports any break.
- TC-PLAIN-005 — When a chain is tampered, the affected chain is quarantined and the executive authority is escalated within one business hour.
- TC-PLAIN-006 — An auditor exports a filtered view with electronic signature; the export includes an integrity manifest the inspector can verify against the platform's published external anchor.
- TC-PLAIN-007 — AI suggestions are flagged in the audit log; the human acceptance is a separate audit row with the human's signature.
- TC-PLAIN-008 — A periodic-review reviewer cannot attest their own actions.
- TC-PLAIN-009 — Cross-tenant break-glass by platform identity emits notification to the affected tenant within 24 hours.
- TC-PLAIN-010 — A user invoking GDPR right-to-erasure has their identifying fields cryptographically erased via subject-key destruction (or read-time redaction overlay where applicable); no historical audit row is modified; chain integrity is preserved; the regulatory record persists.
- TC-PLAIN-011 — Restored data from URS-35 backup produces the same chain HEAD hash as the source.
- TC-PLAIN-012 — Audit rows older than two years move to cold storage; queries still find them with a higher-latency badge.
- TC-PLAIN-013 — An auditor verifying a chain by walking the hash chain end-to-end gets a clear valid badge and the manifest.

### 16.2 Technical test cases

- TC-TECH-001 — `appendAuditRow` and originating mutation commit in the same transaction; rollback on either failure.
- TC-TECH-002 — Hash function and canonical JSON match RFC 8785 + FIPS 180-4 reference vectors; deterministic.
- TC-TECH-003 — Per-chain advisory lock prevents concurrent inserts from interleaving; chain sequence monotonic under load.
- TC-TECH-004 — Genesis row `previous_hash` matches deterministic derivation; replay produces same value.
- TC-TECH-005 — Database grants on `audit_log` deny UPDATE / DELETE for application roles; SQL probe returns permission denied.
- TC-TECH-006 — Trigger rejects UPDATE / DELETE attempts even with elevated grants for testing; reverted to deny.
- TC-TECH-007 — Storage object-lock applied to archived rows; URS-35 attempt to mutate returns immutable-storage error.
- TC-TECH-008 — Integrity verifier walks chain from genesis to HEAD recomputing each hash; verdict deterministic.
- TC-TECH-009 — Tampered row injection (test-only fixture in non-prod) detected by verifier with `INTEGRITY_VIOLATION` at the correct sequence.
- TC-TECH-010 — `INTEGRITY_VIOLATION` quarantines chain (read-only banner); export blocked; SOC alert emitted.
- TC-TECH-011 — Cold-archive run preserves `record_hash` and `previous_hash` verbatim; re-verify post-archive equals stored values.
- TC-TECH-012 — `ARCHIVAL_HASH_MISMATCH` aborts archival and pages on-call.
- TC-TECH-013 — External anchor publish writes signed manifest to regulator + customer endpoints; manifest includes chain HEAD hash matching the database.
- TC-TECH-014 — Time-anomaly detector flags drift > 100 ms; suspect rows recorded in `time_anomaly_detections`; not mutated.
- TC-TECH-015 — Cluster-detection rule fires on threshold; cooldown suppresses subsequent alerts within 30 minutes.
- TC-TECH-016 — Reviewer attempting to attest own action returns `403 REVIEWER_CANNOT_REVIEW_OWN_ACTION`.
- TC-TECH-017 — Annotation API insert succeeds in `audit_annotations`; original `audit_log` row unchanged.
- TC-TECH-018 — Annotation API attempting mutation of original returns `403 ANNOTATION_CANNOT_MUTATE_ORIGINAL`.
- TC-TECH-019 — Cryptographic erasure: (a) subject-key destruction path destroys the per-subject data-encryption key, leaving every historical `audit_log` row unmodified; the integrity verifier still validates chain HEAD because no row was changed; ciphertext is permanently undecryptable. (b) Redaction-overlay path inserts an `pii_redaction_overlays` row referencing the affected `audit_log_id`; the original row remains unchanged; the read surface renders the redacted representation by joining the overlay. In neither case is `audit_log` mutated.
- TC-TECH-020 — Retention configured below launch default returns `400 RETENTION_BELOW_MINIMUM`.
- TC-TECH-021 — Cross-tenant break-glass emits two audit rows (global + target tenant chain); customer notification queued.
- TC-TECH-022 — Schema migrations idempotent; trigger and grant present after migration.
- TC-TECH-023 — Penetration test: SQL UPDATE / DELETE attempts on `audit_log` blocked at all three layers (grant + trigger + storage).
- TC-TECH-024 — Penetration test: cross-tenant audit query without break-glass posture returns RLS-empty result; no leakage.
- TC-TECH-025 — System-actor write succeeds with named system identity; same row attempted to sign a regulated decision is refused per URS-04.
- TC-TECH-026 — AI-advisory row insert succeeds with `ai_advisory = true`; insert without flag from AI-emitting module returns `400 AI_ADVISORY_FLAG_REQUIRED`.
- TC-TECH-027 — Hot-to-cold archival follows the partition-detach path: sealed partition copied to URS-35; URS-35 confirms persistence and hash equivalence; partition detached and physically dropped only after confirmation; the logical `audit_log` view continues to span hot + cold and queries on archived rows return rows with the cold-tier latency badge. No application-layer DELETE on `audit_log` rows is observed at any point. Integrity verifier walks across the boundary seamlessly.
- TC-TECH-028 — Restore drill on URS-35 backup produces chain HEAD hash equal to source for every chain.
- TC-TECH-029 — `INTEGRITY_VIOLATION` blocks export with `409 EXPORT_BLOCKED_INTEGRITY_VIOLATION`.
- TC-TECH-030 — `appendAuditRow` performance: p95 ≤ 50 ms at 1000 RPS sustained per tenant; no lock starvation.
- TC-TECH-031 — Integrity verifier performance: ≤ 60 s for 1 M rows in a single chain.
- TC-TECH-032 — Bidirectional cross-references with URS-04 `electronic_signatures.audit_log_id` and URS-05 `approval_authority_snapshots.audit_log_id` populated atomically.
- TC-TECH-033 — Coarse `AUDIT_LOG_VIEW_OPENED` emitted once per session; per-row reads not audited.
- TC-TECH-034 — Cold-tier query returns rows with tier badge; integrity verification works seamlessly across hot + cold.
- TC-TECH-035 — Cluster-detection cooldown configurable per rule; cooldown reset behaviour deterministic.
- TC-TECH-036 — Per-tenant Merkle aggregation deterministic: same set of per-entity chain HEADs in the same canonical order produces the same Merkle root.
- TC-TECH-037 — Export manifest contains valid Merkle proof for every per-entity chain in scope; external verifier reproduces the per-tenant Merkle root from the proof and compares against the published external anchor; equality test passes.
- TC-TECH-038 — Merkle proof verification fails when (a) a leaf is altered, (b) a sibling hash in the path is altered, (c) the root is altered; each tampering case produces explicit Merkle-proof rejection.
- TC-TECH-039 — `audit_log` row mutation attempted directly via raw SQL is denied at three layers: application role grants, table trigger, and (for archived rows) cold-storage object-lock.
- TC-TECH-040 — Three-row atomic insert (audit_log + electronic_signatures + approval_authority_snapshots) using preallocated UUIDs and `INITIALLY DEFERRED` foreign keys: success when all three present; rollback when any one is missing or mismatched at COMMIT time.
- TC-TECH-041 — `AUDIT_LOG_VIEW_OPENED` audit row emitted exactly once per user-session per tenant scope when the audit-viewer surface is opened; subsequent reads in the same session do not produce additional rows.
- TC-TECH-042 — `AUDIT_PII_ACCESSED` audit row emitted on every successful unmasking of PII by a caller holding `audit:read_pii`, capturing the affected `audit_log_id` set and field paths revealed.
- TC-TECH-043 — Cross-tenant break-glass read by platform identity emits two audit rows: `PLATFORM_TENANT_ACCESS_USED` in the global chain AND `PLATFORM_TENANT_ACCESS_NOTIFIED` in the target tenant's per-tenant chain; the target-tenant notification surface displays the event within 24 hours; URS-30 customer-notification e-mail is queued.
- TC-TECH-044 — `audit_event_policy_registry` lookup at `appendAuditRow` time: an `action_code` whose policy has `ai_source_required = true` causes the library to refuse insertion lacking `ai_advisory = true` with `400 AI_ADVISORY_FLAG_REQUIRED`.
- TC-TECH-045 — Periodic-review queue surfaces only events whose policy `review_required = true` AND whose `severity in ('high','critical')`.
- TC-TECH-046 — `chain_id` derivation deterministic per DEC-06-22: same inputs produce same `chain_id`; per-entity `chain_id = SHA-256(tenant_id || ':' || entity_type || ':' || target_record_id)` reproducible from external test vectors.
- TC-TECH-047 — `CHAIN_GENESIS` row appears at `chain_sequence = 1` for every per-entity / per-tenant / global chain; the first domain event appears at `chain_sequence = 2` per DEC-06-23. Duplicate genesis-plus-domain-creation does not occur.

### 16.3 Acceptance criteria (Given / When / Then)

#### Functional

- AC-06-FUN-01 — Given a regulated mutation, When `appendAuditRow` runs, Then audit row is inserted with valid hash chain in the same transaction.
- AC-06-FUN-02 — Given an integrity verifier run on a clean chain, When verifier walks genesis to HEAD, Then verdict is `valid`.
- AC-06-FUN-03 — Given a tampered row in test fixture, When verifier runs, Then `INTEGRITY_VIOLATION` emitted at correct sequence.
- AC-06-FUN-04 — Given an AI-emitting module, When it appends without `ai_advisory = true`, Then `400 AI_ADVISORY_FLAG_REQUIRED`.

#### Permissions

- AC-06-PERM-01 — Given a non-administrator caller, When attempting mutation surfaces, Then HTTP 403.
- AC-06-PERM-02 — Given a periodic-review attestation by the actor of the row, When called, Then HTTP 403.

#### API

- AC-06-API-01 — Every endpoint listed in §6.3 returns the documented status codes.
- AC-06-API-02 — Every error response carries the structured envelope per §11.1.

#### Audit

- AC-06-AUD-01 — Every Module 6 mutation produces an audit row in the appropriate chain.
- AC-06-AUD-02 — Audit-write failure rolls back the originating action.

#### Data integrity

- AC-06-DI-01 — Chain HEAD hash equals SHA-256 of last row's previous_hash + canonical JSON.
- AC-06-DI-02 — Backup-restore drill produces same chain HEAD as source.

#### Integration

- AC-06-INT-01 — URS-04 `electronic_signatures.audit_log_id` and URS-05 `approval_authority_snapshots.audit_log_id` populated atomically with `audit_log.e_sig_id` and `audit_log.authority_snapshot_id`.
- AC-06-INT-02 — URS-08 onboarding triggers `CHAIN_GENESIS`.

#### Report / export

- AC-06-REP-01 — Every export carries integrity manifest + electronic signature + countersignature.

#### AI / HITL

- AC-06-AI-01 — Static analysis finds zero LLM SDK references in Module 6 source.
- AC-06-AI-02 — `ai_advisory = true` enforced on every AI-suggestion-originated row.

#### Negative paths

- AC-06-NEG-01 — Every error code in §11.2 reachable by automated test.

#### Performance

- AC-06-PERF-01 — `appendAuditRow` p95 ≤ 50 ms at 1000 RPS.
- AC-06-PERF-02 — Integrity verifier ≤ 60 s for 1 M rows per chain.

#### Security

- AC-06-SEC-01 — Database grants + trigger + storage object-lock all deny UPDATE / DELETE on `audit_log`.
- AC-06-SEC-02 — Cross-tenant query without break-glass returns RLS-empty.

#### Migration / backfill

- AC-06-MIG-01 — Module 6 migrations idempotent.
- AC-06-MIG-02 — Migrations seed global chain genesis row; verifier passes against bootstrap state.

### 16.4 Requirements-to-test traceability

| Requirement | Plain-language | Technical | Given / When / Then |
|---|---|---|---|
| URS-06-FE-001 | TC-PLAIN-006 | (UI test) | — |
| URS-06-FE-002 | — | (PII masking test) | — |
| URS-06-FE-003 | TC-PLAIN-013 | (UI test) | AC-06-DI-01 |
| URS-06-FE-004 | TC-PLAIN-006 | TC-TECH-029 | — |
| URS-06-FE-005 | TC-PLAIN-007 | TC-TECH-026 | AC-06-AI-02 |
| URS-06-FE-006 | TC-PLAIN-008 | TC-TECH-016 | AC-06-PERM-02 |
| URS-06-FE-007 | — | (self-view test) | — |
| URS-06-FE-008 | — | (UI test) | — |
| URS-06-FE-009 | TC-PLAIN-012 | TC-TECH-034 | — |
| URS-06-FE-010 | — | TC-TECH-022 | — |
| URS-06-FE-011 | — | (accessibility test) | — |
| URS-06-BE-001 | TC-PLAIN-002 | TC-TECH-001 | AC-06-FUN-01 |
| URS-06-BE-002 | TC-PLAIN-004 | TC-TECH-002 | AC-06-DI-01 |
| URS-06-BE-003 | — | TC-TECH-003 | AC-06-FUN-01 |
| URS-06-BE-004 | — | TC-TECH-004 | — |
| URS-06-BE-005 | TC-PLAIN-003 | TC-TECH-005, TC-TECH-006, TC-TECH-007 | AC-06-SEC-01 |
| URS-06-BE-006 | — | (server timestamp test) | — |
| URS-06-BE-007 | TC-PLAIN-013 | TC-TECH-008, TC-TECH-009 | AC-06-FUN-02, AC-06-FUN-03 |
| URS-06-BE-008 | TC-PLAIN-005 | TC-TECH-010 | — |
| URS-06-BE-009 | — | TC-TECH-011, TC-TECH-012 | — |
| URS-06-BE-010 | — | TC-TECH-013 | — |
| URS-06-BE-011 | — | TC-TECH-014 | — |
| URS-06-BE-012 | TC-PLAIN-008 | TC-TECH-016 | AC-06-PERM-02 |
| URS-06-BE-013 | TC-PLAIN-010 | TC-TECH-019 | — |
| URS-06-BE-014 | — | TC-TECH-020 | — |
| URS-06-BE-015 | — | TC-TECH-025 | — |
| URS-06-BE-016 | TC-PLAIN-007 | TC-TECH-026 | AC-06-AI-02 |
| URS-06-BE-017 | — | (offboarding test) | — |
| URS-06-BE-018 | TC-PLAIN-009 | TC-TECH-021 | — |
| URS-06-BE-019 | — | (executive authority co-sign test) | — |
| URS-06-BE-020 | TC-PLAIN-003 | TC-TECH-017, TC-TECH-018 | — |
| URS-06-BE-021 | — | TC-TECH-022 | — |
| URS-06-BE-022 | — | TC-TECH-015, TC-TECH-035 | — |
| URS-06-WF-001 | — | TC-TECH-008 | AC-06-FUN-02 |
| URS-06-WF-002 | TC-PLAIN-012 | TC-TECH-011, TC-TECH-027 | — |
| URS-06-WF-003 | — | TC-TECH-013 | — |
| URS-06-WF-004 | — | TC-TECH-014 | — |
| URS-06-WF-005 | TC-PLAIN-008 | TC-TECH-016 | AC-06-PERM-02 |
| URS-06-DATA-001 | — | TC-TECH-022 | — |
| URS-06-DATA-002 | — | TC-TECH-022, TC-TECH-027 | — |
| URS-06-DATA-003 | — | (PII tag test) | — |
| URS-06-DATA-004 | — | TC-TECH-003 | — |
| URS-06-SEC-001 | TC-PLAIN-003 | TC-TECH-005, TC-TECH-023 | AC-06-SEC-01 |
| URS-06-SEC-002 | — | TC-TECH-007 | AC-06-SEC-01 |
| URS-06-SEC-003 | TC-PLAIN-003 | TC-TECH-006 | AC-06-SEC-01 |
| URS-06-SEC-004 | — | TC-TECH-024 | AC-06-SEC-02 |
| URS-06-SEC-005 | — | (PII access audit test) | — |
| URS-06-SEC-006 | — | (MFA step-up test) | — |
| URS-06-AUD-001 | — | (attribution test) | — |
| URS-06-AUD-002 | — | (server timestamp + NTP test) | — |
| URS-06-AUD-003 | TC-PLAIN-003 | TC-TECH-005..007 | AC-06-SEC-01 |
| URS-06-AUD-004 | TC-PLAIN-002 | TC-TECH-001 | AC-06-AUD-02 |
| URS-06-AUD-005 | TC-PLAIN-004, TC-PLAIN-013 | TC-TECH-008, TC-TECH-009, TC-TECH-031 | AC-06-DI-01 |
| URS-06-AI-001 | — | (static analysis) | AC-06-AI-01 |
| URS-06-AI-002 | TC-PLAIN-007 | TC-TECH-026 | AC-06-AI-02 |
| URS-06-AI-003 | TC-PLAIN-007 | TC-TECH-026 | AC-06-AI-02 |
| URS-06-INT-001 | — | TC-TECH-032 | AC-06-INT-01 |
| URS-06-INT-002 | TC-PLAIN-011 | TC-TECH-028 | AC-06-DI-02 |
| URS-06-INT-003 | TC-PLAIN-005 | (notification test) | — |
| URS-06-INT-004 | — | (onboarding genesis test) | AC-06-INT-02 |
| URS-06-INT-005 | — | (offboarding seal test) | — |
| URS-06-REP-001 | TC-PLAIN-006 | (export test) | AC-06-REP-01 |
| URS-06-REP-002 | TC-PLAIN-012 | TC-TECH-034 | — |
| URS-06-REP-003 | — | (TTL test) | — |
| URS-06-NOTIF-001 | — | (notification delivery test) | — |
| URS-06-NOTIF-002 | TC-PLAIN-005 | (Founder escalation test) | — |
| URS-06-VAL-001 | — | TC-TECH-022 | — |
| URS-06-VAL-002 | All applicable | All applicable | All applicable |
| URS-06-VAL-003 | — | TC-TECH-030 | AC-06-PERF-01 |
| URS-06-VAL-004 | — | full TC-TECH suite | — |
| URS-06-VAL-005 | — | this table is the seed | — |
| URS-06-VAL-006 | — | (supplier qualification) | — |
| URS-06-VAL-007 | — | (evidence index) | — |
| URS-06-VAL-008 | TC-PLAIN-011 | TC-TECH-022, TC-TECH-028 | AC-06-MIG-01, AC-06-MIG-02 |

---

## 17. Validation and CSV/CSA Evidence Expectations

| Item | Required evidence |
|---|---|
| URS traceability | Matrix linking every requirement identifier in §15 to test-case identifiers and to a regulatory-mapping row in §14 |
| Risk assessment | GAMP 5 risk register; risk-based assurance per FDA CSA |
| Configuration specification | Documented seed of `audit_chain_heads` (global chain genesis); retention policy launch defaults; cluster-detection rule launch set |
| Functional specification | Matches §6 of this document |
| Design specification | Matches §6.1–§6.4 |
| Test protocols | IQ (schema, RLS, indexes, triggers, grants on `audit_log`, advisory locks, genesis row, chain bootstrap, hash function reference vectors); OQ per URS-06-VAL-002; PQ per URS-06-VAL-003; regression per URS-06-VAL-004 |
| Test evidence | Pass / fail records per protocol step, traced to requirement identifier |
| Defect log | Defects mapped to URS requirement identifiers; resolved before release |
| Requirements traceability matrix | Per §16.4 |
| Release approval | Electronically signed by Quality Lead, Validation Lead, Information Security Lead, Regulatory Affairs Lead, executive authority |
| Training record | Engineering, QA, validation, operations trained on Module 6 expected state including chain integrity, WORM posture, atomic write contract |
| Periodic review | Annual review per EU GMP Annex 11 §11; trigger reviews on every Class 1 / Class 2 change |
| Data migration evidence | Backfill of genesis hashes; chain-extension migrations idempotent; chain integrity verifier validates against migrated state; restore drill verifies chain HEAD equality with source |

### 17.1 Supplier and service-provider qualification pack

| Category | Required evidence |
|---|---|
| Cloud hosting provider | Inherited from URS-01 §17.1 |
| Object-storage provider (cold archive) | Object-lock immutability period evidence; retention compliance evidence; right-to-audit |
| Time service (NTP) | Stratum-1 / stratum-2 reference evidence; NTP drift bounds documentation |
| RFC 3161 time-stamp authority (where tenant elects) | Right-to-audit; certificate chain; revocation handling |
| Backup / restore provider (URS-35) | Restore drill preserving chain HEAD hash equality; retention compliance |
| Security-operations / SIEM | Alert routing per §12.9 |
| Notification provider | Inherited from URS-01 §17.1 |

### 17.2 Inspection-ready evidence index

| Evidence item | Owner | Location / system of record | Retention | Linked requirement | Inspection use |
|---|---|---|---|---|---|
| Audit log rows | QA / IS | `audit_log` (hot) + URS-35 cold archive | seven years (twenty-five years where authority snapshot) | URS-06-AUD-001..005 | demonstrate operator-action evidence |
| Hash chain | QA / IS | `audit_log.previous_hash`, `record_hash` + `audit_chain_heads` | per audit log | URS-06-BE-002, URS-06-AUD-005 | demonstrate tamper evidence |
| Integrity verifier run history | IS / QA | `integrity_verifier_runs` | seven years | URS-06-BE-007, URS-06-AUD-005 | demonstrate verification cadence + verdicts |
| External anchor manifests (regulator) | Founder + QA / IS | regulator-readable endpoint + `external_anchors` table | retain (long-term) | URS-06-BE-019 | demonstrate publicly verifiable chain HEAD hashes |
| External anchor manifests (customer) | QA / IS | customer-readable endpoint + `external_anchors` table | retain (long-term) | URS-06-BE-010 | demonstrate tenant-readable proof |
| Integrity manifest exports (per chain) | QA / IS | export bundles | retain per export | URS-06-REP-001 | inspector / customer chain verification |
| Periodic audit-trail review attestation | QA / IS | review queue attestation export | seven years | URS-06-WF-005, URS-06-NOTIF-002 | demonstrate review cadence |
| Time-anomaly detection log | IS | `time_anomaly_detections` | seven years | URS-06-BE-011 | demonstrate clock integrity |
| PII erasure log | Tenant DPO + IS | `pii_field_erasures` | retain (long-term) | URS-06-BE-013 | demonstrate privacy compliance |
| Cold-archive manifest | Platform + QA | `cold_archive_manifest` | retain | URS-06-BE-009 | demonstrate hot-to-cold reconciliation |
| Cross-tenant break-glass evidence | Founder + IS | global chain + target tenant chain notification | retain (long-term) | URS-06-BE-018 | demonstrate platform-access governance |
| Validation evidence pack (IQ / OQ / PQ) | Validation | testing system of record | retain per release | URS-06-VAL-001..008 | release approval |
| Release approval (electronically signed) | Founder, QA, RA, Validation, Information Security | document control (URS-12) | retain per release | URS-06-VAL-007 | demonstrate authority chain for release |

---

## 18. Closed Decision and Dependency Register

### 18.1 Closed Launch Decisions Register

Every closed launch decision is locked in §2.3 and summarised below. No Module 6 internal open questions remain.

| Closed decision | Spec reference |
|---|---|
| Append-only WORM audit log at three layers | DEC-06-01 |
| Three chain scopes (per-entity / per-tenant / global) | DEC-06-02 |
| SHA-256 + RFC 8785 canonical JSON | DEC-06-03 |
| Audit row schema fixed at launch | DEC-06-04 |
| Atomic write contract with originating mutation | DEC-06-05 |
| Retention defaults (7y / 25y) | DEC-06-06 |
| Hot-to-cold archival after 2 years | DEC-06-07 |
| Integrity verifier scheduled + on-demand + on export + on restore drill | DEC-06-08 |
| Audit access roles + `audit:read_pii` permission | DEC-06-09 |
| Export with electronic signature + integrity manifest + 15-min TTL | DEC-06-10 |
| Per-chain advisory lock | DEC-06-11 |
| Audit log unmodifiable; annotation in separate chain | DEC-06-12 |
| PII handling + erasure via subject-key destruction or read-time redaction overlay (no row mutation) | DEC-06-13, DEC-06-13b |
| Periodic audit-trail review (high-risk in 1 business day) | DEC-06-14 |
| AI / LLM advisory flag segregation | DEC-06-15 |
| Server clock UTC + NTP + time-anomaly detection | DEC-06-16 |
| Genesis row per chain with deterministic `previous_hash` | DEC-06-17 |
| Bidirectional cross-references with URS-04 / URS-05 | DEC-06-18 |
| URS-35 backup / restore preserves chain hashes verbatim | DEC-06-19 |
| Named system identities; system actors not signers | DEC-06-20 |

### 18.2 Dependencies

| ID | Dependency | Source | Impact | Blocking? | Mitigation |
|---|---|---|---|---|---|
| DEP-06-01 | URS-01 authentication, MFA step-up | URS-01 | Substrate | Blocking | none |
| DEP-06-02 | URS-02 effective permissions including `audit:read_pii` | URS-02 | Read / export gates | Blocking | none |
| DEP-06-03 | URS-03 active scope | URS-03 | Tenant-scope binding for reads | Blocking | none |
| DEP-06-04 | URS-04 e-signature ceremony, signature chain integrity | URS-04 | Cross-references; export integrity | Blocking | none |
| DEP-06-05 | URS-05 authority resolver and snapshot composition | URS-05 | Cross-references; PII permission | Blocking | none |
| DEP-06-06 | URS-08 (Tenant Management / Tenant Lifecycle) onboarding / offboarding lifecycle | URS-08 | Genesis row insertion at onboarding; chain sealing at offboarding | Blocking | none |
| DEP-06-06a | URS-07 (Study Management) study lifecycle events | URS-07 | Per-entity chain genesis for study-bound regulated records; standard `appendAuditRow` consumer | Blocking for study-bound modules | none |
| DEP-06-07 | URS-30 notifications | URS-30 | Periodic review, integrity violation, cluster detection | Non-blocking | direct e-mail fallback |
| DEP-06-08 | URS-32 AI / MIRA modules emit `ai_advisory = true` | URS-32 | Audit row segregation | Blocking | enforced by `400 AI_ADVISORY_FLAG_REQUIRED` at append |
| DEP-06-09 | URS-35 backup / restore preserves chain hashes verbatim; cold storage with object-lock | URS-35 | Hot-to-cold archival; DR | Blocking for PQ | DR drill |

---

## 19. Completeness Checklist

| Item | Yes / No | Evidence |
|---|---|---|
| Controlled-document metadata complete? | Yes | front matter |
| Approval block complete? | Yes (signatures pending) | Document Approval section |
| Version history complete? | Yes | Version History |
| Glossary complete? | Yes | §0.6 |
| Scope complete? | Yes | §2 |
| Roles and permissions complete? | Yes | §3 |
| User journeys complete? | Yes | §4 (28 journeys) |
| Front-end complete? | Yes | §5 |
| Backend complete? | Yes | §6 |
| Data model complete? | Yes | §6.2 |
| APIs complete? | Yes | §6.3 |
| Resolver / verifier semantics complete? | Yes | §6.4, §6.5 |
| Business rules complete? | Yes | §6.5 |
| Audit trail complete (Module 6 emits about itself)? | Yes | §6.6 |
| AI / Human-in-the-Loop complete? | Yes (no AI in core path; AI-advisory flag policy specified) | §8 |
| Reports complete? | Yes | §9 |
| Notifications complete? | Yes | §10 |
| Cross-module wiring complete? | Yes | §7 |
| Change-impact matrix complete? | Yes | §7.2 |
| Negative paths complete? | Yes | §11 |
| Security / privacy / tenant isolation complete? | Yes | §12 |
| ALCOA+ complete? | Yes | §13 |
| Regulatory mapping complete? | Yes | §14 |
| Predicate-rule applicability matrix complete? | Yes | §14.1 |
| Requirements register complete? | Yes | §15 |
| Acceptance tests complete? | Yes | §16 |
| Requirements-to-test traceability complete? | Yes | §16.4 |
| Validation evidence complete? | Yes | §17, §17.1, §17.2, URS-06-VAL-001..008 |
| Supplier and service-provider qualification pack complete? | Yes | §17.1 |
| Decisions and dependencies registered (no internal decisions outstanding)? | Yes | §18.1, §18.2 |
| Final quality gate answered? | Yes | §20 |

---

## 20. Final Module Output Quality Gate

**URS approval is separate from validation execution.** This document becomes "Approved Controlled URS — released for engineering implementation and validation planning" upon signature capture in the Document Approval block; it becomes "Released for validation execution" only after URS-06-VAL-008 (Migration Evidence Gate) and the §17 validation evidence pack are satisfied. **No Module 6 internal open questions remain.**

- **Specification ready for engineering review?** Yes — every MUST requirement is declarative, atomic, and testable. Front end, back end, data, application programming interface, atomic write contract, hash chain semantics, integrity verifier, retention engine, cold-archive bridge, external anchoring, periodic-review apparatus, security, integration, and the WORM-storage posture are covered as a single self-contained contract.
- **Specification ready for quality validation review?** Yes — Installation, Operational, and Performance Qualification scope is specified; the traceability matrix template is in §16.4; the global-chain genesis seed is enumerated.
- **Specification ready for compliance review?** Yes — ALCOA+ table, regulatory mapping, and predicate-rule applicability matrix are populated.
- **Specification ready for inspector or client review?** Yes — every regulated assertion traces to a regulatory clause and to a test case; no internal item remains open.
- **Specification ready for Founder approval?** Yes.
- **Blocking gaps?** **None internal.** Cross-module dependencies (§18.2) are owned by their named companion modules and tracked at the program level. The Installation Qualification gate URS-06-VAL-008 and the §17 evidence pack govern only the transition to "Released for validation execution".
- **Two-step release path:**
  1. **Approved Controlled URS — released for engineering implementation and validation planning.** Reached upon signature capture. Engineering may begin implementation; validation may begin protocol authoring.
  2. **Released for validation execution.** Reached after URS-06-VAL-008 is satisfied and the §17 evidence pack is complete. Document Status updates from "Approved Controlled URS" to "Released for validation execution".

---

## Appendix A — Audit Substrate Pipeline Composite

```mermaid
flowchart TD
  A([Consuming module begins regulated mutation]) --> B[BEGIN TRANSACTION]
  B --> C[Originating INSERT / UPDATE on regulated record]
  C --> D[Module 6 appendAuditRow with content e_sig_id authority_snapshot_id ai_advisory severity]
  D --> E[Acquire pg_advisory_xact_lock for chain scope]
  E --> F[Read chain HEAD record_hash and chain_sequence]
  F --> G[Compose canonical JSON of content per RFC 8785]
  G --> H[record_hash = SHA-256 previous_hash plus canonical_json]
  H --> I[INSERT audit_log row at chain_sequence + 1]
  I --> J[UPDATE audit_chain_heads pointer]
  J --> K{Originating + audit + snapshot all succeeded?}
  K -- no --> X[ROLLBACK; release lock; return error]
  K -- yes --> L[COMMIT; release lock]
  L --> M[URS-30 notifications for severity high or critical]
  M --> N[Scheduled monthly verifier covers this row eventually]
  N --> O[External anchor publishes chain HEAD weekly]
  O --> P[Hot-to-cold archival after 2 years preserves hash verbatim]
  P --> Q[Inspector queries the chain; verifier validates; export with electronic signature and integrity manifest]
```

— End of Module 6 User Requirements Specification —




