Files
KArtSell.Aegis/docs/CURRENT/SLICE_SPECS/VS-27-SLICE_SPEC.md
T
kjh2064 cedc8d79ee docs: resolve VS-03/04/12/14 numbering collision (renumber to VS-26/27/28/29)
Renumbers the four 2026-08-07 slices (ApprovalWorkflow, AuditTrail,
TradeExecution, PortfolioReconciliation) to previously-unused VS-26..29,
leaving WBS_MASTER.csv's original VS-03/04/12/14 definitions (IngestMarketDataPIT,
ApplyCorporateActions, RankBuyCandidates, GenerateDailyRecommendations) untouched,
per docs/DECISIONS/ADR-WBS-001-slice-renumbering.md.

While investigating, found two things not yet resolved by this commit:
- DEBT-017 (duplicate ApprovalWorkflow implementation): the tested backend
  (ApprovalWorkflow/) is [DontRegister]'d dead code; the live one
  (Features/ApprovalWorkflow/, wired in Program.cs) has no dedicated tests.
  AEG-VS-26-01 downgraded from COMPLETED to BLOCKED in the tracker pending an
  architect decision on which implementation is canonical.
- Features/MarketData and Features/Portfolio (VS-03/04/05/08 Market Data
  Ingestion Dashboard, Portfolio Rebalance, Risk Metrics, Dashboard) are a
  third, already-implemented-and-tested body of work entirely absent from
  WBS_PROGRESS_TRACKER.csv. Flagged in CURRENT_ROADMAP.md as a follow-up.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 12:36:00 +09:00

8.3 KiB

VS-27: Immutable Audit Trail (GDPR/Compliance)

Vertical Slice: VS-27 (Audit Log & Compliance Trail)
Version: 1.0 COMPLETE
Date: 2026-08-07
Owner: Compliance + Security
Status: READY FOR IMPLEMENTATION
Depends On: VS-02/03 (governance foundation) COMPLETE


📋 User Story

As a compliance officer / auditor
I want to maintain immutable audit trail of all model operations
So that we can satisfy regulatory audits (FSS, GDPR, PCI-DSS) and forensically investigate issues

Acceptance Criteria:

  • All model operations logged: create, approve, activate, deactivate, sell decision
  • Audit events immutable: INSERT-only, no UPDATE/DELETE
  • Event data: timestamp, actor, action, model_id, result, evidence links
  • GDPR: Right-to-be-forgotten handling for customer data
  • Retention: 7 years (regulatory requirement)
  • Compliance: Links to approval evidence, PBO/DSR, backtest reports

🎯 Non-Goals

  • Real-time alerting on suspicious activity (belongs to separate monitoring slice)
  • Machine learning for anomaly detection (deferred)
  • Custom compliance report generation (belongs to reporting slice)
  • Encryption of audit logs at rest (assume PostgreSQL encryption)

📊 Data Schema

-- Audit trail (immutable, INSERT-only)
CREATE TABLE compliance.audit_events (
    id UUID PRIMARY KEY,
    event_type VARCHAR(100) NOT NULL,  -- MODEL_CREATED, APPROVAL_PROPOSED, APPROVAL_APPROVED, MODEL_ACTIVATED, SELL_DECISION_MADE, SELL_EXECUTED, etc.
    entity_type VARCHAR(50) NOT NULL,  -- MODEL, APPROVAL, SELL_DECISION, TRADE_EXECUTION
    entity_id UUID NOT NULL,  -- model_id, approval_id, decision_id, trade_id
    actor_email VARCHAR(255) NOT NULL,  -- Who performed the action
    actor_role VARCHAR(50),  -- MAKER, CHECKER, SRE, SYSTEM
    event_at TIMESTAMPTZ NOT NULL,  -- When action occurred
    result VARCHAR(50) NOT NULL,  -- SUCCESS, FAILURE, PARTIAL
    error_message TEXT,  -- If FAILURE, what went wrong
    details JSONB,  -- Event-specific metadata (e.g., model version, approval notes)
    evidence_links TEXT[],  -- Array of evidence artifact URLs (S3, logs, reports)
    ip_address INET,  -- Source IP for security analysis
    user_agent TEXT,  -- Client identifier
    published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    correlation_id UUID NOT NULL,  -- Links to related events
    revision INT NOT NULL DEFAULT 1
);

