nigig-org/crates/nigig-pay-storage
andodeki ecaac4bcb7
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
feat(pay): complete Phase 3, start Phase 4
Phase 3 (secure repository) is now complete.

3.3 retention and erasure — new retention.rs:
- Data minimisation and financial record keeping pull opposite ways, so the
  policy states both: evidence expires 90 days after settlement, settled
  records are held for a five-year floor, never-dispatched intents expire in
  30 days, and anything awaiting reconciliation is never swept. Deleting an
  unresolved payment would destroy the only record of money that may have
  left the account.
- erase_payment_on_request honours a user deletion request without
  destroying the accounting record: it normally erases the parsed copy of
  the user's inbox and retains the financial record, erases fully only past
  the floor, and refuses outright while in flight. Refusals carry a reason.

3.4 backup, restore and corruption reporting:
- integrity_check and foreign_key_check surface damage as StorageError
  ::Corrupt rather than letting a damaged ledger be trusted.
- backup_to uses SQLite's online backup API instead of copying the file, so
  a concurrent writer cannot produce a torn copy, and refuses to back up a
  database that fails its integrity check.
- restore_from validates the candidate in a separate connection before
  touching the live database, so a failed restore cannot destroy a working
  ledger. Tested with both a missing and a corrupt backup.

Storage tests 20 -> 36.

Phase 4 (blocking I/O) — 4.1 to 4.3 implemented:
- 4.1 expenses/mod.rs called reload(), a full parse of the store from disk,
  as the first statement of draw_walk; scrolling re-read the whole ledger
  every frame. Now loaded once, with invalidate()/reload_if_stale() on the
  event path.
- 4.2 the SMS scan was a wall-clock check inside draw_walk, so the branch ran
  every frame and the scan landed mid-paint. Now a cx.start_interval timer on
  the event path, with the interval named rather than inline.
- 4.3 update_summary walked the filtered list and rewrote labels every frame.
  Now invalidated only in refresh_filtered and applied in handle_event, fully
  out of the draw path rather than guarded inside it.
- 4.4 already satisfied by PaymentStorageWorker since tranche 1.

Supporting domain work: view_state.rs adds PeriodSummary and
TransactionsViewState so the summary arithmetic is testable outside a widget.
The tests immediately pin two things the inlined code got wrong: totals now
report overflow instead of wrapping, and a net outflow returns None rather
than a clamped zero. Money gains Default (zero).

Domain tests 66 -> 75.

Validated on rustc 1.97.1: domain and storage each pass test --locked, fmt,
clippy -D warnings and cargo-deny; storage also --features sqlcipher; domain
benches run; 7 M-Pesa store tests pass; 49 manifests parse.

NOT VERIFIED: the nigig-pay widget edits for 4.1-4.3 are not compiled here.
That crate needs the git-hosted Makepad fork. cargo check -p nigig-pay on a
full developer checkout is required before Phase 4 can be called complete.
2026-07-27 15:34:38 +00:00
..
src feat(pay): complete Phase 3, start Phase 4 2026-07-27 15:34:38 +00:00
Cargo.lock feat(pay): complete the partially-done review phases 2026-07-27 15:07:28 +00:00
Cargo.toml feat(pay): complete Phase 3, start Phase 4 2026-07-27 15:34:38 +00:00