store: refusals leave the live books untouched; per-filing names; spec suite
The refusal property gained the converse law (an accepted command journals something; only batch runs may find nothing to do) and checks the store's class and payroll listings. It found a schedule registered with an out-of-range total whose first month was refused after its entry was begun: the live ledger kept a draft the journal never had. - Core: compound commands (post_schedule_month, reverse_entry, close_period_to, create_invoice, create_bill, receive_payment, pay_bill, run_payroll, remit_payroll_taxes) run inside Ledger::atomically, so a refusal partway leaves the ledger exactly as it was. - Core: a schedule total no line could carry, or finer than a cent, and an asset cost beyond the line range, are refused at registration. Replay keeps older schedules (replay_register_schedule). - Store: add_line, add_line_fx, mark_cleared, set_fx_rate, post_schedule_month and close_period_to changed the live ledger before journaling; they now run on a copy, journal what it produced, then swap it in, so a failed write leaves the live books as journaled. New spec-blind suite tests/spec_store.rs (57 tests written from the store's specs alone). Its two findings, adjudicated: - A file filed twice under different names listed the first name and type for both (the projection kept them per blob). Schema v8 gives each attachment its own; older databases backfill and heal by verify. - Withdrawn attachments stay in the store's listing, marked (the MCP listing hides them): the spec and doc said "omit" and are corrected. Also removes journal::truncate_to_last_good_seq: unused, and it dropped everything after the first bad complete line, which the books now treat as corruption for a person, never repaired automatically. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GWVo7x3UHw5kwCUaWxiejX
This commit is contained in:
1 parent
27da4b63bf
commit
111a5af470
11 files changed
+2075
-75
No files matched your search
@@ -5,7 +5,7 @@
|
||||
//! is the current version.
|
||||
|
||||
/// Current schema version.
|
||||
pub const SCHEMA_VERSION: u32 = 7;
|
||||
pub const SCHEMA_VERSION: u32 = 8;
|
||||
|
||||
/// Migrations, in order. `MIGRATIONS[i]` migrates from version `i` to `i+1`.
|
||||
pub const MIGRATIONS: &[&str] = &[
|
||||
@@ -195,5 +195,17 @@ CREATE TABLE IF NOT EXISTS entry_vendors(
|
||||
entry_id INTEGER PRIMARY KEY,
|
||||
vendor_id INTEGER NOT NULL
|
||||
);
|
||||
"#,
|
||||
r#"
|
||||
-- v8: each filing keeps its own file name and type. Before, they came from
|
||||
-- the blob, so filing the same bytes again under another name listed the
|
||||
-- first name (found by the spec-blind store suite, 2026-10-13). Existing
|
||||
-- rows take the blob's; a database whose filings differed then fails
|
||||
-- verify's table check and is rebuilt from the journal.
|
||||
ALTER TABLE attachments ADD COLUMN file_name TEXT;
|
||||
ALTER TABLE attachments ADD COLUMN mime_type TEXT;
|
||||
UPDATE attachments SET
|
||||
file_name = (SELECT original_name FROM blobs WHERE sha256 = attachments.blob_sha),
|
||||
mime_type = (SELECT mime_type FROM blobs WHERE sha256 = attachments.blob_sha);
|
||||
"#,
|
||||
];
|
||||
Reference in new issue
Block a user