Skip to content

Release v1.28.2 — finance money-integrity guards - #127

Open
domsteil wants to merge 5 commits into
masterfrom
fix/finance-money-guards
Open

Release v1.28.2 — finance money-integrity guards#127
domsteil wants to merge 5 commits into
masterfrom
fix/finance-money-guards

Conversation

@domsteil

Copy link
Copy Markdown
Contributor

Summary

  • General ledger: idempotent auto_post_*, period-open guards on post/void (incl. kernel ledger.post, rejecting commerce.ledger.period_not_open), income statement excludes closing entries, double-period-close guard
  • Accounts receivable: payment application bounded by the payment amount, terminal-invoice guards, validated write-off/credit-memo amounts
  • Accounts payable: three-way match aggregates billed quantity per PO line, status-guarded payment/bill transitions, list/count date-filter parity
  • Release: bump 1.28.1 → 1.28.2, CHANGELOG, README "What's New"

Testing

  • 29 new tests (gl/ar/ap_money_guards_test, kernel closed-period rejection, three-way match aggregation); ledger_simulation updated to model void-then-re-close
  • stateset-core 933 passed, stateset-db 896 passed, all embedded finance suites green; clippy -D warnings clean; release hygiene gate passed

🤖 Generated with Claude Code

https://claude.ai/code/session_01PCC33Xf4iAmBnkHFDDPBLu

domsteil and others added 2 commits August 31, 2026 15:13
General ledger (sqlite + postgres + kernel executor):
- auto_post_* is idempotent: a source document that already has a
  non-voided journal entry returns that entry instead of posting twice
- post/void of a journal entry requires its period to be open (the
  kernel ledger.post path rejects with commerce.ledger.period_not_open)
- income statement excludes closing entries, so a closed period's P&L
  no longer reads as zero
- run_period_close refuses while a posted closing entry stands for the
  period; re-closing a reopened period requires voiding it first

Accounts receivable (sqlite + postgres):
- apply_payment_to_invoices is bounded by the payment's own amount
  (existing applications counted), rejecting over-application
- payments/credit memos cannot be applied to voided/written-off invoices
- write-offs validated: positive and no more than the balance due;
  credit memos must be positive

Accounts payable (sqlite + postgres + core model):
- three-way match aggregates billed quantity per PO line, so duplicating
  a bill line can no longer slip over-billing past the match
- clear_payment, cancel_bill, dispute_bill, approve_bill are
  status-guarded transitions (0 rows -> Conflict, not silent success)
- count_payments applies the same date filters as list_payments

29 new tests (gl/ar/ap_money_guards_test, kernel closed-period
rejection, three-way match aggregation); ledger_simulation updated to
model void-then-re-close.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PCC33Xf4iAmBnkHFDDPBLu
Mechanical bump 1.28.1 -> 1.28.2 across all release surfaces
(scripts/release-bump.sh), CHANGELOG entry, and README "What's New"
section for the finance money-integrity guards.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PCC33Xf4iAmBnkHFDDPBLu
Comment thread crates/stateset-embedded/tests/gl_money_guards_test.rs Fixed
Comment thread crates/stateset-embedded/tests/gl_money_guards_test.rs Fixed
Comment thread crates/stateset-embedded/tests/gl_money_guards_test.rs Fixed
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PCC33Xf4iAmBnkHFDDPBLu
domsteil and others added 2 commits August 31, 2026 19:58
spentThisMonth is calendar-bucketed, so the test's daysAgo(1)/(2)
entries fall into the previous month on the 1st and 2nd of every month
and the assertion failed (coverage went red on Sep 1). getBudgetForecast
accepts an optional injectable `now` (defaulting to the current time,
fully backwards-compatible) and the test pins it mid-month.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PCC33Xf4iAmBnkHFDDPBLu
CodeQL (rust/cleartext-logging) traces account-derived data through the
error values into the panic messages. The assertions only need the
Result variant; the messages stay descriptive without the payload.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PCC33Xf4iAmBnkHFDDPBLu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants