Skip to content

What Broke, and How We Knew

A learning module. Kerckhoffs said a system must stay secure when everything about its mechanism is public. This page extends the line one step: it must also stay credible when everything about its failures is public. These are real defects from this substrate — what broke, how it was caught, and what the fix was. Not a postmortem ritual. The catching is the mechanism, and a mechanism you cannot inspect is a promise.

Most projects publish the design and hide the corrections. That is backwards for anything meant to be a substrate. If other people are going to build a floor on top of yours, the useful artifact is not your architecture diagram — it is the list of ways your floor turned out not to be one, and what you now do about each.

So this is the audit report of ourselves. Every case below has a date, a number and a guard that would catch it again.

a design tells you what was intended
a failure tells you what was actually load-bearing

1. A read surface was writing the decision ledger

What broke. A status call was a read. A panel called it for every paired device on a two-second refresh. Having that panel open therefore minted a hash-chained decision tick per device per sweep.

Measured on a live box: 968 ticks per device in 129 minutes, identical across every paired device, evidence file at 224 MB, growing 241 000 lines a day.

Why it mattered more than the disk. It destroyed the only signal that made a fleet of paired devices legible. A first attempt at a device roster read "last seen" out of that chain and reported every device as in use — because the ledger cannot tell a glance from a device. Both write the same record.

How we knew. Nobody holds twenty-five phones. The absurdity of the output was the detector; the size of the file was only the symptom.

The fix.

decision ledger    a tick only when the STATE changed, plus one heartbeat a day
                   (an auditor can still say the binding was live on that date)
observation file   "when did this device last reach us" — a plain file, not a tick

Growth went from 192 lines/min to zero. The rule that came out of it is now doctrine:

A read surface may not write the decision ledger.


2. The chain could fork itself while nothing was wrong

What broke. Two writers read the same tail of the hash chain, both computed the same parent, and both appended. No error was raised. The chain had a fork in it, and a fork looks exactly like tampering.

Measured across the pre-fix history: 903 436 lines, 223 breaks, every one the same shape.

85218  prev=f454562171ed  self=d44b95609519
85219  prev=f454562171ed  self=22b26fb31332      same parent, same second

Why it mattered. Tamper-evident had quietly become race-evident. A chain that can fork itself cannot distinguish an attack from a collision, which is the entire property it exists to provide. At 0.025% per append it is rare per decision and certain over months.

How we knew. A deep verify was run against the full history rather than a sample — because "the chain is fine" had never actually been measured end to end.

The fix. A lock around the whole critical section: read-parent, append, fsync. Appending atomically is not enough; the collision happens before the write, in the read of the tail.

Cost, measured over 200 real appends: 0.171 ms and 0.253 ms per append on two machines — cheaper than the full-tail read it replaced.

The part worth copying. Where the lock is unavailable, the system does not quietly fall back to the racing path. The record itself carries the missing guarantee, and the classifier counts those records. Refusing to write would be worse than degrading:

A receipt withheld is evidence destroyed.

And the old breaks were classified, not rewritten. They are still there, named, with their shape.


3. A label that forgave everything

What broke. Sealed segments carry an integrity profile so a pre-lock history is not shouted at as tampered. Verification short-circuited on "this segment is linear" and never compared the recorded profile against the bytes. A manifest claiming seven breaks was therefore accepted for a spotless segment.

How we knew. Its own guard caught it — a test written to check that the label could not be abused.

The fix. A recorded profile is compared always, linear included, and a mismatch names the difference.

A label that forgives anything is worse than no label.


4. Four times, the failure was the measuring instrument

This is the uncomfortable one, and the most useful.

In a single week, four red verdicts turned out to be about where the checker looked, not about the system:

what reported a failure what was actually wrong
a device roster it read the decision ledger, which cannot tell a glance from a device
a surface comparison it read a scrolling viewport instead of the composited screen
a key-hint guard it pinned its working directory to a shared temporary path, so it never looked at the machine it ran on — passing on a week of leftovers in one place, failing where the path did not exist
a count canary it called an honest split ("nothing at the front · 5 earlier positions") a bare total

Three of the four would have sent someone to fix a feature that was not broken.

A checker with the wrong measurement point is the thing it exists to catch.

The fix, as a rule. A red verdict is a hypothesis. Where the checker looked must be proven before anything is reported as broken. Guards now name the state they measured — a fresh install and a lived-in one are different screens, and each answers for itself.

