cadrumo.application.user_profile.custody_transactions module

Application-owned current-format profile custody transactions.

This module is deliberately independent of the retired profile repository. It owns only local current-format capsule transactions: bounded canonical journals, root-before-profile locking, pointer compare-and-swap, local deletion preflight and receipts. It never contacts a remote system and it never reads a retired custody layout.

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

Bases: CadrumoError

Base error for local current-format custody transactions.

Parameters:
  • message (str | None)

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

  • translated_message (str | None)

Return type:

None

code
exception ProfileCustodyTransactionConflictError(message=None, *, context=None, translated_message=None)[source]

Bases: ProfileCustodyTransactionError

Raised when a captured local witness no longer matches live state.

Parameters:
Return type:

None

code
exception ProfileCustodyDuplicateLabelError(message=None, *, context=None, translated_message=None)[source]

Bases: ProfileCustodyTransactionConflictError

Raised when the requested label already names a committed capsule.

A SUBCLASS of the conflict error because every existing handler that treats a custody conflict as a conflict should keep catching this one. It carries its own error code for one reason: retryability. Its parent means “a captured witness went stale”, which a re-read genuinely fixes, so that code is published as retryable. A label collision is permanent – the name is bound to a committed capsule and the identical command can never succeed – and a non-interactive caller may retry what it is told is retryable.

Parameters:
Return type:

None

code
exception ProfileCustodyTransactionRefusalError(message=None, *, context=None, translated_message=None)[source]

Bases: ProfileCustodyTransactionError

Raised when local deletion is not explicitly authorized by its evidence.

Parameters:
Return type:

None

code
exception ProfileCustodyTransactionCorruptError(message=None, *, context=None, translated_message=None)[source]

Bases: ProfileCustodyTransactionError

Raised for a malformed, oversized, noncanonical, or swapped journal.

Parameters:
Return type:

None

code
class ProfileCustodyTransactionOperation(*values)[source]

Bases: StrEnum

Operation recorded by a local custody transaction journal.

CREATE
DELETE
class ProfileCustodyTransactionState(*values)[source]

Bases: StrEnum

Durable lifecycle state recorded by a local custody transaction journal.

PREPARED
STAGE_VERIFIED
CAPSULE_PUBLISHED
POINTER_PUBLISHED
DELETE_PREPARED
DELETE_MARKED
PROCESS_SECRETS_REVOKED
SESSION_ACCELERATION_DELETED
POINTER_CLEARED
CAPSULE_RENAMED
LOCAL_REMOVED
COMPLETE
ROLLED_BACK
canonical_model_bytes(model, *, maximum_bytes, subject)[source]
Return type:

bytes

Parameters:
  • model (BaseModel)

  • maximum_bytes (int)

  • subject (str)

canonical_payload_digest(payload, *, maximum_bytes, subject)[source]

Digest an already-JSON-shaped payload under the one canonical encoding.

Return type:

str

Parameters:
read_profile_custody_record(path, *, maximum_bytes, subject)[source]
Return type:

bytes

Parameters:
class ProfileCustodyDigestModel(**data)[source]

Bases: BaseModel

Shared digest and JSON behaviour for the profile custody records below.

Named for its layer: the persistence custody package declares a different class for its own records, and the two cannot be merged because application code must not depend on an adapter. Sharing one name across that boundary made a reader guess which contract they were reading.

Parameters:

data (Any)

property computed_self_digest: str

Compute the digest of this record without its stored self-digest field.

canonical_json_bytes()[source]

Serialize this record using its bounded canonical JSON representation.

Return type:

bytes

class ProfileCustodyInventoryWitness(**data)[source]

Bases: BaseModel

Non-secret exact-inventory witness bound into a destructive journal.

All three fields describe the SAME set of capsule members: the ones the inventory’s digest covers. Counting or measuring the wider observed set instead would make the witness self-inconsistent, and the local delete compares whole witnesses for equality between preflight and execution – so a file the digest deliberately ignores would still refuse the deletion through the count, which is the defect the narrowed digest exists to fix.

Parameters:

data (Any)

digest: PrefixedContentDigest
file_count: int
total_bytes: int
classmethod from_inventory(inventory)[source]

