diff --git a/docs/VAULTWARDEN-SETUP.md b/docs/VAULTWARDEN-SETUP.md index 75fca1c..e976c85 100644 --- a/docs/VAULTWARDEN-SETUP.md +++ b/docs/VAULTWARDEN-SETUP.md @@ -1,10 +1,25 @@ # Vaultwarden Setup for Agents -Secrets store: `vault.smilepowered.org` (Vaultwarden, self-hosted). -Organization: **Clawdie** (39727691-3403-4c50-89b8-d5f24310e79c). -Collection: `agent-secrets` (94ba61b8-633c-454e-b749-f115617eeac3). +Secrets store: `vault.smilepowered.org` (Vaultwarden, self-hosted). +Organization: **Clawdie**. +Collection: `agent-secrets` (where agents' secrets are organized). -Agents use the `bw` CLI to retrieve secrets programmatically — no passwords in chat. +Agents retrieve secrets programmatically via the `clawdie-vault-fetch` helper or +the `bw` CLI — no passwords in chat. + +## Retrieval contract (important) + +Every secret is stored as **one login item whose ITEM NAME is exactly the env +var name** (e.g. `ANTHROPIC_API_KEY`, `OPENROUTER_API_KEY`), with the **value in +the password field**. This is what `clawdie-vault-fetch` depends on: + +- `bw get password ` returns the value raw — no `jq` needed. +- Fetch is **fail-closed on ambiguity**: if two visible items share a name, the + fetch errors out instead of guessing. **Item names must therefore be unique** + across the agent account's visible vault (not just within `agent-secrets`), so + do not reuse a name in a personal collection. +- The helper does **not** scope by collection ID. The `agent-secrets` collection + is for operator organization; uniqueness is enforced at fetch time by name. > **Note:** `bw` CLI only accepts **personal** API keys (from Account Settings). > Organization API keys are for the REST API, not the CLI. Do not use them here. @@ -24,11 +39,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`. @@ -44,30 +61,35 @@ operator must create the user account and deliver the master password out-of-ban ## Verification Test -After onboarding, verify with this smoke test — run from the agent host: +After onboarding, verify with this smoke test — run from the agent host. The +helper does the login/unlock/lock lifecycle and exits non-zero on failure. + +```sh +# 1. Preferred: use the helper end-to-end. It reads +# ~/.config/vault-bootstrap.env (0600) and prints KEY=VALUE lines for every +# key it resolved. Exit 3 = no bootstrap file (skip); 1 = broken; 4 = no bw. +clawdie-vault-fetch + +# 2. Resolve one specific key and write it into .env (0600, upsert): +clawdie-vault-fetch --write-env ~/.env --keys "OPENROUTER_API_KEY" +``` + +If at least one `KEY=VALUE` line prints, onboarding is complete — the helper +locks the vault on exit. To verify the raw `bw` path instead (e.g. the helper is +not installed yet): ```sh -# 1. Load bootstrap env without echoing secrets. set -a . ~/.config/vault-bootstrap.env set +a - -# 2. Configure, login, unlock, and capture a raw session token. bw config server https://vault.smilepowered.org bw login --apikey BW_SESSION="$(bw unlock --raw --passwordenv BW_PASSWORD)" -export BW_SESSION - -# 3. List items in agent-secrets collection. -bw list items --session "$BW_SESSION" --collectionid 94ba61b8-633c-454e-b749-f115617eeac3 >/dev/null - -# 4. Retrieve the hermes-debby Forgejo username. -bw list items --session "$BW_SESSION" --search "hermes-debby" | jq -r '.[0].login.username' - -# Expected output: hermes-debby +bw get password OPENROUTER_API_KEY --session "$BW_SESSION" # prints the value +bw lock ``` -If the username resolves: Vaultwarden onboarding complete. Lock the vault (`bw lock`). +If the value resolves: Vaultwarden onboarding complete. ## Setup @@ -88,6 +110,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` @@ -120,10 +143,18 @@ bw unlock --passwordenv BW_PASSWORD ### 5. Retrieve a secret +Fetch by item **name** (the env var name); the value lives in the password +field. This is the same path `clawdie-vault-fetch` uses: + ```sh -bw list items --session "$BW_SESSION" --search "hermes-debby" | jq '.[0].login' -# or get by ID -bw get item --session "$BW_SESSION" +bw get password OPENROUTER_API_KEY --session "$BW_SESSION" +``` + +To upsert resolved secrets into your `.env` without copy-paste, prefer the +helper: + +```sh +clawdie-vault-fetch --write-env ~/.env ``` ### 6. Lock when done @@ -134,8 +165,8 @@ bw lock ## Current items in agent-secrets -| Name | Type | Purpose | -|------|------|---------| +| Name | Type | Purpose | +| -------------------- | ----- | -------------------------------------------------------- | | hermes-debby Forgejo | login | Hermes's code.smilepowered.org password (browser access) | ## Rules