aeat.application.user_profile._bundle module

Portable profile-bundle serialisation for bucket export/import.

This module composes UserProfilePortableExport payloads at the application boundary. A v3 bundle contains the profile record plus the four bucket-local history categories that must move with it: work units, ledger transactions, calculation revisions, and filing records. The v3 shape additionally carries the generic secure-object custody schema and coverage manifest, default-empty until the transport-aware phases populate them. The ledger category is loaded as a TransactionCatalogue through TransactionCatalogueRepository.

Bundles carry typed domain-model payloads, not encrypted blobs, key material, or raw secure-storage rows. Export reads domain records from their owning repositories; import saves those records through the target bucket’s repository save paths so the target bucket re-encrypts them under its own data-encryption key.

The bundle version gate is a ceiling with a durability floor: a version above BUNDLE_SCHEMA_VERSION was written by a newer application and is refused; a version at or above BUNDLE_DURABILITY_FLOOR is readable exactly when the per-hop chain in BUNDLE_PAYLOAD_UPGRADERS reaches the current version. The floor starts at the current version (no released bundles exist below it) and moves forward only through a superseding accepted ADR (2026-07-08-released-data-durability-adr). Callers must provision and collision-check the target bucket and hold the appropriate bucket session before deserialising; this module performs schema-version validation and typed repository writes.

BUNDLE_SCHEMA_VERSION: Final[int]

Current bundle write version. Every export stamps this.

BUNDLE_DURABILITY_FLOOR: Final[int]

Oldest bundle version the import path keeps readable. Starts at the current version (no released bundles exist below it); moves forward only through a superseding accepted ADR.

BUNDLE_PAYLOAD_UPGRADERS: Mapping[int, Callable[[dict[str, object]], dict[str, object]]]

each transforms the parsed JSON mapping of a version-N bundle into the version-N+1 shape (including restamping bundle_schema_version) BEFORE strict pydantic validation — the raw mapping is the one sanctioned pre-validation boundary. Empty while the floor equals the current version; a version bump MUST land its hop here in the same change or the lineage gate fails.

Type:

One-hop raw-payload upgraders keyed by from_version

SUPPORTED_BUNDLE_SCHEMA_VERSIONS: frozenset[int]

the complete floor-to-current range.

Type:

Versions the import path accepts

validate_bundle_payload(raw_json, *, expected_written_version=None)[source]

Parse, chain-upgrade, and strictly validate a serialized bundle payload.

Reads the payload’s own bundle_schema_version, refuses a future version (above BUNDLE_SCHEMA_VERSION) or one below BUNDLE_DURABILITY_FLOOR, chain-upgrades an older supported payload hop by hop through BUNDLE_PAYLOAD_UPGRADERS, and validates the result against the current strict UserProfilePortableExport model.

Parameters:
  • raw_json (bytes | str) – The serialized bundle payload (decrypted transport bytes or the plaintext export text).

  • expected_written_version (int | None) – When set, the version a transport envelope declared for this payload; a payload whose own stamped version differs is refused before any upgrade runs.

Raises:

UnsupportedBundleSchemaVersionError – When the payload does not carry an integer bundle_schema_version, the version is outside the floor-to-current range, an upgrade hop is unregistered, or the stamped version contradicts expected_written_version.

Return type:

UserProfilePortableExport

serialize_profile_bundle(*, bucket_id, custody_profile=StorageCustodyProfile.STRUCTURED)[source]

Build a v3 UserProfilePortableExport.

Reads the profile record and all four financial-history categories from bucket_id’s encrypted repositories and assembles them into one portable payload. The caller is responsible for ensuring a live bucket session is active for bucket_id.

Parameters:
Return type:

UserProfilePortableExport

The bundle carries only decrypted pydantic domain-model payloads (no encrypted envelopes or key material). The recipient re-encrypts each object under its own bucket data-encryption key through the standard repository save paths on import.

deserialize_profile_bundle(bundle, *, target_bucket_id)[source]

Import financial-history objects from bundle into target_bucket_id.

Validates bundle.bundle_schema_version against SUPPORTED_BUNDLE_SCHEMA_VERSIONS before any writes; only the current v3 shape is accepted.

Saves work units, ledger transactions, calculation revisions, and filing records into the target bucket via the standard repository save paths. Each domain object is re-encrypted under the target bucket’s own data-encryption key. No dict[str, Any] intermediate is used; pydantic models flow directly into typed catalogue saves.

The caller is responsible for:

  • Provisioning the target bucket before calling this function.

  • Ensuring a live bucket session is active for target_bucket_id.

  • Running the two-tier collision guard before provisioning.

Parameters:
  • bundle (UserProfilePortableExport) – The validated export bundle.

  • target_bucket_id (str) – The bucket id under which to write the objects.

Raises:

UnsupportedBundleSchemaVersionError – When bundle.bundle_schema_version is not in SUPPORTED_BUNDLE_SCHEMA_VERSIONS.

Return type:

None

exception UnsupportedBundleSchemaVersionError(message=None, *, context=None, suggestion=None, translated_message=None)[source]

Bases: AeatError

Raised when a bundle carries an unsupported bundle_schema_version.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • suggestion (str | None)

  • translated_message (str | None)

Return type:

None

code: ClassVar[ErrorCode]