Lgpd erasure coverage
LGPD Erasure — Conformance & Coverage Registry
Tracks which Koder components implement the cross-service erasure cascade contract per policies/identity-data-retention.kmd § R5 and specs/identity/erasure-flow.kmd.
When a user issues DELETE /v1/me on the Koder ID side, the request enters a 24-hour grace window then publishes identity.user.erased on the cross-service event bus. Every Koder component that stores data linked to a Koder ID subject *UST*subscribe to that event (or be explicitly opted out per the Skip table below) and apply the LGPD cascade — purge linked data, drop sessions, anonymize audit events for the 6-month forensics window.
This registry agglomerates the per-component conformance state. Pre-release release engineering MUST verify the row for the releasing component is at PASS (or PASS¹ — see the status enum) before tagging.
Status enum
| Status | Meaning | Effect on AI / release engineering |
|---|---|---|
| *ASS* | Listener wired into the longkoder:events:flow |
Release engineering green |
| *ASS¹* | Same as PASS *odulo a single deferred sub |
Release engineering green |
| *ARTIAL* | Some cascade elements live, others pending. Notes column enumerates what is and isn't. | Release engineering blocks; sub-ticket required to close. |
| *ODO* | Component stores Koder |
Release engineering blocks; cascade ticket required before next major. |
| */A* | Component does not store Koder |
Release engineering green-lights with no cascade requirement. |
| *KIP* | Component is itself the identity provider (Koder ID) or otherwise outside the consumer surface — cascade contract does not apply. | Release engineering green-lights. |
Cascade surface
For each Koder component the registry tracks:
- *istener*— the long-running goroutine that subscribes to
the erasure stream
- *tore*— production binding to the component's data layer
(the adapter that actually deletes / anonymizes)
- *udit*— completion-event emission (
<service>.erasure.completed)on the canonical
koder:events:<service>stream - *ntegration*— end
toend test against a real fixture - *egression*— structural test locking the contract surface
- *iring*— listener actually booted from the entrypoint
A row is *ASS*when all six columns are green for the component's storage surface.
Components
| # | Date | Component | Status | listener | store | audit | integration | regression | wiring | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2026 |
services/foundation/id/engine/services/auth |
*ASS* | ✓ | ✓ | N/A | ✓ | ✓ | ✓ | Inservices/auth/internal/listener/erasure_listener.go consuming the same event bus directly inside idengine. No audit emission needed — idengine is the source |
| 2 | 2026 |
services/foundation/id/engine/services/sso |
*ASS* | ✓ | ✓ | N/A | ✓ | ✓ | ✓ | Sibling of #1; same architecture. |
| 3 | 2026 |
products/dev/flow/engine/services/erasure (Koder Flow) |
*ASS* | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | *romoted PASS¹ → PASS on 2026FLOW-135 shipped — endtests/integration/erasure_cascade_test.go (2 tests, both green in 5.5s against the standard XORM SQLite fixture). Full FLOWservices/erasure/listener.go (FLOW + usermodel.GetUserByID + userservice.DeleteUser(ctx, u, true), compile-time var _ FlowUserStore assertion). **audit** [serviceserasureaudit_publisher.go`](........productsdevflowengineserviceserasureauditpublisher.go) (FLOW-132 — emits flow.erasure.completed on koder:events:flow with `sourceeventid / flowuserid / flowusername / elapsedms data fields, best-effort semantics, 7 unit tests including 2 negative-firing assertions for no-link and already-purged paths). **integration** [testsintegrationerasurecascadetest.go`](........productsdevflowenginetestsintegrationerasurecascadetest.go) (FLOWTestErasureCascade_RealForgejoData drives full cascade against fixture user 2 + linked Koder ID subject, asserts user row purged + externalloginuser gone + audit envelope shape; TestErasureCascade_NoLinkedUser_AckedNoOp asserts norouters/init.go erasure.Boot(ctx) sibling of backup_scheduler.Boot(ctx) (FLOWapp.ini [flow_erasure] config plumbing (FLOWsetting.FlowErasure with KODER_FLOW_ERASURE_ENABLED + KODER_REDIS_URL + KODER_FLOW_ERASURE_CONSUMER_ID overrides). *I*.koder-flow/workflows/erasure-cascade.yml (FLOWcontrib/legal/privacy.html.sample §"Data Retention and Deletion of Data" rewritten 2026[KDS owner-curated content]). Authkoder-id-auth-coverage.md Flow row 2026flow.koder.dev until operator sets KODER_REDIS_URL (default |
Skipped components (explicit outofscope decisions)
Components reviewed and declared outside the LGPD cascade surface with rationale. A Skip is reversible — when concrete demand surfaces, open a new cascade ticket on the component and remove the row.
| # | Component | Decision | Rationale |
|---|---|---|---|
| S1 | services/foundation/id (itself) |
*KIP*(2026 |
Koder ID is the cascade source, not a consumer. The DELETE /v1/me endpoint + the cascade orchestrator + the 24hservices/auth and services/sso (#1, #2 above) are separate Sectors counted independently. |
Adding a new component
- The component stores data linked to a Koder ID subject (via
external_login_useror equivalent). If not, the row is N/A with one-line rationale. - Open a phase-1 ticket on the component for the listener +
production store + unit tests (model: FLOW-117).
- Open phase
2 subtickets following the FLOW-119 split(FLOW-130..139): eventbus dep decision, production_store, audit_publisher, startup wiring, config knobs, integration test, contract-drift regression, CI workflow, privacy template (if applicable), and this registry row.
- Reference the Flow row (#3) as a worked
example.
Cross-references
- Policy:
policies/identity-data-retention.kmd § R5 - Spec:
specs/identity/erasure-flow.kmd § R4 - Spec:
specs/messaging/cross-service-events.kmd(envelope contract, stream naming, consumer-group semantics) - Sibling registry:
koder-id-auth-coverage.md(OAuth client surface conformance — every cascade consumer is also an OAuth client and should be green in both registries)