feat(audit): the statements checks, the bar and the audit settings (P8)
An audit is the books read as an auditor reads them, through a day. The pure checks over a ledger are one function per finding code in ledger_core::audit: the trial balance balances, assets equal liabilities plus equity, the P&L articulates to equity (net income since the first entry is current earnings plus what the closes moved), the cash flow foots, the control accounts tie to their documents, a members close stays within a minor unit of each member's exact share, schedules and depreciation are posted, the register holds the cost accounts' cost, every posted entry meets evidence::requirement (a reversal resting on its original's receipt is listed as a note, not a failure), no draft is open, every revenue and expense account has a tax category, and the 1099 and settings problems the caller reads are findings. A check that cannot be made is itself a finding. Findings come in one fixed order, so the same books give the same list. The caller hands in what a ledger cannot know: the receipts filed, the cash flow's footing, the settings problems. The attestation bar (D-9) is a value, not a table: reasoning effort high, two verifier agents and an adversarial check, with counts() deciding whether a claim meets it. Every claim needs the effort; one on a year-level audit needs the whole bar; a reading that disagrees with the books never counts. policy.attestation_bar (a new Kind::AttestationBar, one canonical text) and policy.cpa_package_requires_audit are the two settings; both wait for the journal feature audits. 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
d9d63b16dc
commit
843bcc421f
4 files changed
+1350
No files matched your search
@@ -146,6 +146,9 @@ pub enum Kind {
|
||||
Terms,
|
||||
/// Payment methods (A-3): a list of `{kind, label, lines, link?, qr?}`.
|
||||
PaymentMethods,
|
||||
/// What counts as an attestation ([`crate::audit::AttestationBar`]),
|
||||
/// in its one canonical spelling.
|
||||
AttestationBar,
|
||||
}
|
||||
|
||||
/// One setting the books know.
|
||||
@@ -170,6 +173,7 @@ const PARTY_POLICY: &[(&str, &[&str])] =
|
||||
const APPROVAL_MODE: &[(&str, &[&str])] = &[("off", &[]), ("enforce", &[])];
|
||||
const TAX_CATEGORY_POLICY: &[(&str, &[&str])] =
|
||||
&[("warn", &[]), ("refuse", &["required", "require"])];
|
||||
const AUDIT_REQUIRED: &[(&str, &[&str])] = &[("refuse", &["required", "require"]), ("warn", &[])];
|
||||
const SCHEDULE_CONVENTION: &[(&str, &[&str])] = &[("daily", &[]), ("monthly_even", &[])];
|
||||
|
||||
/// A return's key as a setting keeps it.
|
||||
@@ -401,6 +405,21 @@ pub static KEYS: &[Key] = &[
|
||||
sensitivity: Sensitivity::Public,
|
||||
doc: "off: approval_rule conventions are recorded but never block a post. enforce: an entry a rule covers posts only once its approver approves it (books.approve_entry). Unset: off.",
|
||||
},
|
||||
// P8: audits and attestations.
|
||||
Key {
|
||||
name: "policy.attestation_bar",
|
||||
toml: ("books", "attestation_bar"),
|
||||
kind: Kind::AttestationBar,
|
||||
sensitivity: Sensitivity::Public,
|
||||
doc: "What counts as an attestation (plan D-9): the least reasoning effort a checker reports (low, medium, high, xhigh, max), and for a year-level audit the fewest independent verifier agents and whether the check was adversarial, written like effort=high verifiers=2 adversarial=true (a word left out keeps its default). The client reports how it checked; the books record that claim and say whether it meets this bar when asked, so a change here changes what counts, earlier attestations too. Unset: effort=high verifiers=2 adversarial=true.",
|
||||
},
|
||||
Key {
|
||||
name: "policy.cpa_package_requires_audit",
|
||||
toml: ("books", "cpa_package_requires_audit"),
|
||||
kind: Kind::Choice(AUDIT_REQUIRED),
|
||||
sensitivity: Sensitivity::Public,
|
||||
doc: "Whether books.export_cpa_package waits for an audit: refuse (the package is refused unless an audit for the handoff or a full audit at the current books has its period attested; a reason given for the export overrides it and is recorded as a decision) or warn (the package is made and says so). Unset: refuse.",
|
||||
},
|
||||
Key {
|
||||
name: "backup.git_remote",
|
||||
toml: ("backup", "git_remote"),
|
||||
@@ -1103,6 +1122,11 @@ pub fn check(key: &Key, v: &Value) -> Result<Value, String> {
|
||||
Ok(json!(terms.describe()))
|
||||
}
|
||||
Kind::PaymentMethods => payment_methods(name, want_list(name, v)?),
|
||||
Kind::AttestationBar => {
|
||||
let bar = crate::audit::AttestationBar::parse(want_str(name, v)?)
|
||||
.map_err(|e| format!("{name}: {e}"))?;
|
||||
Ok(json!(bar.describe()))
|
||||
}
|
||||
Kind::TimeZone => {
|
||||
let s = want_str(name, v)?.trim();
|
||||
let zone = jiff::tz::TimeZone::get(s).map_err(|_| {
|
||||
@@ -1230,6 +1254,9 @@ pub fn shape(key: &Key, v: &Value) -> Result<(), String> {
|
||||
.ok_or_else(|| format!("{name} {s:?} is not a decimal"))
|
||||
}
|
||||
Kind::Count => count_of(name, v).map(|_| ()),
|
||||
Kind::AttestationBar => crate::audit::AttestationBar::parse(want_str(name, v)?)
|
||||
.map(|_| ())
|
||||
.map_err(|e| format!("{name}: {e}")),
|
||||
Kind::PaymentMethods => {
|
||||
for (i, m) in want_list(name, v)?.iter().enumerate() {
|
||||
let n = format!("{name} method {}", i + 1);
|
||||
@@ -1605,6 +1632,18 @@ impl Settings {
|
||||
}
|
||||
}
|
||||
|
||||
/// `policy.attestation_bar` (unset: the default bar, D-9).
|
||||
pub fn attestation_bar(&self) -> crate::audit::AttestationBar {
|
||||
self.str("policy.attestation_bar")
|
||||
.and_then(|s| crate::audit::AttestationBar::parse(s).ok())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// `policy.cpa_package_requires_audit` (unset: refuse).
|
||||
pub fn cpa_package_requires_audit(&self) -> bool {
|
||||
self.str("policy.cpa_package_requires_audit") != Some("warn")
|
||||
}
|
||||
|
||||
/// `backup.git_remote`, if set.
|
||||
pub fn backup_git_remote(&self) -> Option<&str> {
|
||||
self.str("backup.git_remote")
|
||||
|
||||
Reference in new issue
Block a user