aeat.application.ledger._id_resolution module

Transaction-id prefix resolution and display-id width computation.

Provides the cross-cutting helpers required by the ledger CLI surface to deliver the dual full_id / display_id identity contract and the stable operator lineage handle across edits:

  • compute_display_id_width() returns the minimum prefix width that keeps every transaction id in the supplied set uniquely addressable, with a floor of MINIMUM_DISPLAY_ID_WIDTH. The width grows automatically as the bucket fills; it is never hard-coded to 8.

  • resolve_transaction_id() accepts a user-supplied prefix and returns the matching canonical 64-character hash, raising aeat.domain.transactions.TransactionIdPrefixError on zero-match or ambiguous-prefix conditions.

  • resolve_lineage_transaction_id() extends that resolver with a read-side lineage lookup: when a prefix names no live row but it (or an unambiguous prefix of it) names a superseded id in some live row’s edit-lineage chain, the resolver returns that current row’s id, so an old handle written down before an edit keeps answering.

The matching rule: a prefix matches a full id when the full id starts with the prefix (lowercase, hex). A prefix that equals a full id resolves trivially. Empty input and non-hex characters are refused.

Lineage resolution is a read-side lookup convenience over the authoritative content-addressed id, not a change to how ids are minted. The content hash (see aeat.domain.transactions.derive_transaction_id()) remains the single authority for storage, audit, and machine consumers; this module never freezes an id across an edit. It only lets a historical handle resolve to the row that now carries the edited content.

compute_display_id_width(transaction_ids)[source]

Return the minimum unique-prefix width over transaction_ids.

Parameters:

transaction_ids (Iterable[str]) – Full 64-character hex transaction ids drawn from the active bucket.

Return type:

int

Returns:

The smallest width w such that every id’s first w characters uniquely identify it within the supplied set, capped below by MINIMUM_DISPLAY_ID_WIDTH and above by _FULL_ID_LENGTH.

resolve_transaction_id(prefix, transaction_ids)[source]

Resolve prefix to a single full transaction id.

Parameters:
  • prefix (str) – A user-supplied prefix or full id. Lowercase hex.

  • transaction_ids (Iterable[str]) – The full ids known to the active bucket.

Return type:

str

Returns:

The unique full transaction id matching prefix.

Raises:

TransactionIdPrefixError – When prefix is empty, contains non-hex characters, matches no transaction, or matches more than one transaction. The error message lists all collision candidates so the operator can disambiguate by lengthening their prefix.

resolve_lineage_transaction_id(prefix, catalogue)[source]

Resolve prefix to a live row, following edit lineage when needed.

The resolution order is:

  1. Try resolve_transaction_id() against the live catalogue ids. A current id, a split parent left in the catalogue, an archived merged child, or an unambiguous prefix of any of them resolves here unchanged. This preserves the existing resolver’s behaviour exactly for every handle that names a row still in the catalogue.

  2. When step 1 finds no live row, treat prefix as a historical handle and walk every live row’s edit-lineage chain. An update that edits an id-affecting fact re-derives the content-addressed id and removes the old id from the catalogue, recording it as a previous_transaction_id on the heir’s aeat.domain.transactions.TransactionEditLineageEntry chain. If prefix (or an unambiguous prefix of it) names a superseded id in exactly one live row’s lineage, that row’s current id is returned.

This is a read-side lookup convenience over the authoritative content-addressed id: the id is never frozen across an edit, and the content hash stays the single storage/audit authority. The lineage chain is the same substrate the finalized-modelo guard already walks, so no new storage is introduced.

Parameters:
Return type:

str

Returns:

The unique full transaction id of the live row that prefix addresses — directly, or through its edit lineage.

Raises:

TransactionIdPrefixError – When prefix is empty, non-hex, too long, names no live row and no lineage handle, or matches more than one live row or lineage row ambiguously.