Skip to content

feat(compliance): retention + GDPR erasure/residency + SOC 2 posture (Step 6.10) - #162

Merged
officialCodeWork merged 1 commit into
mainfrom
build/phase-6/step-6.10-compliance-posture
Jun 8, 2026
Merged

feat(compliance): retention + GDPR erasure/residency + SOC 2 posture (Step 6.10)#162
officialCodeWork merged 1 commit into
mainfrom
build/phase-6/step-6.10-compliance-posture

Conversation

@officialCodeWork

Copy link
Copy Markdown
Owner

Summary

Step 6.10 — Compliance posture (the Phase-6 capstone): SOC 2 Type II control mapping, GDPR data-residency config, and data-retention policies. New rag-compliance package.

The platform already ships the controls an auditor maps to (audit / ACL / PII / BYOK / SSO / quotas / breakers / guard); 6.10 adds the three missing pieces:

  • Data retention + GDPR erasureRetentionEnforcer (rag-compliance) drives tenant-scoped purge_*: purge applies per-class retention windows, erase_tenant is the right-to-erasure primitive. Retention is a capability on the existing stores, not a new SPI — non-abstract purge_before / purge_tenant (default no-op) on FeedbackStore + ProvenanceStore, with dry_run in the SPI so a preview counts without deleting uniformly (ProvenanceStore has no list). The audit hash chain is never purged in place (it would break tamper-evidence) — audit retention is the 6.6b WORM export; audit_days is advisory.
  • Right-to-erasure endpointPOST /v1/compliance/erase erases the calling tenant's data (scope from the principal, never the body); dry-run by default, real delete needs dry_run=false and confirm=true.
  • Data residency — per-tenant data_region (resolved onto TenantSettings via the 6.1 resolver) enforced at ingest against cfg.compliance.regionResidencyViolationError (403) + compliance.residency_violation. Opt-in; a single-deployment assertion, not multi-region routing.
  • SOC 2 / GDPR mapping backed by a live postureGET /v1/status/compliance serves a CompliancePosture (controls + region + retention) computed from the build flags; the mapping docs map each Trust Service Criterion / GDPR article to a control, and the posture reports whether it's on in this deployment — so the mapping is checkable, not just prose.

New core types DataClass / RetentionPolicy / ErasureResult / CompliancePosture + ComplianceError / ResidencyViolationError; cfg.compliance + tenants[].data_region / retention_days; PII-free compliance.* events; ragctl compliance report / demo. Phase 6 closes (74/84).

Deferred: subject-level (vs tenant-level) chunk/document erasure (needs an index delete-by-document path), an admin retention-sweep endpoint (today the sweep is ragctl/cron; erasure is the API), multi-region routing, automated audit-evidence bundles.

Documentation

Test plan

  • Unit: RetentionEnforcer purge / erase / dry-run / no-window / no-stores; compliance_posture; residency_ok
  • Contract: purge_before / purge_tenant (age, tenant-scope, dry-run, isolation) on Feedback + Provenance
  • Gateway: /v1/status/compliance posture; /v1/compliance/erase (dry-run default, two-flag delete, 401); residency-violation ingest 403; residency off-by-default
  • ragctl compliance report / demo
  • ruff, mypy --strict (325 files), RAG001, full pytest (excl integration), schema/openapi/config-drift, policy-coverage, log-schema/event-registry/PII

🤖 Generated with Claude Code

…(Step 6.10)

Phase-6 capstone — adds the three compliance pieces on top of the controls
the platform already ships (audit / ACL / PII / BYOK / SSO / quotas).

- New rag-compliance package (deps rag-core + rag-observability only):
  RetentionEnforcer drives tenant-scoped purge_* (purge = per-class
  retention windows; erase_tenant = GDPR right-to-erasure); compliance_posture
  + residency_ok are pure.
- Retention is a *capability on the existing stores*, not a new SPI:
  non-abstract purge_before / purge_tenant (default no-op) on FeedbackStore +
  ProvenanceStore, with dry_run in the SPI so a preview counts-without-deleting
  uniformly (ProvenanceStore has no list). The audit hash chain is never
  purged in place (it would break tamper-evidence) — audit retention is the
  6.6b WORM export; audit_days is advisory.
- POST /v1/compliance/erase erases the calling tenant's data (scope from the
  principal, never the body); dry-run by default, real delete needs
  dry_run=false AND confirm=true.
- Per-tenant data_region (resolved onto TenantSettings via the 6.1 resolver)
  enforced at ingest against cfg.compliance.region → ResidencyViolationError
  (403) + compliance.residency_violation. Opt-in, single-deployment assertion.
- GET /v1/status/compliance serves a CompliancePosture (controls + region +
  retention) computed from the build_app flags — the live backing for the
  SOC 2 / GDPR control-mapping docs (each criterion → a control → whether it's
  on in this deployment, so the mapping is checkable).

New core types DataClass / RetentionPolicy / ErasureResult / CompliancePosture
+ ComplianceError (400) / ResidencyViolationError (403); cfg.compliance +
tenants[].data_region / retention_days; PII-free compliance.* events; ragctl
compliance report / demo. dist schemas/openapi/rag.schema regenerated.

~30 tests; all gates green: ruff, mypy --strict (325 files), RAG001, full
pytest (excl integration), schema/openapi/config-drift, policy-coverage,
log-schema/event-registry/PII.

Docs: docs/compliance/{soc2-control-mapping,gdpr-mapping}.md,
docs/reference/compliance.md, docs/architecture/compliance.md,
docs/adr/ADR-0042-compliance-posture.md, docs/README.md. TRACKER: 6.10 done,
Phase 6 complete (74/84).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@officialCodeWork
officialCodeWork merged commit 41ca59d into main Jun 8, 2026
12 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant