Document the Vaultwarden fetch contract #12

Merged
clawdie merged 1 commit from secrets-out-of-the-box into main 2026-06-23 06:57:44 +02:00

View file

@ -24,11 +24,13 @@ access Vaultwarden, but those credentials can't be stored in Vaultwarden itself
as the only copy.
**Operator's role:**
1. Create a Vaultwarden user account for the agent.
2. Invite the user to the Clawdie organization with access to `agent-secrets`.
3. Share the master password via a secure channel (file drop, not chat).
**Agent's role:**
1. Generate personal API key: Account Settings → Security → Keys → View API Key.
2. Write `BW_CLIENTID` (starts with `user.`), `BW_CLIENTSECRET`, and
`BW_PASSWORD` to a 0600 bootstrap file: `~/.config/vault-bootstrap.env`.
@ -88,6 +90,7 @@ bw config server https://vault.smilepowered.org
Generate your personal API key: Account Settings → Security → Keys → View API Key.
You'll receive:
- `BW_CLIENTID` (starts with `user.`)
- `BW_CLIENTSECRET`
@ -132,10 +135,64 @@ bw get item <item-id> --session "$BW_SESSION"
bw lock
```
## Runtime fetch: `clawdie-vault-fetch`
The manual flow above is the operator/agent CLI path. For a host to pull its own
provider keys **out of the box**, the image ships a small language-neutral
helper, `clawdie-vault-fetch` (`/usr/local/bin/`), that the post-install setup
flow shells out to and the live USB can run directly. It depends only on `bw`
no node module, no `jq`.
### Item-naming convention (the contract)
For a secret to be auto-fetchable, store it in `agent-secrets` as a **login item
whose name is exactly the env var name**, with the value in the **password
field**:
| Item name | Field | Becomes |
| -------------------- | -------- | ---------------------- |
| `ANTHROPIC_API_KEY` | password | `ANTHROPIC_API_KEY=…` |
| `OPENAI_API_KEY` | password | `OPENAI_API_KEY=…` |
| `OPENROUTER_API_KEY` | password | `OPENROUTER_API_KEY=…` |
| `ZAI_API_KEY` | password | `ZAI_API_KEY=…` |
The default key set mirrors clawdie-ai's `PROVIDER_KEY_BY_PROVIDER` (anthropic,
openai, openrouter, zai, deepseek, gemini, groq). `bw get password <NAME>`
returns the raw value, so no JSON parsing is involved.
### Bootstrap drop (the one secret that can't live in the vault)
The helper reads `~/.config/vault-bootstrap.env` (mode 0600) for the headless
credentials — exactly the file from the [Bootstrap Flow](#bootstrap-flow) above:
```sh
BW_CLIENTID=user....
BW_CLIENTSECRET=...
BW_PASSWORD=<master-password>
```
**No bootstrap file → the helper exits cleanly and does nothing**, so a host with
no vault access still uses the manual setup wizard. That is the floor; the vault
fetch only ever adds.
### Usage
```sh
clawdie-vault-fetch # print KEY=VALUE lines to stdout
clawdie-vault-fetch --write-env FILE # upsert results into FILE (0600), keys preserved
clawdie-vault-fetch --bootstrap FILE # explicit bootstrap env file
clawdie-vault-fetch --keys "A B C" # override the key-name list
```
Exit codes let a caller tell "skip" from "broken": `0` ran cleanly · `1` vault
configured but login/unlock/fetch failed · `3` no bootstrap config (fall back to
manual) · `4` `bw` not installed. The helper always `bw lock`s on exit and never
logs secret values.
## Current items in agent-secrets
| Name | Type | Purpose |
|------|------|---------|
| Name | Type | Purpose |
| -------------------- | ----- | -------------------------------------------------------- |
| hermes-debby Forgejo | login | Hermes's code.smilepowered.org password (browser access) |
## Rules