cadrumo.application.operations.financial_operand_custody module

Non-sensitive custody checkpoints for one transient financial operand.

Custody of an operand moves through a fixed order: a wait is opened, an amount is bound to it, delivery to the executor starts, the executor acknowledges, and custody is released. Every step is journalled, and what is journalled is only ever the shape of the wait - which requirement, which state, when - never the amount. The operand contracts keep the value out of every record; this module keeps it out of the durable record too.

The order matters because the interesting failures live between the steps. A process that dies after delivery started but before acknowledgement cannot know whether the executor saw the amount, so restart must classify that as uncertain rather than guess. A wait that lapses must settle as expired even though no one was watching. And release must happen exactly once however many supervisor paths race for it, because a second release would clear a buffer another path believes it still owns.

See also

OperationTransientFinancialOperandRequirement

The durable, amount-free identity every checkpoint is written against.

class OperationFinancialOperandCustodyState(*values)[source]

Bases: StrEnum

The fixed custody order one operand wait advances through.

AWAITING_SUBMISSION
BOUND
DELIVERY_STARTED
DELIVERY_ACKNOWLEDGED
RELEASED
EXPIRED
CANCELLED
class OperationFinancialOperandCrashClassification(*values)[source]

Bases: StrEnum

What a restart may conclude about a wait interrupted mid-flight.

NOT_DELIVERED
DELIVERY_UNCERTAIN
DELIVERED
exception OperationFinancialOperandCustodyError(message=None, *, context=None, translated_message=None)[source]

Bases: CadrumoError

Raised when a custody advance would break the fixed transition order.

Parameters:
  • message (str | None)

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

  • translated_message (str | None)

Return type:

None

code
class OperationFinancialOperandCustodyCheckpoint(**data)[source]

Bases: BaseModel

One journalled custody position, carrying no operand material.

The checkpoint names the wait and its state. It deliberately has no field for an amount, a digest, or any other derivative, so a journal replay can reconstruct what happened without reconstructing what was supplied.

Parameters:

data (Any)

operand_kind: OperationFinancialOperandKind
interaction_id: Annotated[str, Field(min_length=1, max_length=128)]
sequence: Annotated[int, Field(ge=1)]
state: OperationFinancialOperandCustodyState
recorded_at: datetime
refusal_reason: OperationFinancialOperandRefusalReason | None
crash_classification: OperationFinancialOperandCrashClassification | None
property is_terminal: bool

Report whether this checkpoint settles the wait for good.

open_custody(requirement, *, now)[source]

Journal the opening of one bounded wait, before any amount exists.

Return type:

OperationFinancialOperandCustodyCheckpoint

Parameters:
advance_custody(current, target, *, now, refusal_reason=None)[source]

Advance one wait along the fixed order, refusing every other move.

A terminal checkpoint refuses every advance, which is what makes release exactly-once: the second racing path to arrive finds a released checkpoint and is refused rather than clearing a buffer twice.

Return type:

OperationFinancialOperandCustodyCheckpoint

Parameters:
classify_interrupted_custody(checkpoint)[source]

Say what a restart may conclude about a wait that was cut off.

None means the wait was already settled and needs no conclusion. A wait cut off between delivery starting and its acknowledgement is reported as uncertain, never as delivered or as not delivered, because the record genuinely does not say.

Return type:

OperationFinancialOperandCrashClassification | None

Parameters:

checkpoint (OperationFinancialOperandCustodyCheckpoint)

reconcile_on_restart(checkpoint, *, now)[source]

Settle one interrupted wait so no custody position survives a restart.

An unsettled wait cannot be resumed: the amount lived only in the memory of a process that is gone, so custody has in fact ended either way. What reconciliation must not do is decide what it cannot know. A wait cut off between delivery starting and its acknowledgement settles as released because the buffer is gone, and carries DELIVERY_UNCERTAIN forever after. Recording it as acknowledged would manufacture evidence that the executor saw the amount; recording it as not delivered would manufacture the opposite.

This is deliberately not an advance_custody() call. The fixed order governs a live wait; a restart settles a wait whose owner no longer exists, and forcing it through the live transitions is what would tempt a caller to invent the missing acknowledgement.

Return type:

OperationFinancialOperandCustodyCheckpoint

Parameters: