Auditor independence — one firm, one client, ONE role
In 2000, Arthur Andersen billed Enron $25 million for the audit — and $27 million for consulting. The firm certifying the books had a bigger business interest in pleasing management than in challenging it. When Enron collapsed, Andersen's partners were found shredding audit workpapers; the firm itself dissolved, taking 85,000 jobs with it. Sarbanes-Oxley §201 answered by making the dual role itself illegal: a registered public accounting firm may not provide most consulting services to an audit client. Not "disclose it" — may not hold both. Here the prohibition is arithmetic. A firm/client pair can hold at most ONE engagement. Signing the audit writes 1; selling consulting to the same client tries to write 2 — and the engagement ledger refuses. The conflict isn't reviewed by an ethics board after the fact; it is a value the books cannot hold. The audit itself runs a machine where `opinion_issued` is terminal: once signed, an opinion cannot be quietly recalled and re-negotiated.
A Soma program from the governance part of the verified corpus: 117 lines, cells EngagementLedger, IndependenceTests. It passes soma check with soma 3.2.4.
How it is built
The cell EngagementLedger declares 5 signals in its face: sign_audit(firm: String, client: String) -> Map, sell_consulting(firm: String, client: String) -> Map, do_fieldwork(firm: String, client: String) -> Map, issue_opinion(firm: String, client: String) -> Map and engagement_load(firm: String, client: String) -> Int; keeps 1 memory slot: engagements (Map<String, Int>, persistent and consistent) under the invariant engagements >= 0 && engagements <= 1. Its state machine audit starts in proposed and allows 3 transitions: proposed -> engaged, engaged -> fieldwork and fieldwork -> opinion_issued. opinion_issued is terminal. Handlers: sign_audit (line 47), sell_consulting (line 59), do_fieldwork (line 70), issue_opinion (line 76) and engagement_load (line 82).
The file also holds 1 test cell (IndependenceTests) with 14 assertions, run by soma test.
The source
auditor_independence.cell
// ============================================================================
// AUDITOR INDEPENDENCE — one firm, one client, ONE role
// ============================================================================
//
// In 2000, Arthur Andersen billed Enron $25 million for the audit — and
// $27 million for consulting. The firm certifying the books had a bigger
// business interest in pleasing management than in challenging it. When
// Enron collapsed, Andersen's partners were found shredding audit
// workpapers; the firm itself dissolved, taking 85,000 jobs with it.
// Sarbanes-Oxley §201 answered by making the dual role itself illegal:
// a registered public accounting firm may not provide most consulting
// services to an audit client. Not "disclose it" — may not hold both.
//
// Here the prohibition is arithmetic. A firm/client pair can hold at
// most ONE engagement. Signing the audit writes 1; selling consulting
// to the same client tries to write 2 — and the engagement ledger
// refuses. The conflict isn't reviewed by an ethics board after the
// fact; it is a value the books cannot hold. The audit itself runs a
// machine where `opinion_issued` is terminal: once signed, an opinion
// cannot be quietly recalled and re-negotiated.
// ============================================================================
cell EngagementLedger {
face {
signal sign_audit(firm: String, client: String) -> Map
signal sell_consulting(firm: String, client: String) -> Map
signal do_fieldwork(firm: String, client: String) -> Map
signal issue_opinion(firm: String, client: String) -> Map
signal engagement_load(firm: String, client: String) -> Int
}
memory {
// firm:client -> engagements held. The Andersen position
// (audit + consulting, same client) is the unrepresentable 2.
engagements: Map<String, Int> [persistent, consistent]
invariant engagements >= 0 && engagements <= 1
}
// an audit engagement's life; opinion_issued is TERMINAL
state audit {
initial: proposed
proposed -> engaged
engaged -> fieldwork
fieldwork -> opinion_issued
}
on sign_audit(firm: String, client: String) {
let k = "{firm}:{client}"
let w = try { engagements.set(k, (engagements.get(k) ?? 0) + 1) }
if w.error != () {
return map("ok", false, "reason",
"SOX 201: {firm} already holds an engagement at {client}")
}
let r = try { transition(k, "engaged") }
if r.error != () { return map("ok", false, "reason", "{r.error}") }
return map("ok", true, "audit", k)
}
on sell_consulting(firm: String, client: String) {
// SAME ledger, SAME invariant: the second hat does not fit
let k = "{firm}:{client}"
let w = try { engagements.set(k, (engagements.get(k) ?? 0) + 1) }
if w.error != () {
return map("ok", false, "reason",
"SOX 201: {firm} cannot consult for an audit client ({client})")
}
return map("ok", true, "consulting", k)
}
on do_fieldwork(firm: String, client: String) {
let r = try { transition("{firm}:{client}", "fieldwork") }
if r.error != () { return map("ok", false, "reason", "{r.error}") }
return map("ok", true, "state", "fieldwork")
}
on issue_opinion(firm: String, client: String) {
let r = try { transition("{firm}:{client}", "opinion_issued") }
if r.error != () { return map("ok", false, "reason", "{r.error}") }
return map("ok", true, "state", "opinion_issued")
}
on engagement_load(firm: String, client: String) {
return engagements.get("{firm}:{client}") ?? 0
}
}
cell test IndependenceTests {
rules {
// Andersen signs the Enron audit — one engagement, lawful
assert sign_audit("andersen", "enron").ok == true
assert engagement_load("andersen", "enron") == 1
// THE $27M TEMPTATION: consulting for the same client. The
// ledger cannot hold the 2 — refused at the write.
assert sell_consulting("andersen", "enron").ok == false
assert_fails engagements.set("andersen:enron", 2)
assert engagement_load("andersen", "enron") == 1
// and symmetrically: a consulting-first firm cannot take the audit
assert sell_consulting("mckinsey", "enron").ok == true
assert sign_audit("mckinsey", "enron").ok == false
// different client, no conflict — independence is per-pair
assert sell_consulting("andersen", "dynegy").ok == true
// the audit machine: no opinion without fieldwork
assert issue_opinion("andersen", "enron").ok == false
assert_fails transition("andersen:enron", "opinion_issued")
assert do_fieldwork("andersen", "enron").ok == true
assert issue_opinion("andersen", "enron").ok == true
// a signed opinion is history — no recall, no re-negotiation
assert_fails transition("andersen:enron", "fieldwork")
assert_fails transition("andersen:enron", "proposed")
}
}What the toolchain says
$ soma check auditor_independence.cell
✓ All checks passed.$ soma test auditor_independence.cell
test IndependenceTests ...
✓ assert sign_audit("andersen", "enron").ok == true
✓ assert engagement_load("andersen", "enron") == 1
✓ assert sell_consulting("andersen", "enron").ok == false
✓ assert_fails engagements.set("andersen:enron", 2) — raised memory invariant violated on 'engagements': engagements >= 0 && engagements <= 1 — rejected write of 2 (key "andersen:enron"); the slot is unchanged
✓ assert engagement_load("andersen", "enron") == 1
✓ assert sell_consulting("mckinsey", "enron").ok == true
✓ assert sign_audit("mckinsey", "enron").ok == false
✓ assert sell_consulting("andersen", "dynegy").ok == true
✓ assert issue_opinion("andersen", "enron").ok == false
✓ assert_fails transition("andersen:enron", "opinion_issued") — raised invalid transition: engaged → opinion_issued. Current state: 'engaged'. Valid targets: [fieldwork]
✓ assert do_fieldwork("andersen", "enron").ok == true
✓ assert issue_opinion("andersen", "enron").ok == true
✓ assert_fails transition("andersen:enron", "fieldwork") — raised invalid transition: opinion_issued → fieldwork. Current state: 'opinion_issued'. Valid targets: []
✓ assert_fails transition("andersen:enron", "proposed") — raised invalid transition: opinion_issued → proposed. Current state: 'opinion_issued'. Valid targets: []
14 tests: 14 passed, 0 failed$ soma verify auditor_independence.cell
Verifying auditor_independence.cell...
State machine 'audit': 4 states, initial 'proposed'
States: [engaged, fieldwork, opinion_issued, proposed]
✓ 4 states, 3 transitions
✓ all states reachable from 'proposed'
✓ terminal states: [opinion_issued]
✓ no deadlocks
✓ liveness: every state can eventually reach a terminal state
✓ think-isolated: CTL safety properties hold regardless of LLM output (3 handlers, 5 literal transitions, 0 dynamic)
✓ termination: all 5 handlers structurally terminate
✓ refinement: handler `sign_audit` ⟶ {engaged}
✓ refinement: handler `do_fieldwork` ⟶ {fieldwork [if true], fieldwork [if not (true)]}
✓ refinement: handler `issue_opinion` ⟶ {opinion_issued [if true], opinion_issued [if not (true)]}
· transition sources: `sign_audit`, `do_fieldwork`, `issue_opinion` call transition(id, target) without declaring the source — the runtime refuses a move the graph forbids, but the proof does not see where the handler starts; `transition(id, from, to)` names the edge (checked by `soma check`, refused at run time from any other state)
EngagementLedger/invariants:
✓ invariant engagements >= 0 — writer 'sell_consulting' proven by induction (writes (engagements.get(k) ?? 0) + 1)
✓ invariant engagements >= 0 — writer 'sign_audit' proven by induction (writes (engagements.get(k) ?? 0) + 1)
⚠ invariant engagements >= 0 && engagements <= 1 — runtime-checked (computed values): sell_consulting → engagements [engagements <= 1] because `engagements` has no known range; `k` = "{firm}:{client}" — not bounded, sign_audit → engagements [engagements <= 1] because `engagements` has no known range; `k` = "{firm}:{client}" — not bounded
12 passed, 1 warnings, 0 failures
Temporal properties for 'audit':
✓ deadlock_free — no deadlocks in any reachable state
Temporal: 1 passed, 0 failed
VERIFY OK