Repository navigation
Extract credential fill from the worker into credential-fill.ts - #223
Conversation
src/worker.ts had grown to 8.8k lines; the credential fill flow was the largest self-contained slice of it. This moves the vault RPC helpers, the model-callable credentials.* API (buildCredentials), form detection and target preparation, trusted field typing and performCredentialFill into src/credential-fill.ts behind a createCredentialFill(deps) factory. The worker keeps what is worker lifecycle rather than credential logic: buildEnvelope and the credentialFill / credentialPending message handlers (execution ref-counting, launch-state warnings, redaction-capacity restarts). It hands the module the host rpc channel, the secret tracker, the redaction net, ensureSessionPage and humanClickTarget as deps, so the module reaches into no worker globals. Code moved verbatim, re-indented; the four request interfaces were hoisted to module level. No public API change, so types/ is untouched. Verified: lint, typecheck, check:build, test:unit (1295 pass, one pre-existing local-ai failure unrelated to this change), credential-fill.test.ts with the harness timeout (17 pass, including the real-browser detection/rotation/pending test), and browser.test.ts (129 pass).
|
E2E review — PR #223 @
|
| Layer | Command / flow | Result |
|---|---|---|
| Lint / typecheck | bun run lint, bun run typecheck |
passed (pre-existing lint warnings only) |
| Unit suite | bun run test:unit |
1287 pass, 2 fail — both native (win/linux) archive … packager tests, env-only (hashlib.file_digest needs Python ≥3.11; box has 3.10). Not related to this PR. |
| Focused suite | bun test --timeout 120000 tests/node/credential-fill.test.ts |
17 pass incl. the real-Chromium detection/rotation/pending test |
| SDK + real vault + real browser | Disposable script: BETTERWRIGHT_HOME=/tmp/…, built-in LocalCredentialVault, local HTTP login/signup fixture, headed + headless BetterChromium |
18/18 passed — credentials.save, inspect, fillCredential({submit:true}) (server received the exact stored secret, page shows "Welcome back"), typed DOM value redacted to [REDACTED_PASSWORD] in the envelope, ambiguous two-form page fails closed, generateAndFillCredential → server accepted 20-char matching new/confirm → commitGeneratedCredential → pending list cleared → committed record logs in, about:blank refused |
| CLI | betterwright vault list on the disposable home |
shows both records created by the flows (persistence) |
| MCP | betterwright mcp over stdio: initialize → tools/list (browser_login present) → browser navigate → browser_login {submit:true} |
login server-verified, "Welcome back", no secret in MCP output |
Not applicable: no UI / types / docs changes; native artifacts untouched.
Video (headed BetterChromium, real-time, 2m06s)
Both scripted runs of the SDK flow: fill+submit login, redaction probe, ambiguous refusal, generate+fill+commit signup, re-login with the committed record.
- Real-time recording: https://app.devin.ai/api/presigned_proxy?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdfaWQiOiJvcmctYmQ0NTliYTUyOTRiNDEyMGJiYWRhNmE1Y2JmODIyZTUiLCJ1c2VyX2lkIjpudWxsLCJidWNrZXRfbmFtZSI6ImRldmluYXR0YWNobWVudHMiLCJidWNrZXRfa2V5IjoiYXR0YWNobWVudHNfcHJpdmF0ZS9vcmctYmQ0NTliYTUyOTRiNDEyMGJiYWRhNmE1Y2JmODIyZTUvMDlhYmQ2OTktZmFhNS00NWU4LTg1MTAtZTY5YTlhODM2NjA2IiwiaWF0IjoxNzg5OTg1MjEwLCJleHAiOjE3OTA1OTAwMTAsImZpbGVuYW1lIjoicHIyMjMtY3JlZGVudGlhbC1maWxsLXJlYWx0aW1lLm1wNCJ9.P9XOdx_lhXWhiPhNUmgwjVrzYNnj4lThfzwMRpuz0zQ
- Annotated short cut: https://app.devin.ai/api/presigned_proxy?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdfaWQiOiJvcmctYmQ0NTliYTUyOTRiNDEyMGJiYWRhNmE1Y2JmODIyZTUiLCJ1c2VyX2lkIjpudWxsLCJidWNrZXRfbmFtZSI6ImRldmluYXR0YWNobWVudHMiLCJidWNrZXRfa2V5IjoiYXR0YWNobWVudHNfcHJpdmF0ZS9vcmctYmQ0NTliYTUyOTRiNDEyMGJiYWRhNmE1Y2JmODIyZTUvYjJiZjA0NWQtNTRkMS00Y2Y3LTkyMmEtYTI5OWU1MjgyOTdkIiwiaWF0IjoxNzg5OTg1MjEwLCJleHAiOjE3OTA1OTAwMTAsImZpbGVuYW1lIjoicHIyMjMtY3JlZGVudGlhbC1maWxsLWVkaXRlZC5tcDQifQ.XF6PMeOj1e0ZA27lEGExtKa_27ic2zO3bZmwUPWIRO8
Observations (not defects in this PR)
- In headed mode BetterChromium's own "Save password?" bubble pops up after the trusted fill submits (visible in the video). This is browser-level password-manager behaviour untouched by this diff; I did not re-verify it against
main, so treat it as an optional hardening note (e.g.credentials_enable_service: falsepref /--password-store=basic), not a regression.
No fix PR needed.
Evidence-link limitation: GitHub direct video upload is not available from this tooling, so the MP4s are hosted as presigned Devin attachment links (token valid ~7 days from posting). The review sandbox's network allowlist blocks app.devin.ai, so I could not fetch the posted links back from inside the sandbox to confirm they resolve; the same files are also attached to the automation session log.
|
PR #223 @ 69afb6d reviewed E2E: no defects, no fix PR needed. Report posted at #223 (comment) (lint/typecheck, unit suite, focused suite, SDK+real vault+BetterChromium 18/18, CLI vault list, MCP browser_login; 2 unit failures are env-only Python 3.10 packager tests). Limitation: MP4s are presigned Devin attachment links (~7-day token); the sandbox allowlist blocks app.devin.ai so I couldn't re-fetch the posted links to confirm they resolve — files attached here too. This response includes attachments — view them in Devin |
Why
src/worker.tswas 8,808 lines with ~234 top-level functions. The credential fill path (vault RPC, form detection, trusted typing, generate/rotate/pending) was the largest self-contained slice, ~1,300 lines, and already had its own test file that exercised it only through the worker.What
src/credential-fill.ts:createCredentialFill(deps)returningbuildCredentials,performCredentialFill,finalizePendingCredential,recoveryFromError,vaultCall,vaultCallAtOrigin. Imports its pure helpers (credential-constants,credential-target-scan,untrusted-value,vault-capture) directly; takes only worker-owned state as deps (rpc,trackSecret,trackCredentialWriteSecrets,redactDeep,ensureSessionPage,humanClickTarget,actionTimeoutMs).src/worker.ts: 8,808 → 7,489 lines. KeepsbuildEnvelopeand thecredentialFill/credentialPendingmessage handlers, which are execution-lifecycle glue rather than credential logic.types/untouched.Verification
bun run lint,bun run typecheck,bun run check:build: cleanbun run test:unit: 1295 pass. One failure (local-aicustom endpoint validation) reproduces onmainwith this change stashed.bun test --timeout 120000 tests/node/credential-fill.test.ts: 17 pass, including the real-Chromium detection/rotation/pending-commit test.bun test --timeout 120000 tests/node/browser.test.ts: 129 pass.Follow-ups planned as separate PRs: live-view/handoff RPC handlers, CAPTCHA action dispatcher, challenge scan.