Resolve entry identity via entry-id metadata; unfuse user references (libra-#42)

Approving a pending entry created with a reference (e.g. invoice
"42-144") 404'd with "Pending entry unknown not found": the list
endpoints recovered the entry id by parsing links for a libra- prefix,
but reference-bearing entries displace that link with the fused
"{reference}-{entry_id}" form, so the id surfaced as the literal
"unknown" and the approve call round-tripped it.

Make the entry-id transaction metadata the single canonical identity:

- _extract_entry_id() resolves metadata-first (libra- link parsing kept
  only for pre-dfdcc44 ledger history); used by /entries/user,
  /entries/pending, approve, and reject.
- Creation endpoints no longer fuse the reference with the entry id —
  the user reference becomes its own sanitized link and round-trips
  verbatim in API responses. Typed exp-/rcv-/inc- links stay as the
  settlement-tracking handles.
- format_revenue_entry now writes entry-id metadata like its siblings
  and sanitizes its reference link (was appended raw); generic
  POST /entries sanitizes its reference link too.
- User-journal reference extraction skips all system link prefixes
  (typed links used to leak into the reference field).

Contract documented in CLAUDE.md (Data Integrity → Entry Identity &
Links), pinned by tests/test_entry_identity_api.py and formatter
contract tests in test_unit.py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-06-12 20:39:06 +02:00
commit 15d9910073
6 changed files with 374 additions and 89 deletions

View file

@ -945,7 +945,8 @@ def format_revenue_entry(
entry_date: date,
fiat_currency: Optional[str] = None,
fiat_amount: Optional[Decimal] = None,
reference: Optional[str] = None
reference: Optional[str] = None,
entry_id: Optional[str] = None
) -> Dict[str, Any]:
"""
Format a revenue entry (libra receives payment directly).
@ -962,7 +963,8 @@ def format_revenue_entry(
entry_date: Date of payment
fiat_currency: Optional fiat currency
fiat_amount: Optional fiat amount (unsigned)
reference: Optional reference
reference: Optional reference (invoice ID, etc.) stored as its own link
entry_id: Optional unique entry ID (generated if not provided)
Returns:
Fava API entry dict
@ -978,6 +980,9 @@ def format_revenue_entry(
fiat_amount=Decimal("50.00")
)
"""
if not entry_id:
entry_id = generate_entry_id()
amount_sats_abs = abs(amount_sats)
fiat_amount_abs = abs(fiat_amount) if fiat_amount else None
@ -1002,12 +1007,13 @@ def format_revenue_entry(
# Note: created-via is redundant with #revenue-entry tag
entry_meta = {
"source": "libra-api"
"source": "libra-api",
"entry-id": entry_id
}
links = []
if reference:
links.append(reference)
links.append(sanitize_link(reference))
return format_transaction(
date_val=entry_date,