-- GDPR: Personal data retention tracker
CREATE TABLE compliance.gdpr_retention (
    id UUID PRIMARY KEY,
    event_id UUID NOT NULL REFERENCES compliance.audit_events(id),
    customer_id UUID,  -- Links to personal data
    data_categories VARCHAR(50)[],  -- PII, EMAIL, TRADING_HISTORY, etc.
    retention_ends_at DATE,  -- When to purge
    purge_status VARCHAR(50),  -- PENDING, PURGED, EXCEPTION
    published_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

🔐 Event Types Logged

Event Trigger Logged By Details
MODEL_CREATED New model version System model_id, algorithm, version
MODEL_ARCHIVED Model retired SRE model_id, reason
APPROVAL_PROPOSED Maker submits proposal Maker approval_id, model_id, justification
APPROVAL_APPROVED Checker signs off Checker approval_id, evidence_links, notes
APPROVAL_REJECTED Checker rejects Checker approval_id, rejection_reason
MODEL_ACTIVATED SRE activates model SRE model_id, effective_at, approval_id
MODEL_DEACTIVATED SRE deactivates SRE model_id, reason
SELL_DECISION_MADE Engine generates sell signal System decision_id, model_id, signal_strength
SELL_EXECUTED Trade executed System trade_id, quantity, price, model_id
BACKTEST_COMPLETED Shadow run finishes System job_id, oos_score, pbo_score, dsr
DATA_CORRECTION Source data corrected Data Gov entity_id, old_value, new_value
COMPLIANCE_AUDIT Auditor reviews trail Auditor audit_scope, findings, escalation

🔄 GDPR Compliance Flow

Right-to-Be-Forgotten (Article 17)

Scenario: Customer requests deletion of personal data
Process:

  1. Identify: Find all audit_events linked to customer_id
  2. Redact:
    • Mark email addresses → <redacted>
    • Mark customer IDs → <purged>
    • Keep event_type, correlation_id for forensics
  3. Retain: Keep anonymized event log for 7 years (legal requirement)
  4. Verify: Confirm no personal data remains via compliance.gdpr_retention

Implementation:

-- Mark GDPR retention as PURGED (no actual deletion)
UPDATE compliance.gdpr_retention 
SET purge_status = 'PURGED', retention_ends_at = NOW()
WHERE customer_id = $1;

-- Redact personal data in audit_events (soft delete)
UPDATE compliance.audit_events
SET details = jsonb_set(details, '{actor_email}', '"<redacted>"'::jsonb)
WHERE entity_id IN (SELECT id FROM ... WHERE customer_id = $1);

📋 API Contract (Query-Only)

GET /audit/events (Compliance Officer)

Query Params:

  • entityId=uuid (filter by entity)
  • eventType=MODEL_ACTIVATED (filter by event)
  • dateFrom=2026-01-01&dateTo=2026-12-31 (date range)
  • actorEmail=user@company.com (who performed action)

Response (200):

{
  "items": [
    {
      "id": "event-uuid",
      "eventType": "MODEL_ACTIVATED",
      "entityId": "model-uuid",
      "actorEmail": "sre@company.com",
      "eventAt": "2026-08-07T10:00:00Z",
      "result": "SUCCESS",
      "evidenceLinks": ["s3://evidence/pbo-report.json"],
      "correlationId": "correlation-uuid"
    }
  ],
  "total": 1,
  "pages": 1
}

GET /audit/events/{id} (Full Detail)

Response (200):

{
  "id": "event-uuid",
  "eventType": "MODEL_ACTIVATED",
  "entityType": "MODEL",
  "entityId": "model-uuid",
  "actorEmail": "sre@company.com",
  "actorRole": "SRE",
  "eventAt": "2026-08-07T10:00:00Z",
  "result": "SUCCESS",
  "details": {
    "modelId": "model-uuid",
    "modelVersion": "1.0.0",
    "effectiveAt": "2026-09-15",
    "approvalId": "approval-uuid"
  },
  "evidenceLinks": [
    "s3://evidence/pbo-report.json",
    "s3://evidence/oos-backtest.csv"
  ],
  "ipAddress": "192.168.1.100",
  "userAgent": "PostmanRuntime/7.32.3",
  "publishedAt": "2026-08-07T10:00:00Z",
  "correlationId": "correlation-uuid"
}

POST /compliance/gdpr-request (Customer Data Deletion)

Request:

{
  "customerId": "customer-uuid",
  "requestDate": "2026-08-07",
  "reason": "Right to be forgotten (GDPR Article 17)"
}

Response (202 Accepted):

{
  "gdprTrackingId": "gdpr-uuid",
  "status": "IN_PROGRESS",
  "estimatedCompletion": "2026-08-08T12:00:00Z"
}

Governance Gates

Pre-Merge Gates

  • Event Schema: All model operations mapped to audit_events
  • Immutability: INSERT-only, no UPDATE/DELETE
  • GDPR Handling: Redaction logic for personal data
  • Retention Policy: 7-year retention for compliance
  • Audit Query API: Read-only endpoints for compliance officers

Post-Merge Validation (Deferred)

  • Integration tests (event logging on model operations)
  • GDPR purge tests (verify data redaction)
  • Audit report generation (7-year retention query)

🛡️ Security & Compliance

Immutability Guarantees:

  • INSERT-only table (no UPDATE, no DELETE)
  • Timestamp cannot be modified after insertion
  • Correlation_id immutable (traceability)

Regulatory Requirements:

  • FSS (금감원): Audit trail for 7 years (model_operations)
  • GDPR: Right-to-be-forgotten handling (redaction, not deletion)
  • PCI-DSS: IP address + user agent logged (for forensics)
  • Internal Compliance: Evidence linkage (PBO/DSR/OOS artifacts)

Access Control:

  • Compliance Officer: Read-only access to all events
  • Auditor: Query with date range filters
  • System: Automatic event logging (no manual entry)
  • Data Admin: GDPR purge operation (privileged, logged itself)

  • VS-00: PIT envelope (published_at, correlation_id, revision)
  • VS-02: Governance foundation (data sources, policies)
  • VS-26: Approval workflow (events logged by VS-27)
  • Compliance: GDPR, FSS, PCI-DSS requirements

Co-Authored-By: Claude Haiku 4.5 noreply@anthropic.com
Status: READY FOR IMPLEMENTATION
Next: Phase 2 implementation (after F PR merged)