cadrumo.application.user_profile.bundle_export_operation module¶
Durable, non-secret operation state for profile-bundle publication.
The single export_profile_bundle()
authority records the progress of one publication as a credential-free journal
file so a crash in any publication window recovers honestly. Journal files live
under <storage-root>/profile-export-operations, deliberately OUTSIDE both
the target artifact and any bucket directory: the target file is the sensitive
cleartext bundle, so the operation state that describes it carries no bundle
bytes, no passphrase, and no raw tax id – only the resolved target identity,
purpose, transport, schema version, derived data categories, and the payload
digest.
A PREPARED journal records that a bundle was serialized to a staged
temporary file but not yet atomically published; a COMPLETED journal records
that the atomic replace and parent-directory fsync durably landed the target,
with the completion event still owed until the journal is cleared.
Reconciliation completes a durably-published operation – a COMPLETED one, or
a PREPARED one whose destination content matches the recorded digest (the
replace landed but the COMPLETED transition did not) – by emitting the owed
event, and clears a PREPARED operation that never published as an orphan.
This is a distinct surface from the sealed recovery archive, which owns its own confidentiality and restoration semantics and is not folded in here.
- profile_export_staged_path(destination, *, process_id, nonce)[source]¶
Derive the one staged sibling path an export operation may own.
- is_canonical_profile_export_staged_path(destination, staged_path)[source]¶
Return whether staged_path is this destination’s generated staging sibling.
- class ProfileBundleExportOperationStatus(*values)[source]¶
Bases:
StrEnumLifecycle state of one durable profile-export publication.
- PREPARED¶
- COMPLETED¶
- class ProfileBundleExportOperation(**data)[source]¶
Bases:
BaseModelCredential-free durable record of one publication’s progress.
content_sha256is the digest of the exact staged payload bytes. Because publication moves those bytes into place withos.replace()rather than re-serializing, the published target’s digest equals this value, so a reconciliation can tell aPREPAREDoperation whose replace already landed (published, digest matches) from a genuine orphan (digest absent or divergent) without a separate durable marker.event_occurred_atis the fixed timestamp the completion event is derived from, so a live publish and a later reconciliation emit the byte-identical (idempotent) event.- Parameters:
data (Any)
- model_config: ClassVar[ConfigDict]¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- operation_id: Hex64Str¶
- status: ProfileBundleExportOperationStatus¶
- profile_id: ProfileId¶
- display_name: str¶
- target_identity: str¶
- destination: str¶
- staged_path: str¶
- content_sha256: ContentDigest¶
- purpose: ProfileBundleExportPurpose¶
- transport: ProfileBundleExportTransport¶
- bundle_schema_version: int¶
- data_categories: tuple[str, ...]¶
- excluded_data_categories: tuple[str, ...]¶
- started_at: datetime¶
- updated_at: datetime¶
- event_occurred_at: datetime¶
- derive_export_operation_id(*, profile_id, target_identity, purpose)[source]¶
Derive one clock-free operation identifier for a target publication.
The identifier folds the profile, the resolved target identity, and the purpose so a retried export to the same file for the same purpose reconciles to the same journal rather than accreting orphan records. The timestamp is a non-identity progress field and is deliberately excluded.
- Return type:
- Parameters:
profile_id (str)
target_identity (str)
purpose (ProfileBundleExportPurpose)
- class UnreadableExportJournal(**data)[source]¶
Bases:
BaseModelOne journal file the repository could not turn into an operation.
Carries the file’s own identifier and the refusing error’s class name rather than its message: the id is what an operator needs to find the file, and the class name is a stable machine-readable reason that carries no journal contents.
- Parameters:
data (Any)
- model_config: ClassVar[ConfigDict]¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- journal_id: str¶
- reason: str¶
- class ProfileBundleExportJournalScan(**data)[source]¶
Bases:
BaseModelEvery journal the repository could read, and every one it could not.
- Parameters:
data (Any)
- model_config: ClassVar[ConfigDict]¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- operations: tuple[ProfileBundleExportOperation, ...]¶
- unreadable: tuple[UnreadableExportJournal, ...]¶
- exception ProfileBundleExportJournalError(message=None, *, context=None, translated_message=None)[source]¶
Bases:
CadrumoErrorBase failure for profile-export journal persistence and validation.
- Parameters:
- Return type:
None
- code¶
- exception ProfileBundleExportJournalNotFoundError(message=None, *, context=None, translated_message=None)[source]¶
Bases:
ProfileBundleExportJournalErrorRaised when a requested export journal does not exist.
- Parameters:
- Return type:
None
- code¶
- exception ProfileBundleExportJournalCorruptError(message=None, *, context=None, translated_message=None)[source]¶
Bases:
ProfileBundleExportJournalErrorRaised for unreadable, malformed, schema-invalid, or mismatched journals.
- Parameters:
- Return type:
None
- code¶
- class ProfileBundleExportJournalRepository(*, settings=None, storage_root=None)[source]¶
Bases:
JournalRepositoryBase[ProfileBundleExportOperation]Persist credential-free export journals as atomic individual files.
The repository provides no publication orchestration and no cryptographic authenticity guarantee; it is the durable state store the publication service and its reconciliation read and write. The atomic read/write substrate is inherited from
JournalRepositoryBase; this class adds journal deletion, an isolating scan, and prepared-state selection.- Parameters:
settings (Settings | None)
storage_root (Path | None)
- scan()[source]¶
Load every readable journal, reporting the unreadable ones separately.
The isolating counterpart to
JournalRepositoryBase.list(). A journal that is corrupt, schema-invalid, identity-mismatched, or unreadable does not abort the walk and does not disappear either: it is reported inunreadableso the caller can surface it rather than silently skipping a record that may still describe cleartext bytes on disk.- Return type: