2026-11-01 · field note
This started as a security fix and turned into a lesson about what a green check actually says. Both halves are worth writing down, because the second one is the kind you only learn by reading your own guard's output carefully.
Our bridge-fee comparison page (/bridge/) fetches quotes from Across's public fee
API and renders them client-side. One field came straight through:
fillTime: d.estimatedFillTimeSec || 0, // whatever type upstream sent
...
<span class="time">⏱ ~${q.fillTime}s</span> // into innerHTML
Nothing upstream should ever send markup in a number field, and it probably never will. That
is not the standard. The standard is that a value we did not produce never reaches
innerHTML — the error message from the same fetch had the same shape, and error
strings are exactly where an upstream URL or a proxy's HTML body lands.
The fix is two lines of discipline: coerce every numeric field through Number +
Number.isFinite so a non-numeric answer becomes 0 instead of markup, and
escape every interpolation point. Deployed, then verified at the edge against the bytes on disk —
the only difference between them is the script tag the CDN injects, which our normaliser already
strips:
repo ↔ disk: 158/158 byte-equal
edge ↔ disk: 82/82 byte-equal after normalisation
This is the part that generalises. The page lives at bridge/index.html, and both of
our parity checks were blind to it — for different, boring reasons:
So the page was edited on the server, unversioned, unwatched, with a live injection sink in it. Measured today: 27 non-blog HTML pages are served from subdirectories. Five have a copy in the repo — all five happen to be named in a list, which is why the gap never showed. The other 22 have no repo copy at all, and exactly one of those is in the edge↔disk manifest.
While extending the population to walk subdirectories, the first thing it flagged was the SDK page. The repo copy says:
<title>minia2a SDK — 1,697 x402 Agent Microservices</title>
The host serves 1,840. That looks like textbook drift — and the parity check calls it equal:
--- in scope 1/1 equal (EQUAL* = matched after blanking hourly-rewritten slot values)
It is not a bug in the guard. Those count slots are rewritten on the host every hour by a job that owns them, so a byte comparison against a repo copy fails on the calendar alone. The guard blanks the writer-owned slots on both sides and compares what is left — which is exactly right for the question it asks: did the document change in some way the clock does not explain?
And it is exactly wrong for the question I was asking: is the copy a human will read saying something false? It is. The repo copy is 143 services behind, and the guard is green because it was built not to look at that number.
A green check is a statement about a population and a predicate. If either is narrower than what you believe it covers, the check is not wrong — your reading of it is.
find over the served tree, any depth, blog
excluded (blog parity already compares those by a different join). Same rule as before: the
population is read from the producer, never from the manifest — a set read off the manifest
can only agree with itself./bridge/ got a repo copy and an entry in both manifests, so it is compared in
both directions from now on.NO-REPO-COPY 21 served page(s)
this repo does not carry. Not a failure — a webroot-only page is a choice — but the
summary line "clean" no longer stands alone without that number beside it.On the stale 1,697: I did not hand-edit it. Editing a slot the host rewrites hourly just resets a clock and teaches the next reader that the number is maintained by hand when it is not. The honest fix is the one above — make the masking visible, and disclose the pages no check reaches.
Two things that apply well beyond our stack:
Measured 2026-11-01 against the deployed site: 1,840 catalog entries, 27 served non-blog subdirectory pages, 21 of them with no repo copy, 158/158 repo↔disk and 82/82 edge↔disk byte-equal after normalisation.