symfonic.services.privacy.errors¶
errors ¶
The privacy taxonomy. Typed, coded, and never matched on message text.
ERR-2 forbids keying control flow on prose, and the shipped platform is a live
example of why: three routers branch on str(exc).startswith("Budget
exceeded:"). Every class here carries a stable code so a transport maps
the class, and an operator greps the code, without either of them reading the
sentence a translator may one day rewrite.
ErasureFenceDenied ¶
ErasureFenceDenied(message: str, *, reason: str, scope_key: str, expected_generation: int | None = None, observed_generation: int | None = None)
Bases: PrivacyError
A conditional write was refused by the fence (EFX-ER-4).
Carries reason — generation_mismatch or subject_tombstoned —
because the two are operationally different: the first says "somebody else
moved", the second says "this subject is gone and retrying is
resurrection".
Source code in src/symfonic/services/privacy/errors.py
ErasureSagaError ¶
FenceAuditBindingError ¶
Bases: PrivacyError
Something tried to take over a fence's denial recorder (HOST-3).
Two hosts in one process — a test suite, a sidecar, an adopter mounting two agents — can share a fence. A silent rebind sends the first host's EFX-ER-4 denials to the second host's sink, which is worse than either host having no audit: the events exist, in the wrong place, and nobody is looking for them there. Rebinding is therefore an explicit act, not a constructor side effect.
ParticipantRegistrationError ¶
Bases: PrivacyError
A store is missing from, or duplicated in, the coverage registry.
PRIV-1 makes coverage checkable by making it declared. A silent overwrite would drop a store out of the erasure path with no diagnostic at all.
PrivacyError ¶
ReadSuppressedError ¶
Bases: PrivacyError
An erasure is in flight and at least one store is unconfirmed.
Distinct from :class:SubjectErasedError on purpose: this one is a
transient fail-closed state an operator can act on by driving the saga to
completion, and it maps to a different status than "this subject is gone".
Source code in src/symfonic/services/privacy/errors.py
SubjectErasedError ¶
Bases: PrivacyError
The subject carries a tombstone: no admission, no read, no write.
Terminal by design. There is no "the erasure finished so it is safe again" branch, because that branch is exactly how a restored backup serves data the subject asked to have destroyed (PRIV-7).