browserrot: Phase A-tier-1 site-side rotation engine (go-rod)

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>
This commit is contained in:
leetcrypt
2026-07-18 12:43:56 -07:00
parent 6e3b39b393
commit 7a06d57bb3
8 changed files with 798 additions and 3 deletions
+14 -3
View File
@@ -308,9 +308,20 @@ adapter is pure-exec Go, so it is unit-validated cross-platform via an injected
- **Phase B (now):** `pwgen` + `pwstore` (interface + Bitwarden/1Password/KeePassXC in-place +
Chrome/Firefox CSV ingest-and-shred) + the staged-list propagation engine + `passwords`
commands. Human does the site change + MFA; incredigo does everything else.
- **Phase A-tier-1:** deterministic `go-rod`/`playwright-go` driving the curated change-URL
table for a handful of high-frequency, no-MFA sites, with verify-before-commit. Measure the
real success rate before promising anything.
- **Phase A-tier-1 (engine built):** `internal/browserrot` — a deterministic `go-rod` driver
(behind a browser-agnostic `Driver`/`Session` interface so `playwright-go` and a Tier-2 AI
driver are swap-ins) that discovers the change page via `internal/links` (curated table +
RFC 8615), injects OLD + a freshly-minted NEW password over CDP with **no model in the loop**,
submits, and **re-logs-in to verify the new password before commit** (hard rule 2). A `Rotator`
here implements `rotate.Rotator`, so `rotate.Snapshot` (backup), the verify-before-revoke
ordering, and the proof gate all apply unchanged; `RevokeOld` is a no-op because the site
invalidates the old password itself. Proof-as-data per `Site`: the **ENGINE is LIVE-VM**
(real headless Chromium against a real local change-password form —
`lab-provision-browserrot.sh` / `TestIntegration_realBrowserRotation`); a **specific real-site
selector table stays UNPROVEN** until run against that real site, and no production `rotate`
wiring auto-enables it yet (still gated behind per-credential authorization). Still to do:
build out the curated selector table for real high-frequency no-MFA sites and measure the real
success rate before promising anything.
- **Phase A-tier-2:** Computer-Use / AI-in-browser vision fallback for DOM variance, with
**secrets kept out of the model loop** (the model decides navigation; the Go harness injects
the actual password via CDP, redacted from the screenshot stream). Opt-in, measured.