Rotate owner-signed challenges.toml / measurements.toml (or challenge keys inside them) without a hot push and without bricking validators mid-epoch.
Normative ceremony background: ../../config/CEREMONY.md.
Threat bounds: owner remains the trust root (R12 / D19).
- Rotation is a signed release, never an unsigned file drop on a live host.
- Publish
v(n+1)besidev(n). Loaders accept either signature/body pair forrotation_epochs(default 3) after the newer file'sintroduced_epoch. - After the window, drop
v(n)in a follow-up release. - Challenge secrets stay off-git (age-encrypted). Only public keys and TOML bodies +
.sigenter the repo.
# From repo root. Secrets outside git.
mkdir -p ~/.base-secrets
chmod 700 ~/.base-secrets
# Optional: ensure age identity exists (do not commit)
# age-keygen -o ~/.base-secrets/age-identity.txt
# Edit the next version body (example paths; keep v(n) files until window ends)
cp config/challenges.toml config/challenges.vNEXT.toml
# ... edit public keys / bps / participant policy ...
# Ensure emission bps sum to 10000.
# Sign with owner mini-secret (age-encrypted path shown)
cargo run -q -p trustroot-bin -- sign \
--key ~/.base-secrets/owner-throwaway.age \
--age-identity ~/.base-secrets/age-identity.txt \
--input config/challenges.vNEXT.toml \
--kind challenges \
--out config/challenges.vNEXT.toml.sigIf you do not have the production owner secret in this environment, stop. Do not invent a new owner key for prod.
cargo run -q -p trustroot-bin -- verify \
--owner-pub config/owner.pubkey \
--input config/challenges.toml \
--kind challenges
cargo run -q -p trustroot-bin -- verify \
--owner-pub config/owner.pubkey \
--input config/measurements.toml \
--kind measurementsBoth must exit 0 against the committed owner pubkey.
When dual files are wired in config, verify both v(n) and v(n+1) the same way.
- Open a PR that adds
v(n+1)artifacts and bumps release notes. Do not deletev(n)yet. - Merge to
rebornafter CI green (external-docs-check,spec-check, tests). - Promote images / config to staging first (
promote-rollback-restore.md). - Confirm validators log acceptance of either root during the dual-accept window.
- After
rotation_epochsepochs on prod, PR to removev(n).
- If signature verify fails anywhere: do not promote. Fix the body or resign offline.
- If a bad root already reached staging: roll back the release digest and restore previous config files from git tag / backup.
- Compromised challenge key: quarantine absorbs garbage scores (D6); still rotate the key via this runbook (R10). Honesty of past scores is not restored (D19).
These must exit 0 on a clean checkout with the committed throwaway owner key:
cargo run -q -p trustroot-bin -- verify \
--owner-pub config/owner.pubkey \
--input config/challenges.toml --kind challenges
cargo run -q -p trustroot-bin -- verify \
--owner-pub config/owner.pubkey \
--input config/measurements.toml --kind measurements