aeat.application.user_profile._integrity module¶
Cross-store integrity validation for a logical profile.
A logical profile fragments across a bucket directory, a plaintext
manifest, and an encrypted secure-object row. Each store independently
records the profile UUID; a torn write, a hand-edited manifest, or a
half-rolled-back create can leave them disagreeing. Serving such a
profile silently is the missing_profile_record / ghost-profile
defect class.
verify_profile_integrity() is the read-time gate
ProfileRepository.load runs on every load. It checks that the
manifest bucket_id, the on-disk directory name, and the
UserProfileRecord.profile_id all agree on the profile UUID.
Decryption and pydantic validation of the record happen earlier in
load itself — by the time this gate runs the record is already a
validated object, so this function is a pure cross-store identity
comparison. It raises ProfileIntegrityError on any
disagreement — the repository never returns an inconsistent aggregate.
- exception ProfileIntegrityError(message=None, *, context=None, suggestion=None, translated_message=None)[source]¶
Bases:
ProfileNotFoundErrorRaised when a profile’s physical stores disagree on its identity.
Inherits from
ProfileNotFoundErrorso existing handlers that catch the broader profile-resolution family also catch cross-store drift; an inconsistent profile is, for every consumer purpose, not a usable profile.- Parameters:
- Return type:
None
- code: ClassVar[ErrorCode]¶
- verify_profile_integrity(*, profile_id, directory_name, manifest_bucket_id, record_profile_id, manifest_status, record_status, manifest_label, record_display_name)[source]¶
Assert every physical store agrees on the profile UUID and status.
The three cross-store identity claims are:
directory_name— the<root>/buckets/<name>/directory the bucket lives in.manifest_bucket_id— thebucket_idkey in the plaintextmanifest.toml.record_profile_id— theprofile_idon the decryptedUserProfileRecord.
All three must equal
profile_id.The lifecycle status is denormalised: the encrypted
UserProfileRecordcarries the authoritative status and the plaintext manifest mirrors it so the manifest scan can exclude a tombstoned profile without decryption.manifest_statusandrecord_statusare the two copies of that mirror, compared by their string value. A disagreement is the drift state that re-opens the tombstone leak — a manifest sayingactiveover a tombstoned record would letlist/switchserve a deleted profile — so it must be surfaced, never served.The display label is denormalised the same way:
renamewrites the encrypted recorddisplay_nameand the plaintext manifestlabelas two copies of one value. A crash between those two writes leaves them divergent, and without this gateloadwould silently serve the stale manifest label over the renamed record forever, with no signal forrepair.manifest_labelandrecord_display_nameare compared by their string value and a disagreement is surfaced, never served.A mismatch raises
ProfileIntegrityErrorwith sanitized context naming the disagreeing stores so arepairsurface can act on a concrete delta without echoing raw profile identifiers.- Parameters:
profile_id (
str) – The canonical UUID the caller expects all stores to agree on.directory_name (
str) – The<root>/buckets/<name>/directory name.manifest_bucket_id (
str) – Thebucket_idkey from the plaintext manifest.record_profile_id (
str) – Theprofile_idfrom the decrypted record.manifest_status (
str) – The lifecycle status mirrored in the manifest.record_status (
str) – The authoritative lifecycle status from the record.manifest_label (
str) – The display label mirrored in the manifest.record_display_name (
str) – The authoritative display label from the record.
- Raises:
ProfileIntegrityError – If any store disagrees on the UUID, the manifest and record disagree on the lifecycle status, or they disagree on the display label.
- Return type: