# adom-desktop credential vault for HTTP Basic Auth popups

## Problem

When `pup` navigates to a subdomain that issues an HTTP **Basic Auth** challenge (e.g. `nxp.componentsearchengine.com`, `mouser.componentsearchengine.com`, NXP design portals, some IBM/HP/Renesas docs), Chrome shows a system-level popup that lives **outside the page DOM**. It can't be interacted with via `browser_eval`. The user has to manually type the same email + password every time. Real Adom-user feedback: *"typing into these popup windows is heinous."*

## Why we can't just `browser_eval` past it

The popup is a Chrome native dialog (HTML lives in browser chrome, not the rendered page). Its DOM is inaccessible from the controlled page context. Puppeteer **does** offer `page.authenticate({username, password})` which intercepts basic-auth challenges before they show — but `pup` doesn't currently expose that API.

## Desired behavior

Add a credential vault to `pup` that:

1. Stores `{host_pattern → {username, password}}` mappings in an encrypted local file (`<adom-desktop>/plugins/puppeteer/credentials.enc`, AES-256 with a key derived from the user's machine ID + a one-time passphrase).
2. Calls `page.authenticate(creds)` on every new page in a session, with creds matched by URL hostname.
3. Exposes new CLI commands so users / Claude can manage entries:
   - `adom-desktop credential_set '{"host":"*.componentsearchengine.com","username":"user@example.com","password":"..."}'`
   - `adom-desktop credential_list` — returns list of host patterns + usernames (NEVER passwords)
   - `adom-desktop credential_delete '{"host":"..."}'`
4. Returns `password_required` when no entry matches and a basic-auth challenge fires, so chip-fetcher can prompt the user once and then store.

## Wire format

```jsonc
// adom-desktop credential_set '<json>'
{
  "host": "*.componentsearchengine.com",   // glob, matched against new-page URL host
  "username": "...",
  "password": "..."                         // never echoed back via list/get
}
```

```jsonc
// adom-desktop credential_list
{
  "credentials": [
    { "host": "*.componentsearchengine.com", "username": "user@example.com" }
    // password omitted
  ]
}
```

## Files to look at

- `src-tauri/plugins/puppeteer/index.js` — `getOrLaunchBrowser()` is where new pages are created. Hook `page.on('targetcreated')` (or wrap `addTabToSession`) to inject `page.authenticate(creds)` when host matches.
- New file: `src-tauri/plugins/puppeteer/credential_vault.js` — encrypted storage, glob host matching, lookup helper.
- `cli/src/commands.rs` — add `credential_set` / `credential_list` / `credential_delete` subcommands routed through the existing relay.

## Encryption

Use **OS keychain / DPAPI** (Windows: `keytar` npm or `windows-credential-manager`; macOS: `security add-internet-password`; Linux: libsecret) so the user's OS-level lock screen protects the secrets. Don't reinvent encryption.

## Acceptance test

```bash
# 1. Set creds for CSE family
adom-desktop credential_set '{"host":"*.componentsearchengine.com","username":"user@example.com","password":"<paste>"}'

# 2. Navigate to nxp.componentsearchengine.com — basic-auth popup MUST NOT appear; page just loads
adom-desktop browser_navigate '{"sessionId":"chip-fetcher","url":"https://nxp.componentsearchengine.com/preview_newDesign.php?..."}'
adom-desktop browser_eval '{"sessionId":"chip-fetcher","expr":"document.title"}'  # should be SamacSys Part Preview, not "Sign in"

# 3. List shows username but NEVER password
adom-desktop credential_list  # → [{host:"*.componentsearchengine.com", username:"user@example.com"}]
```

## Bonus: import from existing browser password manager

After the basic plumbing, expose:
```
adom-desktop credential_import_chrome
```
which reads the user's primary Chrome profile's `Login Data` SQLite (DPAPI-decrypted on Windows), shows them which entries to import, and stores the picked ones. One paste, never type again.

## Why this matters

The chip-fetcher skill instructs harvesting CAD across 5+ vendors (TI / ST / ADI / NXP / Microchip / etc.), most of which route through Component Search Engine. Each subdomain has its own basic-auth challenge. Without a credential vault, the user types their CSE password 10× per session. This is the highest-impact UX win in chip-fetcher right now and is the natural companion to the `pull_file` streaming fix.
