Nothing reaches the report unverified
Everything else in the design follows from that. See The verification
gate.
The problem
An API ends up with three descriptions of itself: the handler code, the generated spec, and the prose your partners read. Different people edit each one, at different times. Code review asks whether the code is correct. It does not ask whether the code still matches what was promised, so the difference tends to show up at integration time, in someone else’s codebase.The problem, second half: who can reach what
Drift is not only what an endpoint returns. It is also who is allowed to call it, and that half is invisible in code review. Most codebases register two APIs in one place. One is the public contract, held open by an API key an integrator stores in a config file for years. The other is a dashboard or admin console, reached with a session token that expires. They live in the same router files, and are told apart only by which middleware they sit behind. Once one guard accepts both credentials (anauthenticate that takes
x-api-key or a bearer token, which is a very ordinary thing to write),
every route behind it is reachable with either. A machine key scoped for
payments now also reaches account management, and nobody decided that. It was
never written down, so nothing contradicts it.
The auditor makes that surface visible two ways:
contract-middlewarerestricts the audit to routes behind the guard that reads the credential your spec promises integrators. What comes back is, precisely, the set of endpoints your API key can reach. Anything in that list you believed was dashboard-only is an architectural finding, and it is the reason this section exists. That is how the payments API above discovered its own session endpoints answered to a merchant key.auth_guard_missingandauth_guard_undocumentedcompare each route’s guard against the security its spec declares, in both directions. Documented as protected but registered open is critical. Guarded but documented public answers an integrator 401 for following the documentation.
router.use(mw) protects only the routes
registered after it, and a route above that line is open however protected the
rest of the file looks.
Measured on a real payments API
Who it is for
Teams publishing an API
Run it in CI, and drift gets caught at the commit that caused it.
Fintech and payments
Knows about money precision, auth scope, idempotency, webhook signing.
Teams integrating
Where the code is readable to you: another team’s service in your own
monorepo, an open source API, or a vendor repo you were given. Check the
docs you were handed against it.
Platform and DevEx
A number for doc drift, instead of a hunch.
The audit reads source. Stage 1 parses the route table out of the handlers,
and the verification gate compiles and runs a test against them. So it runs
where the code is: in the provider’s repository, or in yours if the code was
shared with you. It cannot audit an API you can only reach over the network.
Quickstart
Running in five minutes, no API key.
How it works
The pipeline in one diagram.