--- name: credential-manager description: Read this before any login, signup, password change, or checkout so the right credential source is used in the right order without ever exposing a secret. autoInject: keywords: ["login", "log in", "sign in", "sign-in", "sign up", "signup", "password", "credential", "checkout", "payment", "2fa", "mfa"] --- # Credential manager Use metadata to choose an account, then let the password manager detect and fill the form. Never fetch, inspect, transform, or print a stored secret. ## Source order Work down this ladder; stop at the first source that works. 1. **A configured external manager.** If the operator prompt explicitly names 1Password or Bitwarden, use its inline menu and read the matching provider pack first (`../1password/SKILL.md`, `../bitwarden/SKILL.md`). 2. **BetterWright's built-in vault.** `credentials.list()` returns matching metadata only: id, username, label, category, saved URL, and match mode. Filter with `credentials.list({text, category})`. If one account clearly fits the task, call `credentials.fill({id, submit: true})`. BetterWright detects the visible form and resolves/types the secret internally. MCP/Pi's `browser_login` and the SDK's `fillCredential` use the same path. 3. **The page itself.** Focus the username field with `human.click` and re-snapshot; a session may already exist, an SSO button may be present, or the user's own password manager may surface. 4. **Ask the user** through the host's question mechanism, offering the accounts you found as masked options (e.g. "account ending in 999"). This is the last resort, not the first. ## Account choice and staged login - Search before filling. One clear match may be used directly. If several plausible accounts remain and the task does not disambiguate them, ask with usernames/labels only; never mention a secret. - On a username-first flow, enter the selected record's public username and advance. On the password stage call `credentials.fill({id, submit: true})`; password-only pages are detected. - Detection uses autocomplete/type/label/form context. If it reports multiple plausible forms, scope explicit `usernameSelector`, `passwordSelector`, `currentPasswordSelector`, `confirmPasswordSelector`, or `submitSelector` from a fresh snapshot. For an ambiguous rotation, pin current, new, and confirmation password roles together. Do not guess selectors before detection fails. ## Signup and password rotation 1. Call `credentials.generateAndFill({username, submit: true})`. Generation returns only an opaque pending id; the encrypted provisional entry is not an active saved login yet. 2. Verify the site's visible success state. A clicked button or request alone is not proof. 3. On success, call `credentials.commitGenerated({pendingId})`. On rejection or abandonment, call `credentials.discardGenerated({pendingId})`. If generation fails but returns `pendingCredential`, do not generate again. Inspect the visible site outcome, then commit or discard that exact recovery id. After a complete host restart with no returned id, revisit the signup site and call `credentials.listPending()`. Use its secret-free username, label, and timestamps to identify the attempt; never guess or auto-pick among several. For rotation, pass the existing credential `id` to `generateAndFill`. Commit only after the site confirms the change; commit updates that item instead of creating a duplicate. Rotation preserves its URL scope, so update `matchMode` separately before rotating when needed. Choose an existing username/email when the site allows it; never invent an address. ## Rules - An empty `credentials.list()` means no enabled item matches this site under its URL policy. Fall through the ladder instead of searching unrelated credentials. - Never read, print, encode, or transmit a password, card number, or one-time secret. Snapshots and results redact password inputs; keep it that way: no `inputValue()`, `input.value`, `evaluate`, console, or network probes on secret fields. - A failed fill ("info isn't correct") means the stored secret may be stale: try the next source on the ladder, then ask the user — never brute-force variants. - Save a task-supplied credential only when the user asks to remember it, and only after the site accepts it.