# Saved-password store

> Manage Chromium Profile passwords with Chrovia SDK: list and add credentials, observe changes, and understand the limits of clearing and importing saved passwords.

Source: https://console.getchrovia.com/en/docs/sdk-passwords

**Entitlement:** `passwords`. **API:** `chrovia.passwords`. Available only in a Provision extension Service Worker, even with `unrestrictedApi`. Observing the message channel also needs `messaging`.

## Add and list test credentials

Use a disposable Profile. This adds actual password-store rows; it is not temporary form filling:

```js
async function addTestLogin() {
  const passwords = globalThis.chrovia?.passwords;
  if (!passwords) {
    throw new Error('passwords is required in a Provision Service Worker');
  }
  await passwords.add([{
    origin: 'https://example.com/login',
    signon_realm: 'https://example.com/',
    username: 'sdk-test-user',
    password: 'replace-with-a-test-password',
  }]);
  const rows = await passwords.list();
  console.log('Saved credential count:', Array.isArray(rows) ? rows.length : 0);
}
```

Call from a deliberate test command, not on every worker wake. `add()` accepts the array directly, not `{credentials: [...]}`. Each item requires a valid `origin` URL and non-empty string `username` and `password`. `signon_realm` is optional; missing/empty uses the origin's sign-on realm. Use real HTTP(S) login URLs and a matching realm.

## Methods

| Method | Behavior |
| --- | --- |
| `add(credentials)` | Adds saved passwords; Promise resolves to `undefined` |
| `list()` | Promise of exported credential objects with `origin`, `signon_realm`, `username`, `password` |
| `empty()` | Promise resolving to `undefined`; requests clearing the Profile password store |
| `watch()` | Promise resolving to `undefined`; attaches change observation to the caller's current store |

`list()` excludes blocked entries, federated entries, empty usernames and empty passwords. Its results contain plaintext secrets: do not print the list to logs or expose it through an unrestricted popup/page command. An empty result can also reflect a read failure or unavailable store; it is not a health certificate.

`add()` does not make the saved-password list equal to the provided array and does not reliably update an existing login by site and username alone. Invalid items are skipped. Within one input array, repeated realm/username pairs are added only once. Existing logins with different origin or form details can remain as separate entries. Use a test profile and inspect the resulting list before relying on replacement behavior.

## Observe changes

Register the listener before calling `watch()` each worker start:

```js
const sdk = globalThis.chrovia;
if (sdk?.passwords && sdk.messaging) {
  sdk.messaging.on('chrovia.passwords.changed', () => {
    console.log('Password store changed; schedule a controlled refresh');
  });
  sdk.passwords.watch().catch(console.error);
}
```

The event is an empty object announcing a change, not a password payload. Call `watch()` to enable notifications; `list()`, `add()`, and subscribing to the channel alone do not enable them. Repeat `watch()` on every Provision Service Worker start so notifications resume when a profile is reopened. Worker sleep alone does not stop an existing watch.

Writes from your plugin can produce changes too. Avoid an echo loop where every change triggers a write followed by another change. Batch application-side refreshes and keep secrets in your controlled storage boundary.

## Clearing and startup import

`empty()` is destructive and separate from `add()`. Its Promise does not report whether clearing succeeded, so resolution does not prove every password was deleted. Verify the result before importing a replacement list or uploading local passwords to a managed vault; a later `add()` does not remove leftovers from a failed clear. Remember that `list()` can also return an empty result on a read failure.

Already-open login pages can continue offering old passwords after an import. Complete planned startup imports before opening login pages, or reload affected pages before testing autofill and save prompts.

Import saved passwords with `add()`; adding passwords to EP alone does not import them. For configuration-based autofill, see [injected credentials](https://console.getchrovia.com/en/docs/sdk-injected-credentials). This API does not manage TOTP or WebAuthn passkeys.
