DEV Community

Alkis Yuv
Alkis Yuv

Posted on Originally published at dev.yuv.run

Every hole in the gate is signed

A routine commit in my hub repo tripped the content screen last week on text that had been fine for weeks. The screen is the pre-commit door that refuses anything matching my leak patterns, and the text it refused was the kind the hub exists to hold: the names it is allowed to name, the banned terms a standard must quote in order to ban them. Those had exemptions. The exemptions lived in a file that had been there since the screen was written, one regex per line, and a new version of the auditor had started reading that format as "unsigned", reporting it, and then ignoring it. Every exemption in the file had silently stopped applying.

I want to be precise about why this surfaced at all. It failed in the strict direction: the gate checked more, not less, so it blocked a commit and I noticed. The same change could as easily have made a gate check less, and nothing, no commit, no report, no test, would have told me. That asymmetry is the whole argument of this piece.

- A hole in a gate that nobody signed and a gap in a gate that nobody declared are the same object, a thing no one can audit later, and the difference between them is only which way the next upgrade happens to fall.

So the exemption format changed, and the change is the signature. Each exemption is now a block of labeled lines, and one missing field means the exemption does not apply:

-^AcmeCorp|BetaCorp$
+pattern ^AcmeCorp|BetaCorp$
+reason fixture proving the detector fires on either name
+date 2026-08-15
+author someone
Enter fullscreen mode Exit fullscreen mode

Migrating the old file forced the exercise the old format had let me skip: writing the reason next to each pattern. Thirteen bare regexes went in; fifteen signed blocks came out, two of them new, for content the old file had never covered and that only became visible once every block had to say what it was for. One reason field records its own history: the pattern had been a hand-kept roll-call of project names until registering a new project made the hub's own gate refuse the commit that registered it. A list kept by hand lags in the direction that blocks work. Its replacement names the family by shape.

The labeled lines are not a style choice, and this is the second lesson, smaller, but the one I would carry to any format you design for a parser. The field is a regex. A regex can contain any printable character, so there is no character you can put between fields that the field itself cannot also contain: no colon, no tab, no pipe, none. The old one-per-line format worked because nothing in it had happened to be ambiguous yet. The rule I wrote down afterwards: delimit a field in-band only with a character the field cannot contain by construction, imposed by the filesystem, the protocol or the language grammar, never by convention. Where no such character exists, stop delimiting; give each field its own labeled line and let the line break do the separating. And never fix a format's ambiguity with guards in the parser. Guards convert the misparses you imagined into loud ones and leave the rest exactly as silent as before.

The machinery is public. etymd is the auditor; npx etymd screen --tree runs the screen over a working tree, .etymd-screen-allow at the repo root holds the signed exemptions, and the screen reads that file from the repo it is screening and screens the file too, because an exemption file is also content. That much you can set up today. The rest of the essay is why the four labels are not optional.

What I took from the week is a test I now apply to every gate I run: for each way it could stop checking, what would tell me? If the honest answer is "a commit that should have failed", the gate's failure mode is an unaudited hole, and signing the holes you already know about is the cheapest place to start.

Top comments (0)