Deterministic, headless browser-driven password rotation:
discover change page via RFC 8615 / links, inject old+new over CDP
(no model in the loop), submit, and re-login to verify the new
password before commit. Implements rotate.Rotator so the mandatory
backup gate, verify-before-revoke ordering, and proof gate apply
unchanged; RevokeOld is a no-op (the site invalidates the old pw).
Proof-as-data per Site: the engine is LIVE-VM (real headless
Chromium vs a real local change-password form, via
lab-provision-browserrot.sh / TestIntegration_realBrowserRotation);
real-site selector tables stay UNPROVEN and nothing auto-registers
into production rotate yet. 14 packages, -race clean.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the Rotator interface across all four rotation patterns, each a
self-contained one-file driver self-registering via init():
in-place DB password postgres, mysql (3-stmt unprivileged fallback), redis
local keypair + propagate sshkey (ed25519), wireguard (clamped curve25519)
provider-API token gitea PAT, mullvad device key
cloud-key self-identifying aws IAM access key (hand-rolled SigV4, no SDK dep)
Spine (execute.go) enforces Hard Rule #2: backup -> rotate -> verify(new) ->
store -> re-read+verify -> revoke-old; dryrun.go keeps --execute gated. Each
driver ships a table-driven test proving real cutover (old secret stops
authenticating) and asserting no secret substring leaks to argv/Meta/errors.
Promotes golang.org/x/crypto to a direct dependency.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>