ADR 0064 — SOC-2 Retention SLA, Auditor Role, and Attestation Cadence
Status: Accepted
Date: 2026-05-09 UTC
Deciders: operator (Kristerpher), software-architect
Refs: customer-audit-unified/design.md §10, ADR-0058, ADR-0060, docs/security/customer-audit-unified-threat-model.md §T-PRIV-2, docs/ops/runbooks/audit-soc2-attestation.md (to be created, SC-A16)
Context
The operator has confirmed SOC-2 compliance as in scope for v1 (Milestone #6). This affects three concrete design elements:
- Retention SLA: how long must audit records be kept, in what form, and with what retrieval guarantees?
- Auditor role: how do SOC-2 auditors access audit data without triggering customer notifications or requiring individual support tickets?
- Attestation cadence: what periodic control checks confirm that the audit system is functioning correctly?
SOC-2 Trust Service Criteria (TSC) relevant to this design: CC6.1 (logical access controls), CC7.2 (system monitoring), CC9.1 (business continuity), A1.2 (availability capacity), C1.1 (confidentiality).
The security agent also raised SEC Rule 17a-4 posture (T-PRIV-2): Raxx is not a broker-dealer, but if Raxx's audit records are considered order records or customer communications, WORM (write-once, non-erasable) storage may be required. This is routed to BLR for final determination; this ADR adopts the conservative 7-year retention posture and notes the WORM question as open.
Decision
1. Retention SLA
| Data class | Hot (Timescale / Postgres) | Warm (S3 Standard-IA) | Cold (S3 Glacier Instant Retrieval) | Deletion / pseudonymization |
|---|---|---|---|---|
| Trade-affecting audit events (financial record) | 30 days | 90 days | 7 years | Pseudonymize customer references on DSR; retain event structure for compliance |
| Non-financial audit events | 30 days | 90 days | 2 years | Pseudonymize on DSR within 30 days |
Shadow table rows (*_history) |
30 days | 90 days | 2 years | Pseudonymize row_data PII fields on DSR |
| Operator dim-3 events | 30 days | 90 days | 7 years (regulatory alignment) | Pseudonymize customer references; retain operator actor hash for accountability |
DSR erasure manifest (dsr_log) |
Active period | 90 days | 7 years | Not pseudonymized (it is the record of erasure) |
7-year cold storage is chosen to align with the SEC 17a-4(b)(4) posture (3–6 year range for broker-dealer records) plus a 1-year buffer, pending BLR confirmation. If BLR determines WORM storage is required, cold storage migrates to S3 Object Lock (Compliance mode) — an operational change to the archiver job, not a schema change.
Retrieval SLA from cold: S3 Glacier Instant Retrieval provides millisecond retrieval. This satisfies incident-response query needs. DSR response (portability export) from cold storage must complete within GDPR Art. 20 bounds (30 days).
2. Auditor Role — raptor-audit-compliance
The SOC-2 auditor role grants read-only access across all three dimensions for all customers, without triggering customer notifications.
Properties of raptor-audit-compliance:
- Read-only: SELECT only on customer_audit_events, *_history, audit_archival_runs, audit_integrity_log.
- No INSERT, UPDATE, DELETE.
- No customer notification: auditor reads are logged in customer_audit_events with dimension = 'operator_interaction' and actor_type = 'system_actor' (auditor is treated as an internal process, not an individual operator), but the notification pipeline checks actor_type and skips notification for system_actor audit reads.
- All auditor sessions are logged via pg_audit at the Postgres level (independent of application layer).
- raptor-audit-compliance is implemented in RBAC V2. It is stubbed in this design; the RBAC V2 architect produces the concrete data model and group composition.
Access provisioning for SOC-2 audit engagements:
- Auditor identity is provisioned as a time-bounded raptor-audit-compliance group membership (start date, end date).
- Provisioning requires superadmin action in the RBAC V2 console.
- The provisioning action itself is logged as operator.rbac.grant in customer_audit_events.
- At the end of the engagement, membership is revoked and the revocation is logged as operator.rbac.revoke.
3. Attestation Cadence
A quarterly attestation confirms that the audit system's controls are operating effectively. The runbook (docs/ops/runbooks/audit-soc2-attestation.md, SC-A16) covers:
| Check | Frequency | Owner | Pass criterion |
|---|---|---|---|
| HMAC chain integrity — full chain from genesis | Monthly (1st of month, 01:00 UTC, automated) | audit_integrity_check.py |
Zero HMAC verification failures |
| HMAC chain integrity — last 24h | Nightly (automated) | audit_integrity_check.py |
Zero failures |
| pg_audit log delivery | Weekly (automated) | Log drain health check | Zero delivery gaps > 5 min |
| Retention archival run completion | Monthly (automated) | audit_archiver.py manifest |
All expected date ranges present in audit_archival_runs |
raptor-audit-compliance membership review |
Quarterly (manual) | Operator | No stale or unrevoked auditor memberships |
| Deprovision runbook drill | Quarterly (manual) | Operator | Heroku Postgres rotation completes within 4-hour window |
| Cold storage retrieval test | Quarterly (manual) | Operator | Test query returns expected rows from S3 Glacier within SLA |
| DSR erasure verification | Per DSR (automated check) | dsr_verification.py |
No plaintext PII found in history rows for erased customer |
The quarterly attestation report is produced by the operator using the runbook. The report is an evidence artifact for SOC-2 Type II audit periods.
Consequences
Positive
- The 7-year retention posture is conservative relative to SEC 17a-4. If BLR confirms Raxx is subject to 17a-4, the design is already compliant (pending WORM determination). If BLR confirms Raxx is not subject to 17a-4, the conservative posture is still legally defensible.
- The
raptor-audit-compliancerole allows auditor access without per-customer notification noise. Auditor reads are logged at the pg_audit level; the application layer does not treat them as individual operator interactions. - Quarterly attestation cadence produces evidence artifacts. SOC-2 Type II audit periods (typically 6–12 months) will have at least 2–4 attestation reports as evidence.
- The monthly full-chain HMAC verification (from genesis) satisfies CC7.2 (system monitoring) requirements.
Negative
- The
raptor-audit-compliancerole depends on RBAC V2. If SOC-2 certification is scheduled before RBAC V2 ships, the operator must useraptor-audit-admin(which triggers customer notifications) instead — an interim workaround with customer-notification side effects. - 7-year cold storage at scale: at 10K customers, 7 years of trade-affecting events is a significant S3 storage cost. Estimate: ~10 GB/year/1K customers (compressed) = ~70 GB for 1K customers × 7 years = ~700 GB cold storage. At S3 Glacier Instant Retrieval pricing (~$0.004/GB/month) = ~$2.80/month. Negligible at v1. Revisit at 10K customers.
- The WORM question is open (BLR). If WORM is required, the archiver job must be updated before Phase 4 (legacy drop). The design accommodates this without schema changes — only the S3 write call changes (add
ObjectLockMode=COMPLIANCE).
Open Questions (deferred to BLR)
-
SEC 17a-4 applicability: Is Raxx subject to Rule 17a-4(b)(4) record-keeping requirements? If yes, does the 7-year cold storage satisfy the requirement, or does WORM (Object Lock Compliance) apply?
-
GDPR pseudonymization scope: After pseudonymizing
customer_idandactor_id, does the remaining behavioral data in trade-affecting audit events still constitute personal data under GDPR Art. 4(1)? This determines whether the 7-year retention creates a GDPR conflict. -
GDPR controller vs. processor: For the first customer (individual retail trader), Raxx is the controller. Confirm before Milestone #6 onboard.
Alternatives Considered
2-year retention for all audit data
Simpler. Lower storage cost. No BLR ambiguity.
Rejected: SEC 17a-4 posture (pending BLR) may require 6 years for trade records. A 2-year default would require a migration to extend retention after BLR confirms the requirement — a more disruptive change than starting at 7 years.
Compliance auditor uses a read-only database credential (no RBAC role)
Simpler for provisioning. Auditor receives a read-only Postgres credential.
Rejected: a direct DB credential bypasses application-layer RBAC and the pg_audit log tagging that identifies auditor sessions. It also creates a credential management burden (rotation, revocation). RBAC role + time-bounded membership is the correct access model.
Annual attestation (instead of quarterly)
Lower operational overhead.
Rejected: SOC-2 Type II reporting periods are typically 6–12 months. Annual attestation produces only 1 evidence artifact per year, which may be insufficient for a 12-month audit period with continuous monitoring criteria. Quarterly provides 4 artifacts per year with evidence coverage distributed across the audit window.