One pass over the LOW-tier review items plus two folded issues:
- Delete validate_journal_entry (dead since the Fava migration; it
validated the pre-string-amount model) with its exports, unused
crud imports, and tests. Beancount validates entries now.
- Migration m006: UNIQUE index on user_roles(user_id, role_id) after
deduping; assign_user_role inserts with ON CONFLICT DO NOTHING and
returns the existing assignment — closes the auto-assign
check-then-act race on concurrent logins.
- Extract _get_username_from_user_id (110 lines in views_api, fresh
LNbits Database per call inside per-row hot paths) into
user_lookup.py with one shared core-DB handle, a 60s TTL cache and
a batch get_usernames API (review #18).
- Receivable-entry responses report CLEARED, matching the flag the
formatter actually writes; PENDING misled the UI (libra-#35).
- Replace the remaining print() calls in tasks.py with logger.
- get_all_accounts derives valid roots from
account_utils.ACCOUNT_TYPE_ROOTS instead of a hardcoded tuple, and
the no-op per-test rate-limit reset is gone (libra-#54).
- Delete migrations_old.py.bak, MIGRATION_SQUASH_SUMMARY.md,
docs/PHASE*_COMPLETE.md and the rendered .html; .gitignore data/
(it holds the runtime .lnbits_auth_key secret).
- Track docs/CODE-REVIEW-2026-06.md with finding statuses updated for
the PR #55-#59 + chore/hygiene series.
- CLAUDE.md notes LNbits pins Pydantic v1: keep .dict(), don't
"modernize" to .model_dump().
Note: format_payment_entry's is_payable docstring (flagged in review
follow-up) turned out to be consistent with the body — no change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
The previous journal_entries/entry_lines local mirror was removed during
the Fava migration but the docs still described it as a local cache.
Replace with explicit statement that Fava is canonical and the remaining
SQLite tables hold orthogonal operational state.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Simplifies the representation of journal entry lines by replacing separate debit and credit fields with a single 'amount' field.
Positive amounts represent debits, while negative amounts represent credits, aligning with Beancount's approach. This change improves code readability and simplifies calculations for balancing entries.
Creates a markdown file to provide guidance to Claude Code (claude.ai/code) when interacting with the Castle Accounting codebase.
This document outlines project overview, architecture, key files, database schema, transaction flows, API endpoints, development notes, and other crucial information. It aims to improve Claude's ability to understand and assist with code-related tasks.