store: specs for the write path, open, verify, heal, receipts, viewer
check / check (push) Canceled after 0s

GOAL/SOURCE/INVARIANTS/SCENARIOS blocks, citing R-11, R-12, R-13a,
docs/receipt-store.md, IRS Pub. 583, and Rev. Proc. 98-25: the module
spec every command method follows (refuse whole, journal first, gapless
chained lines, replay equals live, multi-step commands rehearsed whole,
nothing deleted), Store::create, open, verify, verify_and_heal,
attach_receipt, link_receipt, unlink_receipt, withdraw_attachment, and
Snapshot::refresh. Also moves ensure_control_account's doc comment back
onto it (it had been stacked on rehearse).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-13 19:08:33 -06:00
1 parent 2cbb6a263f
commit 8a49f0ff0e
2 files changed
+164 -4

No files matched your search

+18
View File
@@ -95,6 +95,24 @@ impl Snapshot {
/// Apply whatever the writer appended since the last read. Returns the
/// number of new journal lines (0 when nothing changed).
///
/// ```text
/// GOAL: a viewer that follows the live books without ever writing.
/// SOURCE: docs/receipt-store.md (the journal is the source of truth;
/// lines are appended whole and chained); R-11.
/// INVARIANTS:
/// 1. NEVER write to the data directory.
/// 2. MUST apply only complete lines (ending in a newline) that chain
/// onto the last one read; a line still being appended waits for
/// the next refresh.
/// 3. After a refresh, the ledger MUST equal a replay of the lines
/// read so far.
/// SCENARIOS:
/// 1. IF nothing was appended: SHOULD return 0 and change nothing.
/// 2. IF the file shrank or no longer chains (a restore, a repaired
/// tail): SHOULD reload from scratch.
/// 3. IF a complete new line fails its hash or parse: SHOULD refuse.
/// ```
pub fn refresh(&mut self) -> Result<usize, StoreError> {
let len = std::fs::metadata(self.data_dir.join(JOURNAL_FILE))?.len();
if len < self.offset {