operator-token-runbook: add a credential inventory #7

Closed
solo.ist wants to merge 3 commits from solo.ist/docs:docs/credential-inventory into main
pull from: solo.ist/docs:docs/credential-inventory
Showing only changes of commit 11ea40485c - Show all commits
+25 -12
View File
@@ -136,8 +136,8 @@ admin — just the scope.
## Credential inventory (draft, 2026-10-26) ## Credential inventory (draft, 2026-10-26)
Every credential the agent and the member-facing apps hold, compiled from the Every credential the agents and the member-facing apps hold, compiled from the
public code and docs. **No secret values appear here, only names and roles.** 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 "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 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. 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 | | `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 | | `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 | | `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 | | `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 | | `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 | | | `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 | | 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 | | 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 | | `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 | | `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 | | `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 | | `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 | | Credential | Purpose | Where it lives | Who rotates | Notes |
|---|---|---|---|---| |---|---|---|---|---|
| Cloudron agent token | Cloudron API | Agent `.env` | GM | See "The two-token split" above | | 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 |
| Gitea token | Commits, issues, PRs as `inference-bot` | Agent `.env` | GM | |
### 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 | | 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 | | 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 |
| Direct provider key (fallback) | Inference during a gateway outage | Agent `.env` | Provider account owner | Planned on co-op/support#17 | | 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 |
| LibreChat admin credential | Per-member key sync job | Agent `.env` | GM | Inferred from the job list on #17 | | `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 |
| Restic repository passphrase | Nightly encrypted backup of the agent's state | Agent host and the co-op vault | GM | Per #17 | | `HERMES_CUSTOM_API_GREENPT_AI_API_KEY` | Provider key, still present | Steward agent `.env` | Provider account owner | Confirm whether still needed; retire if not |
| Infomaniak Swiss Backup S3 keys (agent) | Backup target | Agent host | Infomaniak account owner | Per #17 | | 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) ### Accounts (not tokens, but the things tokens come from)