symfonic.services.shadow.privacy¶
privacy ¶
SEC-PRIV-5 tenant erasure contract and legacy deletion wiring.
The process-global participant registry remains for the live legacy fallback.
Native hosts explicitly register their recording store with the injected
SubjectDataStoreRegistry via shadow.native_privacy. Neither path implicitly
imports participants from the other. Native registration is synthetic-only
until its synchronous writer can commit through the native erasure fence.
Legacy production attestation still requires a seeded erase round trip and an
absence check.
DeletionWiringAttestation
dataclass
¶
DeletionWiringAttestation(participant_id: str, registry_id: str, verified_at: datetime, probe_tenant: str, seeded: int, residual: int)
Evidence that erasure actually reaches this participant.
ErasureParticipantRegistry ¶
The set of stores the tenant-erasure path must sweep.
Source code in src/symfonic/services/shadow/privacy.py
erase_all
async
¶
Sweep every participant. Returns participant_id -> rows removed.
sweep
async
¶
Erase from every participant, surviving one that fails.
A participant is somebody else's store — a remote backend having a bad minute must not abort the tenant's erasure, skip every participant sorted after it, and lose the completion trail. Each failure is logged and reported by id instead.
Source code in src/symfonic/services/shadow/privacy.py
ErasureSweep
dataclass
¶
The outcome of one sweep: what was erased, and what refused to be.
A sweep is deliberately not all-or-nothing. Erasure is the one operation where a partial success must still be reported rather than rolled back — the rows that went are gone — so a participant that raises is recorded by id and the sweep continues to the rest.
TenantErasureParticipant ¶
verify_deletion_wiring
async
¶
verify_deletion_wiring(participant: TenantErasureParticipant, *, registry: ErasureParticipantRegistry = PRIVACY_DELETION_PARTICIPANTS, probe_tenant: str = 'deletion-wiring-probe', seed: int = 1) -> DeletionWiringAttestation
Run a real erase round-trip and attest to the result.
Raises when the participant is not registered — an attestation for a store the deletion path cannot reach would be worse than none at all.