package pgstore import ( "regexp" "testing" ) // ledger_appendonly_test.go: the strongest money invariant this package states, held by something // other than a sentence (register row PD-397). // // `Adjust` promises "a ledger row is never edited: the correction is another row, which is what // makes the sum reproducible", and `appendLedger` promises "the two are never written apart, because // a cache that can lag its source is a second answer about money". Both were true, and both were // held ONLY by nobody having written the statement that breaks them. // // ⚠ WHAT THIS DOES NOT DO, and the register asked for a decision rather than a reflex: it does not // add a trigger on `credit_ledger`. A trigger was measured against this tree and refused on two // grounds, both concrete. It fires on CASCADE too, and deleting a user cascading away that user's // ledger is the boundary of "append-only" that the migration itself declares — so the trigger would // forbid the one edit the schema means to allow. And it would break // `TestAReleaseWhoseKeyWasSpentIsRefusedRatherThanSilent`, whose whole fixture is deliberate surgery // on the ledger to reach a state "no code path produces" (runs_test.go): a legitimate test, and one // that must not be sacrificed to a guard against a risk that is not the code's. // // So the invariant is what its own doc comment says it is — the discipline of the CODE — and this is // that discipline made checkable. What stays unheld is named rather than implied: a data migration, // an operator's psql and a future tool all go around this package by construction, and no rule here // reaches them. // // Mutation caught: any `update credit_ledger` or `delete from credit_ledger` added to this package, // including inside a statement assembled from fragments — which is why it walks the SQL gate's // extractor rather than grepping the files. func TestTheLedgerIsAppendOnlyInTheCodeThatWritesIt(t *testing.T) { stmts := collectSQL(t) // The same floor the gate next door keeps, and for the same reason: an extractor that stopped // seeing this package would turn this into a green light over nothing. if len(stmts) < 140 { t.Fatalf("the extractor found %d statements: it has stopped seeing this package, and a gate that checks nothing passes", len(stmts)) } // ⚠ SCHEMA-QUALIFIED TOO. `update public.credit_ledger` is the same statement to Postgres and // walked straight through the first version of this pattern, which matched the bare name only — // a gate with a hole exactly the width of a schema prefix. const table = `(?:[a-z_]+\.)?credit_ledger` edits := regexp.MustCompile(`(?is)(update\s+` + table + `|delete\s+from\s+` + table + `)`) for _, st := range stmts { if m := edits.FindString(st.sql); m != "" { t.Errorf("%s: this package edits the ledger (%q). A ledger row is never edited — the "+ "correction is another row — and that is what makes the sum of the ledger the "+ "reproducible answer about an account's money. The schema does NOT enforce this "+ "(PD-397); nothing but this rule does.\n%s", st.where, m, indent(st.sql)) } } t.Logf("%d statements checked; none edits the ledger", len(stmts)) }