Skip to content

v12.4 -- you could not create, clone or delete a strain on any install but ours

Choose a tag to compare

@paracoding-ai paracoding-ai released this 31 Aug 03:13
· 10 commits to main since this release

v12.4 — you could not create, clone or delete a strain on any install but ours

Full release tree at commit 5966424ee0e22cd2617ac4df7074925cfa7c2254 of the source repository,
published by the product's own gh_commit reading each blob straight out of its own git store.
MANIFEST.txt lists every file and its digest. 104 files. Eight paths move; the other 96 are
byte identical to 12.3.

IF YOU INSTALLED 12.3, THREE BUTTONS DID NOT WORK. Create a strain, subculture one, delete one
— each answered with a popup reading "Passkey: no registered passkey" on a product that does
not ship passkeys, does not ask you to enrol one, and cannot enrol one because install.sh
never sets WA_BOOTSTRAP_SECRET. There was no way around it from the console.

THE DEFECT WAS ONE MISSING CONDITION, IN THREE PLACES. /api/strain/create, /delete and
/subculture each opened with if (!waElevatedOk(req)), and waElevatedOk never consulted
PC_REQUIRE_PASSKEY. install.sh ships PC_REQUIRE_PASSKEY=0. The approval path in the same file
had it right — if (PC_REQUIRE_PASSKEY && !waElevatedForJob(...)) — so the correct pattern
was sitting eleven hundred lines away from the three call sites that lacked it.

WHY FOUR RELEASES SHIPPED WITH IT. This fleet's own production console carries a WebAuthn
credential in Firestore from an era when the gate was armed. There, the pre-flight returns a
challenge, Face ID appears, and the buttons work. A from-zero install has no such row, so the
pre-flight 400s and the handler returns before it ever reaches /api/strain/*. Every release
was exercised on the one install in the world that could not reproduce the bug. The operator
found it in twenty minutes by installing the published zip into a clean project, which is the
only test that was ever going to find it.

WHAT CHANGED. The three guards are gone, and so is the approval conditional they should have
matched: with PC_REQUIRE_PASSKEY=0 on every shipped install, that check has never once fired,
and a check that cannot fire is not a control. Nothing is loosened that was ever tight. The
console's three client-side handshakes go with them, because the server fix alone would not
have helped — the browser gave up before it called the server. So does a poller that hit
/api/webauthn/pending every fifteen seconds behind an empty catch.

IAP IS THE DOOR, AND NOW SAYS SO. waSessionOk's IAP branch was wrapped in
if (!PC_REQUIRE_PASSKEY), a condition true on every install this installer has ever
produced. It is now unconditional — the code finally describes the posture the product
actually ships. The fail-closed audience guard is untouched: no PC_IAP_AUD, no admission, so
an assertion minted for some other IAP-protected app still cannot satisfy this gate.
waMakeSession stops stamping pk and waSessionOk stops requiring it, in the same commit,
because doing one without the other is a total lockout in one direction or the other.
WA_SESSION_SECRET is untouched, so sessions live across the upgrade.

AND A COMMENT THAT PROMISED SOMETHING THAT NO LONGER EXISTS. Every staged destroy-class GCP
job was stamped "# DANGER destroy-class GCP call (METHOD) — Face ID required" into its own
command header, and into the journal. No Face ID had been required on that path for months.
An operator reading the audit trail was being told a tap happened that never did.

THE PASSKEY ROUTES ARE STILL IN THE TREE AND THIS RELEASE DOES NOT PRETEND OTHERWISE.
Removing the fifteen /api/webauthn/* routes and locked.html is the next commit, not this one:
gen.py's REQUIRED list names control-plane/src/locked.html and refuses the cut if it is absent,
and a second gate cross-checks every pcHtml() argument against the emitted tree, so the file,
its loader and the manifest entry have to move together. Shipping the fix tonight was worth
more than shipping the tidy-up with it.

Cut deterministically: gen.py run twice into separate directories, diff -r reports zero.

Apache-2.0. Your project, your bill, your key.