Skip to content

Domain Specification: Audit & Governance

Validated against PRD v1.0 — All FR-AU-* requirements. See Traceability Matrix.


1. Context Overview

Bounded Context: audit
Responsibility: Immutable append-only event log. Deterministic replay. Segregation of duties enforcement.
Owns: AuditEvent aggregate.
Consumed By: ALL bounded contexts (write events), Auditors (read/replay).
Events Published: AuditEventRecorded.


2. Event Model

data class AuditEvent(
    val eventId: Long,                     // BIGSERIAL — sequential within partition
    val correlationId: UUID,              // links events across a single request
    val eventType: EventType,             // STATE_TRANSITION, MODULE_INVOCATION, DECISION, CONFIG_CHANGE, DATA_ACCESS, AUTH
    val actorType: ActorType,             // USER, SYSTEM
    val actorId: UUID?,
    val contextType: ContextType,         // CUSTOMER, CASE, WORKFLOW
    val contextId: UUID,
    val action: String,                   // "State transition: ANALYST_REVIEW → EDD_REVIEW"
    val payload: JsonNode,                // full event data
    val configVersion: String?,
    val timestamp: Instant
)

enum class EventType { STATE_TRANSITION, MODULE_INVOCATION, DECISION, CONFIG_CHANGE, DATA_ACCESS, AUTH }
enum class ActorType { USER, SYSTEM }
enum class ContextType { CUSTOMER, CASE, WORKFLOW, CONFIG }

3. What Gets Logged

Action EventType Payload Includes
Workflow state transition STATE_TRANSITION fromState, toState, workflowInstanceId, trigger
Module invocation (screening, risk, network) MODULE_INVOCATION moduleType, request payload, response payload, executionTimeMs, configVersion
Human decision (approve, reject, adjudicate) DECISION decisionType, actor, rationale, evidenceRefs, configVersion
Configuration change CONFIG_CHANGE configVersion, changedBy, changeSummary, oldValues, newValues
Sensitive data access DATA_ACCESS userId, accessedFields, customerId, ipAddress
Authentication AUTH userId, success/failure, ipAddress, reason (if failed)

Events are write-only. No UPDATE, no DELETE. Immutable from the moment of recording.


4. API Contracts

4.1 Record Event (Internal)

POST /api/v1/audit/events
Authorization: System

Request:
{
  "correlationId": "uuid",
  "eventType": "DECISION",
  "actorType": "USER",
  "actorId": "user-uuid",
  "contextType": "CASE",
  "contextId": "case-uuid",
  "action": "Onboarding decision: APPROVED",
  "payload": { "decisionType": "APPROVED", "rationale": "...", "configVersion": "1.0.3" }
}
Response 201: { "eventId": 14932 }

4.2 Replay Case (Auditor)

GET /api/v1/audit/replay?contextType=CASE&contextId={caseId}&from=2024-01-01&to=2025-06-01&page=1&limit=100
Authorization: Bearer <jwt> (AUDITOR role)

Response 200:
{
  "contextType": "CASE",
  "contextId": "case-uuid",
  "events": [
    { "eventId": 14200, "timestamp": "2025-06-01T10:00:00Z", "eventType": "STATE_TRANSITION", "action": "CREATED → ASSIGNED", "actor": "System" },
    { "eventId": 14201, "timestamp": "2025-06-01T10:05:00Z", "eventType": "MODULE_INVOCATION", "action": "Name Screening completed", "actor": "System" },
    { "eventId": 14250, "timestamp": "2025-06-01T13:00:00Z", "eventType": "DECISION", "action": "APPROVED", "actor": "Jane Doe (KYC Analyst)", "payload": { "rationale": "..." } }
  ],
  "summary": {
    "totalEvents": 52,
    "decisions": [{ "type": "APPROVED", "actor": "Jane Doe", "configVersion": "1.0.3" }],
    "moduleInvocations": 3,
    "stateTransitions": 8
  }
}

4.3 Export Audit Package

POST /api/v1/audit/export
Authorization: Bearer <jwt> (AUDITOR role)

Request: { "contextType": "CASE", "contextId": "uuid", "format": "PDF" }
Response 200: Binary PDF with full reconstruction.

5. Segregation of Duties

Enforced at the application layer:

Rule Enforcement
Case creator ≠ approver Checked on decision: if case.createdBy == requestingUser → 403 Forbidden
Analyst ≠ FCC reviewer for same case Checked on review: if case.lastAnalyst == requestingUser → 403 Forbidden
Auditor = read-only Role has no POST/PATCH/DELETE permissions on any domain endpoint
Override requires secondary approval Override decision creates PENDING_REVIEW task for second approver

All SoD violations are logged as audit events with eventType=DECISION, action="SoD VIOLATION ATTEMPT", payload={actor, attemptedAction, blockedAt}.


6. Retention

  • Active: 7 years from event timestamp (NFR-C01). Partitioned by month.
  • Archived: After 7 years, partition detached and moved to cold storage. Retrievable within 30 days.
  • Deletion: Never automatically deleted. Manual deletion requires break-glass procedure with dual approval.

Spec validated against PRD v1.0 requirements FR-AU-01 through FR-AU-03.