diff --git a/operator-token-runbook.md b/operator-token-runbook.md index c047a78..86496a6 100644 --- a/operator-token-runbook.md +++ b/operator-token-runbook.md @@ -136,8 +136,8 @@ admin — just the scope. ## Credential inventory (draft, 2026-10-26) -Every credential the agent and the member-facing apps hold, compiled from the -public code and docs. **No secret values appear here, only names and roles.** +Every credential the agents and the member-facing apps hold, compiled from the +public code and docs, corrected against what the agent holds (PR #7 review). **No secret values appear here, only names and roles.** "Where it lives" and "Who rotates" are filled in where the docs say; blank cells are for the operator to complete. When rotating anything, check every row that names the same credential: several are held by more than one app. @@ -149,7 +149,7 @@ row that names the same credential: several are held by more than one app. | `CLOUDRON_TOKEN` (portal token) | Create users and groups, invite links | Portal app env | GM | See "The two-token split" above | | `OC_PERSONAL_TOKEN` | Read members and orders from Open Collective GraphQL | Portal app env | The Open Collective account that minted it | Needs the `email` scope (see below). Currently a personal token; a co-op-owned OC account would make it a co-op credential | | `WEBHOOK_TOKEN` | Secret in the Open Collective webhook URL | Portal app env, and the webhook URL on Open Collective | GM | Rotating means re-creating the webhook on OC as well | -| `LITELLM_MASTER_KEY` | Create gateway teams and keys for members | Portal app env (copy of the gateway's) | GM | Also held by the gateway; rotate both together | +| `LITELLM_MASTER_KEY` | Create gateway teams and keys for members | Portal app env (copy of the gateway's) | GM | Three holders: portal, gateway, steward agent. Rotate all together | | `LITELLM_DB_*` | Read spend logs from the gateway database | Portal app env | Cloudron (addon) | Postgres credentials for the gateway's database | | `MATRIX_BOT_TOKEN` | `@inference-bot:inference.coop` admin account: invites, space membership | Portal app env | GM | The account has no password; the token is the only credential | | `LOOMIO_API_KEY`, `LOOMIO_B3_KEY` | Forum (Loomio) membership sync | Portal app env | GM | | @@ -163,25 +163,38 @@ row that names the same credential: several are held by more than one app. | Credential | Purpose | Where it lives | Who rotates | Notes | |---|---|---|---|---| -| `LITELLM_MASTER_KEY` | Gateway admin | `/app/data/.master_key`, exported into the litellm process by `start.sh` | GM | Also held by the portal (above) and the audio keep-alive job | +| `LITELLM_MASTER_KEY` | Gateway admin | `/app/data/.master_key`, exported into the litellm process by `start.sh` | GM | Also held by the portal (above), the steward agent (below) and the audio keep-alive job | | Salt key (`SALT_KEY_FILE`) | Encrypts provider keys stored in the gateway database | `/app/data` | GM | Losing it means re-entering every provider key | | `TINFOIL_API_KEY` | Provider account | Gateway app env | Provider account owner | Billing lives at the provider | | `GREENPT_API_KEY` | Provider account | Gateway app env | Provider account owner | Billing lives at the provider | | `REGOLO_API_KEY` | Provider account | Gateway app env | Provider account owner | Billing lives at the provider | | `CLOUDRON_POSTGRESQL_*`, `CLOUDRON_REDIS_*` | Database and cache | Cloudron addons | Cloudron | Managed by the platform | -### Agent (inferencebot, on the agent VPS) +### Chat (LibreChat, `chat.inference.coop`) | Credential | Purpose | Where it lives | Who rotates | Notes | |---|---|---|---|---| -| Cloudron agent token | Cloudron API | Agent `.env` | GM | See "The two-token split" above | -| Gitea token | Commits, issues, PRs as `inference-bot` | Agent `.env` | GM | | +| LibreChat encryption keys and app secrets | App secrets; the per-member key sync runs in the app's own Cloudron scheduler | App data directory | GM | Not held by the agent | + +### Agents (on the agent host) + +Exact file paths are deliberately not listed; "agent `.env`" is the right +granularity for the public half. Highest privilege first. + +| Credential | Purpose | Where it lives | Who rotates | Notes | +|---|---|---|---|---| +| Gateway master key (`GW_MASTER_KEY`) | Admin over every gateway team, key and spend record | Steward agent `.env` | GM | **Third holder**, with the portal and the gateway. The row most in need of coordinated rotation | +| `MATRIX_LOCAL_BOT_TOKEN` | The `@inference-bot:inference.coop` automation account: room administration in every co-op room | Steward agent `.env` | GM | Same account as the portal's `MATRIX_BOT_TOKEN`; confirm whether it is the same token | +| Cloudron agent token | Cloudron API | Steward agent `.env` | GM | See "The two-token split" above | +| `REGISTRY_BUILD_TOKEN` (and its username) | Image build and push for the custom apps | Steward agent `.env` | GM | Moves to CI (co-op/support#30); the agent stops holding it then | +| Gitea token | Commits, issues, PRs as `inference-bot` | Steward agent `.env` | GM | | | Matrix access token (`@inferencebot:inference.coop`) | Reading and posting in rooms | Agent host, with its E2EE key store | GM | The off switch in [Working with the agent](working-with-the-agent.md) revokes this second | -| Gateway virtual key | The agent's own inference | Agent `.env` | GM | Model allowlist and budget live on this key; the off switch revokes it first | -| Direct provider key (fallback) | Inference during a gateway outage | Agent `.env` | Provider account owner | Planned on co-op/support#17 | -| LibreChat admin credential | Per-member key sync job | Agent `.env` | GM | Inferred from the job list on #17 | -| Restic repository passphrase | Nightly encrypted backup of the agent's state | Agent host and the co-op vault | GM | Per #17 | -| Infomaniak Swiss Backup S3 keys (agent) | Backup target | Agent host | Infomaniak account owner | Per #17 | +| Steward agent's gateway key (`api:info@inference.coop:inferencebots`) | The steward agent's own inference | Steward agent `.env` | GM | Today: empty model allowlist and no per-key budget; draws on the co-op account team's budget. To be scoped like the per-agent keys below. The off switch revokes this first | +| Per-agent gateway keys (`infrastructure-bot`, later agents) | That agent's inference | That agent's `.env` | GM | Model allowlist and monthly budget enforced at the gateway | +| `GREENPT_FALLBACK_API_KEY` | Direct-to-provider fallback inference during a gateway outage (live since 2026-10-26) | Steward agent `.env` | Provider account owner | Rotation-coupled to the gateway's `GREENPT_API_KEY`: rotate one without the other and the fallback silently breaks. A dedicated key is the cleaner end state | +| `HERMES_CUSTOM_API_GREENPT_AI_API_KEY` | Provider key, still present | Steward agent `.env` | Provider account owner | Confirm whether still needed; retire if not | +| Restic repository passphrase | Nightly encrypted backup of the agent's state | Agent host and the co-op vault | GM | | +| Infomaniak Swiss Backup S3 keys (agent) | Backup target | Agent host | Infomaniak account owner | | ### Accounts (not tokens, but the things tokens come from)