Steward Console — hardware binding

Tap your YubiKey when it flashes. This page proves a specific key was physically present for an exact packet. It binds nothing on its own (authority_effect = 0) — the proof is what a later human act consumes.

Where this is

Console origin · API · RP id . Served from barycenters.ai. CORS limits which browser origins can read the API response; the real guarantee is server-side — every assertion is refused unless its signed clientData.origin and RP id match this console. So this page must stay served here, and your key is registered against this exact RP id.

1 · Register a hardware key

Enroll each YubiKey (primary, then a backup). Backup-eligible / synced passkeys are refused server-side — hardware only. Re-tapping an already-enrolled key is rejected, so a "backup" can't secretly be the same device. The first key is one tap. Each backup is two taps: the new key, then an already-enrolled key to authorize it — a stranger who reaches this page still cannot enroll their own key. A charter maps kid → one credential: enroll the backup under a distinct kid (e.g. steward-dami-2). Re-enrolling as a second kid adds a row — it does not remove the old same-kid enrollment. Unenroll the stale row here (tap a remaining key to authorize). Two keys sharing steward-dami cannot both be stewards.

ready.
loading enrolled keys…

2 · Sign a packet — legacy provenance (grants no release authority)

This grants NO release authority — do not tap it expecting to arm a release. A valid tap here proves a steward key was physically present over this exact packet and that the encoding verifies — provenance, nothing more. The resulting afterburner_trust_root_v1.json stays HOLD and never opens V1 or V2 (afterburner_trust_root_provisioner_v1 says so in its own docstring). Real release-signing is a separate, raw-byte-pinned V2 registry, and that gate is deliberately fail-closed (HOLD) today — so release authority is not armed on any path.

Paste a provisioning request produced offline by app/afterburner_trust_root_provisioner_v1.build_provisioning_packet(...) — shape {"keys":{kid:pubkey}, "packet":{...}}. The packet's keys_hash is computed in Python (canon-v1 authoritative); this page never re-hashes it. You'll see exactly what the tap grants before you tap. The output is the exact proofs/afterburner_trust_root_v1.json — a provenance record, committable but non-authoritative.

ready.

Before committing the output: set AFTERBURNER_STEWARD_WEBAUTHN_ANCHOR to your pinned steward credential and run python -c "from pathlib import Path; from app.afterburner_envelope_verifier_v1 import load_trust_root; print(load_trust_root(Path('.')))" — it must return your keys, not {}. That closes the loop this page cannot: it proves the encoding verifies.

3 · Sign a governance boundary — a real hardware signature, then submit it

A pack is law text. POST /v1/packs/{id}/instantiate returns unsigned candidates — prep, not a bind. This tap is the gavel: it produces a genuine SignedQuorumBinding, then this page POSTs it to /v1/boundaries and shows the live detail. Instantiating does not mark a pack proven_in_production. Default packet A is barycenters.ci.merge_to_main. Both Option B kids are named (quorum 1 — either key). A packet listing only steward-dami refuses a steward-dami-2 tap.

ready.

The signed output binds nothing on its own (authority_effect = 0). This page submits it: POST /v1/boundaries persists a hardware-signed binding for an already-chartered namespace. Fail-closed stays fail-closed — unsigned, forged, or a packet whose steward set is not the charter's kids is refused, and the live detail is shown here. After a successful bind, GET /v1/namespaces/{ns} lists the binding in bound_boundaries. A pack instantiate is not that list.

4 · Charter a namespace — genesis (your enrolled keys become its stewards)

This is the authority root. Name a namespace to claim; the server composes a genesis charter from every enrolled hardware key with a distinct kid — it reads the enrolled keys directly (the browser has no read path to the cose_key, by design), so the charter embeds exactly the keys that may tap. Quorum 1 means either key governs; losing one is survivable. Two keys under the same kid are refused: unenroll the stale same-kid row in Section 1 (do not guess, do not drop a key). An explicit credentialId still charters a single key — tonight's fallback if the collision is still live. Your tap self-signs the genesis; submitting it to POST /v1/namespaces is the one human authority act. The registrar enforces embedded == enrolled.

ready.

Register keys in step 1 first (backup = a second kid). The charter is composed from your ENROLLED keys and self-signed by one tap (quorum 1); it binds only when you submit it here (authority_effect = 0 until then). Quorum 1 with two distinct-kid keys is resilient governance — either key can still move the namespace if the other is lost. Raise the quorum when you want a boundary no single hand can shift.