In two days on one compliance pipeline we found three controls that could never work. A status that opens a user’s workspace could never be written. A role that approves applications could never be held. A button that issues invitations had never been displayed. Each had passing tests around it, and none of them ever failed, because none of them ever ran. Walking the chain end to end found all three; the unit tests found none.
The pipeline
The client runs a network of freelance correspondents who file reporting that institutional clients act on. Before a correspondent can work, they pass a series of gates: a conflicts declaration, an editor’s review, policy acknowledgments, and a signed agreement. Each gate writes an immutable record. When every required gate is clear, the correspondent’s compliance status becomes active, and enforcement opens their workspace only at active.
The design had been reviewed, the gates were built one by one, and each one had tests. Then we started preparing the change that turns enforcement on.
Three controls that could not fire
| The control | Why it could never fire | What it would have caused |
|---|---|---|
The active status | No code path ever wrote it | Enforcement would have locked out every correspondent, with an audited override as the only way back |
| The editor role that decides applications | Becoming an editor needs an invitation, only a senior editor can issue one, and nothing could make anyone a senior editor | The role the design made responsible for approvals could not be held by anyone, in any environment |
| The senior editor’s “invite an editor” button | It had never been shown to anyone, because nobody held the role that saw it | When it was first rendered, it posted an empty body to a handler that had required a recipient for months |
The status nothing wrote
The status field was carefully protected. Every new record was pinned to invited. Any update that tried to change it was refused, for administrators too. It could move only through the pipeline’s own handlers. Tests proved all of that.
What no test asked was whether any handler ever did move it to active. None did. The workspace check was correct, the protection was correct, and together they would have locked out every correspondent on the day enforcement went live, including one working in production that week.
The role nobody could hold
The approval design said an editor decides who joins, not an operator. To become an editor you redeem an invitation. To issue an invitation you must be a senior editor. Nothing in the product made anyone a senior editor, which was deliberate: an endpoint that grants the root editorial role is a self-promotion path. The seed script was also right to refuse to treat administrators as editors.
Each piece was correct. Together they meant the chain had no first link. The fix was a script that appoints the first senior editor alongside the database, requiring a reason and a named appointer, the same way the first administrator is created.
The button nobody had seen
Once someone could hold the senior editor role, the invite button appeared for the first time. Its handler had required a recipient address since it was written. The button sent {}. The handler’s tests passed, because they called the handler with a recipient. The button had never been clicked, because no one could see it.
Why tests missed all three
Each test checked one control in isolation, set up with the state the control needed. A test for the workspace check creates a correspondent who is already active. A test for the editor’s approval creates a user who is already an editor. A test for the invite handler passes a recipient.
The fixtures supplied exactly the thing that was missing in real life. A unit test answers “does this control behave correctly when it is reached?” It cannot answer “can it be reached?”, because the setup reaches it for you.
That is why these defects never show up as failures. They show up as silence: a gate nobody clears, a role nobody holds, a screen nobody opens. Nothing errors, so nothing alerts.
The same shape, one level down
Once we knew the pattern, we went looking for it.
States nothing writes. Two of the seven compliance status values were declared in the schema and described in the design, but written by no code and present in no row in any environment. We recommended removing them. The owner decided to keep them for gates still to be built. That is a fine decision, but it is one an unreachable-state sweep will flag again, so we pinned it with a test. Each reserved status names the issue that will write it, the declared statuses must match the schema in the other repository, and nothing may write a reserved status before its gate exists.
A gate that masks another. A later gate, a recurring trading attestation, was built to block activation, following its issue’s wording. The owner had already ruled it would come after launch. Worse, the code that decides what a correspondent is waiting for returns only the first unmet step. A non-binding gate placed ahead of the agreement would hide an unsigned agreement, and the promotion logic, seeing only a non-binding item, would have marked someone active who had signed nothing. Post-launch gates now sit last in the chain, and a test pins that order.
How to find unreachable controls
Walk the chain as a real user, from nothing. We wrote a rehearsal script that starts from an empty account and drives every gate in order to active, using no fixtures and no direct database writes. It now runs before the enforcement change can merge. It found more than the unit tests in a fraction of the time.
For every control, ask who provisions it.
- For every gate: what writes the state that clears it?
- For every role: how does the first person get it, in every environment?
- For every screen or button: does anyone hold the permission that renders it today?
- For every status value: what code writes it, and does any row have it?
If the answer is “nothing yet”, either build the path or write that down beside the code with the issue that will build it.
Search for writes, not definitions. An enum value, role name or permission declared in one place and assigned in none is a lead. So is a handler with tests and no caller.
Turn enforcement on as one deliberate change. Ship gates that record and display what’s outstanding, but block nothing. Turn blocking on once, after a rehearsal shows a real user can clear every required gate. If you enforce gate by gate, each new gate locks out everyone who hasn’t cleared it yet.
The general rule
A control has two properties: it behaves correctly when reached, and it can be reached. Unit tests are good at the first and blind to the second, because their setup supplies the reachability. Check the second directly, by walking the path the real user takes, before the day the control starts to matter.
How we can help
We stabilize and harden applications before the day their controls start to bite, by walking the real paths rather than trusting the test suite. If you are about to turn on enforcement, permissions or compliance gates, talk to us first.