Bind the inventory digest and exact member totals into a witness.

Return type:

ProfileCustodyInventoryWitness

Parameters:

inventory (ProfileCustodyInventoryPort)

class ProfileCustodyDeleteConfirmation(**data)[source]

Bases: BaseModel

A confirmation whose exact target is bound to one prepared journal.

Parameters:

data (Any)

transaction_id: UUID
profile_id: UUID
inventory_digest: PrefixedContentDigest
challenge: Hex64Str
class ProfileCustodyTransactionJournal(**data)[source]

Bases: ProfileCustodyDigestModel

One bounded canonical, credential-free local custody transaction record.

schema_version: Literal[2]
transaction_id: UUID
operation: ProfileCustodyTransactionOperation
profile_id: UUID
state: ProfileCustodyTransactionState
started_at: datetime
updated_at: datetime
pointer_before: BucketPointer
expected_custody_digest: PrefixedContentDigest | None
proposed_custody_digest: PrefixedContentDigest | None
proposed_generation: int | None
label: str | None
label_revision: int | None
label_content_digest: PrefixedContentDigest | None
label_self_digest: PrefixedContentDigest | None
staged_relative_path: str | None
inventory: ProfileCustodyInventoryWitness | None
hold_assessment: ProfileCustodyHoldAssessment | None
retention_override: ProfileCustodyRetentionOverride | None

The operator authorisation, if any, to proceed past the FILING half of hold_assessment. Digest-bound like every other field here, so the authorisation cannot be edited into a journal after the fact, and the recorded reason survives with the transaction that acted on it.

requires_inactive_target: bool

True only for a single-target delete whose authority requires the target to remain inactive across preparation, confirmation, crash recovery, and every destructive owner effect.

confirmation_challenge: Hex64Str | None
tombstone_relative_path: str | None
self_digest: PrefixedContentDigest
property canonical_payload: dict[str, object]

Return the journal payload excluding the self-digest field.

classmethod create(**values)[source]

Construct a journal with a canonical self-digest.

Return type:

ProfileCustodyTransactionJournal

Parameters:

values (Any)

with_update(**changes)[source]

Return a new journal with changes and a recomputed self-digest.

Return type:

ProfileCustodyTransactionJournal

Parameters:

changes (object)

class ProfileCustodyTransactionReceipt(**data)[source]

Bases: ProfileCustodyDigestModel

One idempotent durable receipt for the application local-delete owner.

schema_version: Literal[1]
owner: Literal['application-local-custody']
transaction_id: UUID
profile_id: UUID
operation: ProfileCustodyTransactionOperation
completed_at: datetime
inventory: ProfileCustodyInventoryWitness
pointer_cleared: bool
pointer_published: bool
retained_external_state: tuple[str, ...]
self_digest: PrefixedContentDigest
classmethod create(**values)[source]

Construct a receipt with a canonical self-digest.

Return type:

ProfileCustodyTransactionReceipt

Parameters:

values (Any)

class CustodyReceiptOwner(*values)[source]

Bases: StrEnum

Which custody effect a local receipt attests.

The two are not alternatives on one axis: a revocation destroys a process secret and an acceleration caches a local session. A receipt attributed to the wrong one would claim a secret was revoked when it was not.

PROCESS_SECRET_REVOCATION

The process secret was revoked.

LOCAL_SESSION_ACCELERATION

A local session was accelerated.

CustodyReceiptOwnerValue

The same owner for a strict receipt field or a boundary parameter.

alias of Literal[PROCESS_SECRET_REVOCATION, LOCAL_SESSION_ACCELERATION]

class ProfileCustodyOwnerReceipt(**data)[source]

Bases: ProfileCustodyDigestModel

One durable idempotence receipt for an ordered local deletion owner.

schema_version: Literal[1]
transaction_id: UUID
profile_id: UUID
owner: CustodyReceiptOwnerValue
effect: Literal['revoked', 'removed', 'verified_absent']
completed_at: datetime
self_digest: PrefixedContentDigest
classmethod create(**values)[source]
Return type:

ProfileCustodyOwnerReceipt

Parameters:

values (Any)