Skip to content

verifier cutover: move the size pins, and make a stale site page someone - #417

Merged
defenwycke merged 3 commits into
mainfrom
docs/verifier-cutover-v0217
Sep 19, 2026
Merged

defenwycke merged 3 commits into
mainfrom
docs/verifier-cutover-v0217

Conversation

@defenwycke

@defenwycke defenwycke commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Two halves of the same incident.

1. The cutover's repo-side size pins

check-deployed-verifier.sh compares the README's raw figure against the deployed module, not against the release — so these move in the same cutover as the site. Update them first and the check goes red; update the box first and it also goes red.

old new
raw 1,064,517 1,065,400
gzipped 295,077 295,130

Gzipped measured, not derived: gzip -c < hazync-verify.wasm.

docs/THREAT_MODEL.md carried "both measured 200, 1,064,517 bytes, on 2026-09-14" — now the v0.21.7 size, dated to the cutover rather than left implying it's current.

2. release.sh now says the cutover is owed

hazync.org served v0.21.6's verifier for ~80 minutes after v0.21.7 published, and nothing prompted anyone.

release.sh classes deployed-verifier as IGNORABLE_JOB because that job tests the live site and is red by construction between a release and its cutover. The script knew the job was ignorable; it never said what the operator owed as a result. It finished green and silent.

So it now names the cutover in its closing block, beside the other things it can't do itself, and points at the one command that proves it landed.

⚠ What I removed, and why

I first added hazync-check-deployed-verifier.{service,timer}. That was wrongadversarial.yml's deployed-verifier job already runs on a schedule, and last night's scheduled run has it completed/success. A systemd timer would duplicate it on boxes that cannot run it: the script needs node to instantiate the wasm and call method_id(), and neither the coordinator nor the web box has node. Installing a JS runtime on the box holding the ledger, to re-run a check GitHub already runs, is a worse trade than the gap it closes.

Do not size the gap from the cron expression. The workflow says 0 3 * * *, but GitHub defers scheduled runs under load — the last five started 07:33, 07:37, 07:59, 07:56, 08:02 UTC. v0.21.7 published at 08:46, 45 minutes after that morning's run had already passed, so a stale site would have gone unnoticed until the next morning.

That makes this a prompting failure, not a monitoring one — which is what the release.sh note fixes.

Verified both ways

Before the cutover the check failed: release asset is 1065400 bytes, the deployment is 1064517 — the site is serving something the release did not ship.

After, it passes — deployed size = release = README, method_id canonical, live spine verifies through block 79,706, bit-flipped proof rejected. It can fail, and it can pass.

check-deployed-verifier.sh compares the README's `raw` figure against the DEPLOYED
module, not against the release. So these pins must move in the SAME cutover as the
site: update them first and the check goes red, update the box first and it also goes
red. They are one change, not two.

Measured, not copied: gzip -c < hazync-verify.wasm = 295,130 bytes (old 295,077).

THREAT_MODEL.md carried "both measured 200, 1,064,517 bytes, on 2026-09-14" — the size
is now v0.21.7's and the claim is dated to the cutover rather than left to imply it is
still current.
… not ship

⛔ THE HOLE. On 2026-09-19 the site served v0.21.6's module for hours after v0.21.7
published and nothing noticed. release.sh classes `deployed-verifier` as IGNORABLE_JOB
because that job tests the LIVE SITE and is red BY CONSTRUCTION between a release and
its cutover — so a green release is compatible with a stale site. Afterwards, nothing
looked again.

⚠ AND THE CHECK ALREADY EXISTED. scripts/check-deployed-verifier.sh was written, correct,
and exited 1 on exactly this condition. It was installed on no box and wired to no timer.
A check that runs nowhere cannot fail, which is the same shape as a probe whose silence
reads as success.

Two parts:

1. hazync-check-deployed-verifier.{service,timer} — hourly at :37, through hazync-run-check
   so a failure reaches ntfy via OnFailure=hazync-alert@%n.service. CHECK_FAILS_BEFORE_ALERT=2
   because a release and its cutover are minutes apart and one transient fetch is not a stale
   deployment.
   ⛔ The unit deliberately does NOT set ALLOW_SKIP=1. The script honours it and exits 0 when
   tooling is missing — right for a laptop, exactly wrong here, and it would rebuild the very
   hole this closes.

2. release.sh now NAMES the cutover in its closing block, next to the other things it cannot
   do itself, and points at the one command that proves it landed. The script already knew
   `deployed-verifier` was ignorable; it never said what the operator owed as a result.

Verified before committing: the check FAILED against the stale site ("release asset is
1065400 bytes, the deployment is 1064517") and PASSES after the cutover. It can fail, and
it can pass.
@defenwycke defenwycke changed the title docs: the deployed wasm is v0.21.7's — 1,065,400 raw, 295,130 gzipped verifier cutover: move the size pins, and make a stale site page someone Sep 19, 2026
⛔ I PROPOSED MACHINERY FOR A SOLVED PROBLEM. adversarial.yml's deployed-verifier job
already runs on a schedule — `if: github.event_name == 'schedule' || workflow_dispatch`
— and last night's scheduled run has it completed/success. A systemd timer would
duplicate it on boxes that cannot even run it: the script needs `node` to INSTANTIATE
the wasm and call method_id(), and neither the coordinator nor the web box has node.
Installing a JS runtime on the box that holds the ledger, to re-run a check GitHub
already runs, is a worse trade than the gap it closes.

⚠ AND THE GAP IS WORSE THAN A CRON LINE SUGGESTS. The workflow says '0 3 * * *', but
GitHub defers scheduled runs under load: the last five started 07:33, 07:37, 07:59,
07:56 and 08:02 UTC. v0.21.7 published at 08:46 — 45 minutes AFTER that morning's run
had already passed. So the stale site would not have been noticed until the next
morning's run, roughly 23 hours later. Do not size this from the cron expression.

⚠ THE REAL FIX IS PROMPTING, NOT MONITORING. Nothing told the operator the cutover was
owed; release.sh finished green and silent. The closing note added in the previous
commit addresses that directly, and is what stays.

What stays: the size pins, and release.sh naming the cutover in its closing block.
@defenwycke
defenwycke force-pushed the docs/verifier-cutover-v0217 branch from 22130aa to 8fdc54f Compare September 19, 2026 10:11
@defenwycke
defenwycke merged commit 23ac92d into main Sep 19, 2026
6 checks passed
@defenwycke
defenwycke deleted the docs/verifier-cutover-v0217 branch September 19, 2026 11:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant