feat(evidence): one function decides whether an entry needs evidence (P4)
Accounting reason: the receipt rule (Pub. 583, Rev. Proc. 98-25: the books must be demonstrably supported by the records) was decided in three places that could disagree: the server's post, the digest, and a string match on a journal-event origin in the viewer. ledger_core:: evidence::requirement is now the one decision: Required (with why) or Exempt (with the source). A reversal needs no receipt of its own (its evidence is its original's, D-47, D-12); neither do a closing entry, a schedule month's or a depreciation run's posting, a disposal, a document's entry, a payroll run or its remittance. The ledger learned the two origins it could not see (a disposal, a remittance) from the events that already name their entry, live and on replay. A split group counts for a draft only: a posted entry's decision was made when it posted. The policy moved with it (evidence::Policy; ReceiptPolicy in ledger-config keeps the words and delegates). Store::post_entry_checked refuses a covered draft with no receipt (StoreError::ReceiptRequired, which the MCP maps to the unchanged receipt_required error); Store::post_entry stays the primitive that commands and fixtures post through, since ~176 call sites post hand entries with no receipt. The viewer's missing_receipt calls requirement; its string match is gone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
This commit is contained in:
1 parent
28d46332e4
commit
7299cf90f2
6 files changed
+451
-132
No files matched your search
@@ -35,6 +35,24 @@ pub enum StoreError {
|
||||
#[error("asset {0} already has depreciation posted; correct it with entries instead")]
|
||||
AssetDepreciationPosted(u64),
|
||||
|
||||
/// The receipt policy covers the entry and it has no receipt (plan P4,
|
||||
/// I-5; rules.md B-43): refused before anything is journaled.
|
||||
#[error(
|
||||
"entry {entry_id} needs a receipt before it posts: {reason} ({policy}); attach one with books.attach_receipt"
|
||||
)]
|
||||
ReceiptRequired {
|
||||
/// The entry that needs the receipt.
|
||||
entry_id: u64,
|
||||
/// Its total debits, `None` when they pass exact arithmetic.
|
||||
debits: Option<rust_decimal::Decimal>,
|
||||
/// The policy that triggered, in words.
|
||||
policy: String,
|
||||
/// Why this entry is covered.
|
||||
reason: String,
|
||||
/// The posted entries it appears to split (anti-splitting).
|
||||
split_group: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Filesystem error.
|
||||
#[error("io error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
Reference in new issue
Block a user