A related trap, from the same family: a fixed number of waits inside a test is a wall-clock assumption hiding in a guard. Waiting until the screen stops changing is the version that survives a slower machine.


5. The same number, wrong on three surfaces at once

What broke. "How many devices are paired" was derived independently by three surfaces. All three answered twenty-five. Not one of them was lying about its own reading — they were all reading a store that cannot say which device is now.

The fix. One source, and a canary that refuses both a difference between surfaces and a bare total, because a single number is the original lie. Each surface is compared at its own last mile: a command-line tool at its printed output, a terminal UI at the composited screen, a browser view at the painted DOM, a device at the screen in someone's hand.

And what the comparison cannot reach is named, never assumed to pass:

surfaces not measured (surface_unknown — the brother of paths_unknown):
  browser view   painted DOM — needs the console running plus a driver
  device         the screen in the hand is the last mile; none attached

A map that lies is worse than a hard error.


6. A deployed file is not a running fix

What broke. Twice in one morning, a corrected file was copied to a machine and the old code kept running — a long-lived process still held the previous module in memory. The verification had checked that the file arrived, which is not the same question.

The finer point. "Deployed" is not one claim. It is three, and each can be true while the next is false:

file copied     ≠     process changed     ≠     behaviour changed
(a filesystem fact)   (a runtime fact)         (an observable fact)

The cheapest, most familiar operation in the world hides all three at once:

systemctl restart something-api      # claims all three, proves none

It can copy nothing (the file was already there), change nothing (the unit points at a different path than you edited), or restart cleanly while the behaviour is identical (a second copy shadows yours, a cached artefact wins, the config was never re-read). Each break looks like success from the step before it.

So each claim needs its own evidence, and they are different kinds of evidence:

claim what proves it how it fails silently
file copied digest on disk equals the digest you meant you wrote to a path nothing loads
process changed the running process is newer than the file, and loaded that path the unit restarted a different thing, or nothing did
behaviour changed the thing reports something only the new code can report it restarted and behaves exactly as before

The fix, as a habit. Ask the running thing what it thinks it is, rather than asking the filesystem what it holds. The same three-step applies to a release: the published digest, the downloaded bytes, and the runtime's own self-report must all agree before anything is called shipped. Two matching out of three is the most convincing way to be wrong.

A smaller sibling from the same day: a pattern-based process kill matched the shell that issued it, because the pattern was in its own command line.


7. The gate that never looked at the guards

What broke. Eight guards existed, each with a proof that its refusal actually bites. The release gate — 230 lines of fail-closed checks — referenced none of them. The release chain had its own version of a read surface that never reads.

The fix. The gate runs every guard, and treats the three outcomes distinctly:

exit non-zero      FAIL   the release is blocked
exit zero, scoped  WARN   first-class: it named what it could not reach
could not run      FAIL   NEVER a pass — a check that fails to execute
                          has measured nothing, and silence must not read as green

Within an hour it earned itself twice, and one of those was against its own author: a guard baseline measured on a build machine had been reported as coverage, when two of those passes were built on leftovers and on emptiness.


Why publish this

Three reasons, in increasing order of importance.

Because a substrate is inherited. If someone builds on this floor, the failure list is more load-bearing than the feature list. They need to know which of our assumptions did not survive contact.

Because zero-trust that hides its own defects is a contradiction. A system asking not to be trusted implicitly cannot ask for exactly that about its own quality.

Because the detection is the product. Any system will have defects. What distinguishes one you can build on is whether it finds them, names them, and keeps a proof that the finding still works. Every case above has a guard attached, and every guard has been watched failing on purpose.

A guard nobody has watched fail is a guard nobody has tested.


The rules that came out of it

Collected, because they generalise past this codebase:

a read surface may not write the decision ledger
a receipt withheld is evidence destroyed
a checker with the wrong measurement point is the thing it exists to catch
a red verdict is a hypothesis until you prove where the checker looked
a label that forgives anything is worse than no label
a map that lies is worse than a hard error
could-not-run is a failure, never a pass
a deployed file is not a running fix
one source, N witnesses — each measured at its own last mile
what cannot be measured gets a name, never an assumption

None of these were designed in. Every one is scar tissue.


Related: Everything Falls Back to TIBET · Operating in the Agentic Era: Audit as a Precondition · What We Push Is What You Download · Reasoning ≠ Execution