Articles

Preparing a repository for audit

An audit is a fixed number of senior hours pointed at your code. Everything those hours go into that is not finding bugs is waste, and most of that waste is decided before the engagement starts. The difference between a repository that is ready and one that is not is routinely two days of a two-week review.

Freeze the code

The single most expensive thing a client does is keep committing. An auditor builds a mental model of your system over the first days; every push invalidates part of it, and the invalidation is invisible until something is reviewed against a version that no longer exists.

Tag a commit. Send the hash, not the branch. If something genuinely has to change mid-review, say so explicitly rather than letting it arrive silently in a merge - a known change costs an hour, an unknown one costs the trust in everything reviewed before it.

Say what the system is supposed to do

Most high severity findings are not violations of the code, they are violations of an assumption the code never wrote down. An auditor cannot tell you that an invariant broke if nobody said it was an invariant.

You do not need a formal specification. You need the answers to four questions, in prose, in the repository:

  • What must always be true, no matter what any caller does?
  • Who is trusted, and exactly how far? An owner, a keeper, a sequencer, an oracle - each is a trust assumption with a blast radius.
  • Where does value enter and leave, and who can move it?
  • What did you already decide to accept? Known risks stated up front are scoped out in minutes; discovered late they consume a report section.

Scope precisely, and mean it

Give a file list, not a directory. A directory quietly includes the mock you wrote in an afternoon, the deprecated contract you kept for reference, and the fork of a dependency you patched once. Every one of those gets reviewed at senior rates unless you exclude it.

Include the line count you expect. If your number and the auditor's number disagree, one of you is wrong about what is in scope, and finding that out before the engagement is free.

Make the tests run

Not full coverage - runnable. An auditor who cannot execute your suite loses the fastest tool available for confirming a suspicion, and goes back to reading. A README that builds on a clean clone, with pinned dependency versions and any required environment variables documented, is worth more to a review than another fifty tests.

If a test is currently failing, say which and why. Auditors treat an unexplained red test as a lead and spend real time on it.

The four things that waste the first two days

  • A branch instead of a commit hash.
  • A scope given as a folder, containing mocks and dead contracts.
  • No written trust model, so every privileged function has to be reverse-engineered before it can be judged.
  • A build that does not work from a clean clone.

None of these are hard. All four are common. Fixing them costs an afternoon and buys back review time you are already paying for.

What good looks like

A tagged commit. A file list with line counts. A page of prose naming the invariants and the trusted roles. A suite that runs on a clean clone. Known issues listed up front. That is the whole checklist, and a repository that arrives in that state gets a materially deeper review for the same money - not because anyone tries harder, but because none of the hours go anywhere other than your code.

Request an audit

All articles