# ops-warden routing catalog — POINTER LAYER # # This file is a machine-readable index of NetKingdom credential needs. It tells a # worker WHICH subsystem owns a need and WHERE the authoritative doc is. It is NOT # a second copy of any subsystem's procedure. # # No-double-source rule (binding — docs/adr/ADR-0001-catalog-is-a-pointer-layer.md, # owner: ops-warden; origin workplans/WARDEN-WP-0010-access-routing-charter.md): # - For any subsystem ops-warden does not own, an entry carries identifiers + # pointers ONLY: owner_repo, subsystem, wiki_ref, canon_ref, need_keywords. # - Authored procedure (a `steps:` block and `cert_command:`) is allowed ONLY on # entries with `warden_executes: true` — i.e. the SSH certificate lane, the one # lane ops-warden owns. # - A CI/test (WARDEN-WP-0011 T5) FAILS any non-SSH entry that carries a `steps` # block, and checks that every `wiki_ref` anchor resolves to a real section. # - No secret material in this file, ever. # # Field reference: # id kebab-case stable identifier (lookup key) # title human-readable need # need_keywords tokens for `warden route find` keyword matching # owner_repo repo/subsystem that owns the procedure # subsystem platform component a worker acts on # warden_executes true only for the SSH lane; false everywhere else # wiki_ref anchor into an in-repo wiki section (authoritative restatement) # canon_ref upstream net-kingdom doc the wiki section tracks # reviewed date this pointer was last checked against canon (YYYY-MM-DD) # status active (surfaced by default) | draft (hidden unless --all) # steps ONLY when warden_executes: true # cert_command ONLY when warden_executes: true # delegation WP-0030 register. mode: native | interim | permanent. # intended_owner required unless permanent; blocked_on required # when interim. Absence is implicit interim with unknown owner. version: 1 entries: - id: ssh-cert-host-access title: Short-lived SSH certificate for host / ops reachability need_keywords: [ssh, certificate, cert, host, access, sign, adm, agt, atm, reachability, ops] owner_repo: ops-warden subsystem: ops-warden warden_executes: true wiki_ref: wiki/AccessRouting.md#issue-vs-route canon_ref: net-kingdom/docs/platform-identity-security-architecture.md#operational-ssh-path reviewed: "2026-06-18" status: active delegation: mode: permanent reviewed: "2026-08-15" cert_command: "warden sign --pubkey " steps: - "Confirm the actor is in inventory (`warden inventory list`); add with `warden inventory add` if not — see wiki/ActorInventoryPatterns.md." - "Confirm the backend is configured (`warden status`) — local CA for labs, vault for production." - "Sign: `warden sign --pubkey ` — cert is written to stdout (the cert_command contract)." - "TTL is enforced per actor type: adm 48h / agt 24h / atm 8h. No long-lived keys." - id: ops-warden-warden-sign-token title: Scoped OpenBao token for ops-warden SSH signing (warden-sign) need_keywords: [vault_token, vault, token, warden-sign, warden, ops-warden, signing, sign, smoke, flex-auth, credential, broker, lease, openbao, ssh, production] owner_repo: railiance-platform subsystem: OpenBao credential broker warden_executes: false wiki_ref: wiki/playbooks/ops-warden-warden-sign-token.md#worker-checklist canon_ref: net-kingdom/docs/platform-identity-security-architecture.md reviewed: "2026-07-01" status: active delegation: mode: native intended_owner: railiance-platform reviewed: "2026-08-15" # Concrete broker lane — RAILIANCE-WP-0005 pilot (live 2026-07-01): # credential exec injects VAULT_TOKEN only into the child process; ops-warden # issues SSH certs and never mints or holds OpenBao tokens. auth_method: "railiance-platform credential broker (issuer via OPENBAO_TOKEN_FILE for apply; child tokens via grant)" path_template: "credential-grants/catalog.yaml grant ops-warden/warden-sign" fetch_command: "scripts/credential.py request --grant ops-warden/warden-sign --purpose ops-warden-sign --ttl 15m" policy_ref: "flex-auth optional preflight per grant catalog" exec_owner: railiance-platform exec_command: "scripts/credential.py exec --grant ops-warden/warden-sign --ttl 15m -- " pointer_command: "make credential-exec-ops-warden-smoke" rotation: method: rotate owner: railiance-platform automatable: true steps: - "This lane vends a short-lived (15m) child VAULT_TOKEN — routine renewal is just re-running `credential.py exec`; the token auto-expires, nothing to revoke." - "To rotate the underlying grant/issuer: railiance-platform edits `credential-grants/catalog.yaml` for `ops-warden/warden-sign` (scope/policy) and re-mints the issuer token behind OPENBAO_TOKEN_FILE." - "Verify capabilities-safe: `make credential-exec-ops-warden-smoke` and a `bao token capabilities` check on ssh/sign/{adm,agt,atm}-role (never read a value)." - id: openbao-api-key title: API key, DB credential, or dynamic lease need_keywords: [api, key, secret, database, db, password, token, lease, openbao, vault, kv, dynamic, credential, npm, npm_auth_token, registry] owner_repo: railiance-platform subsystem: OpenBao warden_executes: false wiki_ref: wiki/CredentialRouting.md#routing-table canon_ref: net-kingdom/docs/platform-identity-security-architecture.md reviewed: "2026-06-27" status: active delegation: mode: interim intended_owner: secrets-engine blocked_on: "secrets-engine has not confirmed whether exec --catalog generalizes over arbitrary OpenBao lanes (asked 2026-08-11, msg 7d55d332)" reviewed: "2026-08-11" # Structured handoff (WP-0014) — reference example. Templates only, no values. # ops-warden does not own this secret; it advises and (exec_capable) proxies the # fetch *as the caller* via `warden access`, never holding or persisting the value. auth_method: "key-cape OIDC → bao login -method=oidc role=" path_template: "platform/workloads///" fetch_command: "bao kv get -field= " policy_ref: "flex-auth check secret.read:" exec_capable: true rotation: method: rotate owner: railiance-platform automatable: false steps: - "Generic template lane — rotate per the concrete workload's own catalog entry when one exists." - "Provider re-mint (or OpenBao dynamic-secret rotation): mint a fresh value at the source, then `bao kv put =@file` (value from a mode-0600 file, never on argv)." - "For dynamic-lease secrets, revoke the old lease (`bao lease revoke`) instead of a KV put." - "Verify capabilities-safe (`bao token capabilities` on the data path); notify consumers to re-fetch." - id: whynot-design-npm-publish title: whynot-design npm publish token (@whynot/design → coulomb Gitea registry) need_keywords: [whynot-design, whynot, npm, publish, npm_auth_token, gitea, registry, coulomb, package] owner_repo: railiance-platform subsystem: OpenBao warden_executes: false wiki_ref: wiki/playbooks/whynot-design-npm-publish.md#worker-checklist canon_ref: net-kingdom/docs/platform-identity-security-architecture.md reviewed: "2026-06-29" status: active delegation: mode: native intended_owner: secrets-engine reviewed: "2026-08-15" # Concrete, owner-confirmed lane — railiance-platform CCR-2026-0001 (commit 8f617fc): # status=active, access_frontdoor.readiness=ready, resolvable=true; positive fetch # passed and negative (non-whynot) login denied. Zero-placeholder fetch: an automated # caller can `warden access whynot-design-npm-publish --exec -- npm publish` directly. # The path was corrected to the `coulomb` tenant — the whynot-design/whynot-design/… # form is superseded; do not reintroduce it. auth_method: "bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read" path_template: "platform/workloads/coulomb/whynot-design/npm-publish" fetch_command: "bao kv get -field=NPM_AUTH_TOKEN platform/workloads/coulomb/whynot-design/npm-publish" policy_ref: "flex-auth check secret.read:whynot-design" exec_capable: true lane: secret # Owner-native exec front door (WP-0019, secrets-engine SECRETS-WP-0003, decision # e6381a56): route-primary, proxy-fallback. The secrets-engine exec is the primary # path; warden access --fetch/--exec remains a transparent fallback. exec_owner: secrets-engine exec_command: "secrets-engine exec --catalog whynot-design-npm-publish -- " pointer_command: "secrets-engine route whynot-design-npm-publish --json" rotation: method: rotate owner: railiance-platform automatable: false steps: - "In the coulomb Gitea/Forgejo registry, revoke the current @whynot/design publish token and generate a new one (scope: package read/write) for the whynot-design publish identity." - "Write it back: `bao kv put platform/workloads/coulomb/whynot-design/npm-publish NPM_AUTH_TOKEN=@file` (value from a mode-0600 file)." - "Verify capabilities-safe, then confirm publish works via `secrets-engine exec --catalog whynot-design-npm-publish -- npm whoami` (value used, not printed)." - id: flex-auth-policy-check title: Authorization decision — may this actor perform this action need_keywords: [authorization, policy, permission, allow, deny, may, flex-auth, topaz, pdp, decision] owner_repo: flex-auth subsystem: flex-auth warden_executes: false wiki_ref: wiki/CredentialRouting.md#quick-decision-tree canon_ref: net-kingdom/docs/responsibility-map.md reviewed: "2026-06-18" status: active delegation: mode: native intended_owner: flex-auth reviewed: "2026-08-15" - id: key-cape-oidc-login title: Interactive login, OIDC token, or MFA need_keywords: [login, oidc, identity, mfa, token, jwt, sso, keycloak, key-cape, iam, claims, authenticate, signin] owner_repo: key-cape subsystem: key-cape / Keycloak warden_executes: false wiki_ref: wiki/CredentialRouting.md#quick-decision-tree canon_ref: net-kingdom/docs/canon/standards/iam-profile_v0.2.md reviewed: "2026-06-27" status: active delegation: mode: interim intended_owner: secrets-engine blocked_on: "secrets-engine has not confirmed whether exec --catalog generalizes over arbitrary OpenBao lanes (asked 2026-08-11, msg 7d55d332)" reviewed: "2026-08-11" # Login lane (WP-0014 T4) — interactive auth bootstrap, not a secret read. No # secret-read gate (you have no identity yet) and no caller-auth precheck (the # point is to obtain one). warden runs it interactively as the caller and never # captures the resulting token — the owner tool writes it to the caller's store. lane: login auth_method: "browser OIDC via key-cape / Keycloak" fetch_command: "bao login -method=oidc role=" exec_capable: true - id: ops-bridge-tunnel title: SSH tunnel or port forward need_keywords: [tunnel, port, forward, bridge, ops-bridge, reverse, transport, ssh-tunnel, cert_command] owner_repo: ops-bridge subsystem: ops-bridge warden_executes: false wiki_ref: wiki/playbooks/ops-bridge-tunnel-cert.md#migration-checklist canon_ref: net-kingdom/docs/platform-identity-security-architecture.md#operational-ssh-path reviewed: "2026-06-24" status: active delegation: mode: native intended_owner: ops-bridge reviewed: "2026-08-15" - id: railiance-infra-principals title: Host SSH principal file or force-command deployment need_keywords: [principal, auth_principals, force-command, host, sshd, hardening, railiance-infra, ansible] owner_repo: railiance-infra subsystem: railiance-infra warden_executes: false wiki_ref: wiki/CredentialRouting.md#routing-table canon_ref: net-kingdom/docs/responsibility-map.md reviewed: "2026-06-18" status: active delegation: mode: native intended_owner: railiance-infra reviewed: "2026-08-15" - id: inter-hub-bootstrap-ssh title: Inter-Hub bootstrap SSH envelope need_keywords: [inter-hub, interhub, bootstrap, ops-hub, agt-interhub-bootstrap, envelope, force-command, CUST-WP-0049] owner_repo: ops-warden subsystem: ops-warden + railiance-infra warden_executes: false wiki_ref: wiki/InterHubBootstrapAccessLane.md#worker-checklist canon_ref: net-kingdom/docs/platform-identity-security-architecture.md#operational-ssh-path reviewed: "2026-06-24" status: active delegation: mode: native intended_owner: railiance-infra reviewed: "2026-08-15" - id: activity-core-issue-sink title: activity-core IssueSink → issue-core REST emission need_keywords: [activity-core, issue-sink, issue-core, emission, issue_core_url, issue_core_api_key, tasks, ingest, rest, issuesink] owner_repo: activity-core subsystem: activity-core + issue-core warden_executes: false wiki_ref: wiki/playbooks/activity-core-issue-sink.md#worker-checklist canon_ref: net-kingdom/docs/platform-identity-security-architecture.md reviewed: "2026-06-18" status: active delegation: mode: native intended_owner: activity-core reviewed: "2026-08-15" - id: issue-core-ingestion-api-key title: issue-core ingestion API key (OpenBao KV + ESO) need_keywords: [issue-core, ingestion, api, key, openbao, issue_core_api_key, eso, external-secrets] owner_repo: railiance-platform subsystem: OpenBao + issue-core + activity-core warden_executes: false wiki_ref: wiki/playbooks/issue-core-ingestion-api-key.md#worker-checklist canon_ref: net-kingdom/docs/platform-identity-security-architecture.md reviewed: "2026-07-02" status: active delegation: mode: interim intended_owner: secrets-engine blocked_on: "secrets-engine has not confirmed whether exec --catalog generalizes over arbitrary OpenBao lanes (asked 2026-08-11, msg 7d55d332)" reviewed: "2026-08-11" # Concrete, owner-confirmed lane — railiance-platform CCR-2026-0002 / RAILIANCE-WP-0009 # (promoted 2026-07-02): policy workload-kv-read-issue-core-runtime and k8s auth role # external-secrets-issue-core applied; ExternalSecret issue-core/issue-core-runtime # SecretSynced; positive + negative access verified with OpenBao audit evidence. # Production consumer is ESO; warden access proxies reads as the caller (caller's own # OpenBao authority) and never holds the value. auth_method: "caller's own OpenBao token (operator OIDC via key-cape, or a token carrying workload-kv-read-issue-core-runtime)" path_template: "platform/workloads/issue-core/issue-core/issue-core-runtime" fetch_command: "bao kv get -field=ISSUE_CORE_API_KEY platform/workloads/issue-core/issue-core/issue-core-runtime" policy_ref: "flex-auth check secret.read:issue-core" exec_capable: true lane: secret rotation: method: rotate owner: railiance-platform automatable: false steps: - "Mint a new issue-core ingestion API key at the issue-core admin surface; keep the old one until consumers cut over." - "`bao kv put platform/workloads/issue-core/issue-core/issue-core-runtime ISSUE_CORE_API_KEY=@file` (value from a mode-0600 file)." - "ESO re-syncs ExternalSecret issue-core/issue-core-runtime; roll consumers, then revoke the old key at the source." - "Verify capabilities-safe on the data path (`bao token capabilities`); never read the value to confirm." - id: reuse-surface-hub-write-token title: reuse-surface federation hub write bearer token need_keywords: [reuse-surface, reuse_surface, hub, register, federation, write, token, bearer, REUSE_SURFACE_TOKEN, REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET, reuse.coulomb.social] owner_repo: railiance-platform subsystem: OpenBao + reuse-surface warden_executes: false wiki_ref: wiki/playbooks/reuse-surface-hub-write-token.md#worker-checklist canon_ref: reuse-surface/specs/FederationHubAPI.md reviewed: "2026-07-07" status: active delegation: mode: interim intended_owner: secrets-engine blocked_on: "secrets-engine has not confirmed whether exec --catalog generalizes over arbitrary OpenBao lanes (asked 2026-08-11, msg 7d55d332)" reviewed: "2026-08-11" # Concrete, owner-confirmed lane — railiance-platform CCR-2026-0005 / RAILIANCE-WP-0011 # (promoted 2026-07-07): policy workload-kv-read-reuse-surface-runtime; ExternalSecret # reuse/reuse-surface-runtime SecretSynced to reuse-surface-env on Railiance01; # positive + negative access verified. Production consumer is ESO; warden access # proxies reads as the caller and never holds the value. auth_method: "caller's own OpenBao token (operator OIDC via key-cape, or a token carrying workload-kv-read-reuse-surface-runtime)" path_template: "platform/workloads/reuse/reuse-surface/runtime-secrets" fetch_command: "bao kv get -field=REUSE_SURFACE_TOKEN platform/workloads/reuse/reuse-surface/runtime-secrets" policy_ref: "flex-auth check secret.read:reuse" exec_capable: true resolvable: true lane: secret rotation: method: rotate owner: railiance-platform automatable: false steps: - "Generate a new reuse-surface federation hub write bearer token at reuse.coulomb.social; if the Forgejo webhook secret rotates too, regenerate REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET alongside it." - "`bao kv put platform/workloads/reuse/reuse-surface/runtime-secrets REUSE_SURFACE_TOKEN=@file` (and the webhook field if changed)." - "ESO re-syncs reuse/reuse-surface-runtime → reuse-surface-env on Railiance01; roll the consumer; update the Forgejo webhook config if the secret changed; revoke the old token." - "Verify capabilities-safe on the data path (`bao token capabilities`)." - id: openrouter-llm-connect title: OpenRouter API key for llm-connect in activity-core need_keywords: [openrouter, llm, llm-connect, api, key, activity-core, gemini, provider, openrouter_api_key] owner_repo: railiance-platform subsystem: OpenBao + activity-core warden_executes: false wiki_ref: wiki/playbooks/openrouter-llm-connect.md#worker-checklist canon_ref: net-kingdom/docs/platform-identity-security-architecture.md reviewed: "2026-07-02" status: active delegation: mode: interim intended_owner: secrets-engine blocked_on: "secrets-engine has not confirmed whether exec --catalog generalizes over arbitrary OpenBao lanes (asked 2026-08-11, msg 7d55d332)" reviewed: "2026-08-11" # High-risk: provider API key with spend impact + prompt-adjacent (WP-0026 T04). risk: high # Concrete, owner-confirmed lane — railiance-platform CCR-2026-0003 / RAILIANCE-WP-0010 # (promoted 2026-07-02): policy workload-kv-read-llm-connect-provider-secrets and k8s # auth role external-secrets-activity-core applied; ExternalSecret # activity-core/llm-connect-provider-secrets SecretSynced and llm-connect rolled out on # the OpenBao-delivered value; positive + negative access verified with audit evidence. # Production consumer is ESO; warden access proxies reads as the caller and never holds # the provider key. auth_method: "caller's own OpenBao token (operator OIDC via key-cape, or a token carrying workload-kv-read-llm-connect-provider-secrets)" path_template: "platform/workloads/activity-core/llm-connect/llm-connect-provider-secrets" fetch_command: "bao kv get -field=OPENROUTER_API_KEY platform/workloads/activity-core/llm-connect/llm-connect-provider-secrets" policy_ref: "flex-auth check secret.read:llm-connect" exec_capable: true lane: secret rotation: method: rotate owner: railiance-platform automatable: false steps: - "Create a new key in the OpenRouter dashboard for the llm-connect identity; keep the old key active until rollout completes." - "`bao kv put platform/workloads/activity-core/llm-connect/llm-connect-provider-secrets OPENROUTER_API_KEY=@file` (value from a mode-0600 file)." - "ESO re-syncs activity-core/llm-connect-provider-secrets; roll out llm-connect on the new value; then delete the old OpenRouter key." - "Verify capabilities-safe on the data path (`bao token capabilities`)." - id: railiance-backup-offsite-lane title: Railiance offsite backup Nextcloud WebDAV credentials need_keywords: [railiance, backup, nextcloud, webdav, offsite, age, forgejo-backup, NC_WEBDAV_TOKEN, file drop] owner_repo: railiance-platform subsystem: OpenBao + Nextcloud warden_executes: false wiki_ref: wiki/playbooks/railiance-backup-offsite-lane.md#worker-checklist canon_ref: railiance-platform/docs/workload-kv-access-lanes.md reviewed: "2026-07-16" status: active delegation: mode: interim intended_owner: railiance-platform blocked_on: "Rotation is re-establish, a multi-step procedure ops-warden only describes" reviewed: "2026-08-11" # High-risk: WebDAV upload token + AGE recovery escrow (WP-0026 T04). risk: high # CCR-2026-0004: policy + OIDC role applied; values provisioned 2026-07-07. # Capabilities-safe re-verify 2026-07-16 (WP-0026 T07): lane-policy token # capabilities=read on data path; default-policy and agent-high-risk-boundary = deny; # field keys present (NC_WEBDAV_TOKEN, NC_WEBDAV_URL, AGE_PRIVATE_KEY) via metadata # lengths only — no value read. Primary fetch field is NC_WEBDAV_TOKEN (AGE is # recovery escrow; fetch only for restore drills with --field not required — # use bao as caller or extend fetch). EXPOSED taint set on version 2 (T05). auth_method: "caller's own OpenBao token (OIDC netkingdom role railiance-backup-workload-kv-read)" path_template: "platform/workloads/railiance/backup/offsite-lane" fetch_command: "bao kv get -field=NC_WEBDAV_TOKEN platform/workloads/railiance/backup/offsite-lane" exec_capable: true lane: secret # Mixed lane: NC_WEBDAV_TOKEN rotates (provider re-mint); AGE_PRIVATE_KEY # re-establishes (new keypair + re-encrypt existing artifacts). Method reflects # the more involved re-establish path. Marked exposed 2026-07-16 (see # history/2026-07-16-credential-disclosure-lessons.md); rotation is the operator's # optional call (buildup), not a blocker for promotion. rotation: method: re-establish owner: railiance-platform automatable: false steps: - "Rotate NC_WEBDAV_TOKEN: regenerate the Nextcloud WebDAV app password/token; `bao kv put platform/workloads/railiance/backup/offsite-lane NC_WEBDAV_TOKEN=@file`. NC_WEBDAV_URL changes only if the host/share moves." - "Re-establish AGE_PRIVATE_KEY: generate a new keypair (`age-keygen`), decrypt existing offsite artifacts with the old key and re-encrypt to the new recipient, then `bao kv put ... AGE_PRIVATE_KEY=@file` (mode-0600 file, shred after)." - "Because AGE_PRIVATE_KEY is recovery escrow, retain the old key offline until re-encryption of all retained backups is confirmed." - "Verify capabilities-safe on the data path (`bao token capabilities`); run a restore drill against a re-encrypted artifact." - "After rotation, clear EXPOSED taint: remove custom_metadata exposed_at/exposed_version (see `warden taint railiance-backup-offsite-lane`)." - id: forgejo-admin-api-token title: Forgejo operator/admin API token (PAT) need_keywords: [forgejo, admin, pat, package, prune, FORGEJO_ADMIN_TOKEN, forgejo-package-prune, forgejo-tegwick, webhook, forgejo-npm] owner_repo: railiance-platform subsystem: OpenBao + Forgejo warden_executes: false wiki_ref: wiki/playbooks/forgejo-admin-api-token.md#worker-checklist canon_ref: railiance-platform/docs/workload-kv-access-lanes.md reviewed: "2026-07-13" status: active delegation: mode: interim intended_owner: secrets-engine blocked_on: "secrets-engine has not confirmed whether exec --catalog generalizes over arbitrary OpenBao lanes (asked 2026-08-11, msg 7d55d332)" reviewed: "2026-08-11" # High-risk: site-admin PAT (WP-0026 T04). risk: high # CCR-2026-0006: approved by platform-operator 2026-07-12; policy # workload-kv-read-forgejo-admin + OIDC role forgejo-admin-workload-kv-read live on # bao.coulomb.social; PAT attended-minted and stored under field API_TOKEN at # platform/workloads/forgejo/forgejo-admin (v-latest). Verified 2026-07-13: documented # fetch_command returns non-empty, PAT valid against forgejo.coulomb.social # (/api/v1/user -> login=tegwick, is_admin=true); negative default-policy denial # recorded on CCR. Sibling to forgejo-mailer (SMTP via ESO); phase 1 is # workstation/worker OIDC fetch only, no cluster ExternalSecret. auth_method: "caller's own OpenBao token (OIDC netkingdom role forgejo-admin-workload-kv-read)" path_template: "platform/workloads/forgejo/forgejo-admin" fetch_command: "bao kv get -field=API_TOKEN platform/workloads/forgejo/forgejo-admin" exec_capable: true lane: secret rotation: method: rotate owner: railiance-platform automatable: false steps: - "As Forgejo user tegwick (site admin): Settings → Applications → generate a new token with the current scopes (read/write:package, read/write:repository, plus admin scopes for operator-bootstrap); keep the old token until cutover." - "Store via the provisioning helper: `~/railiance-platform/scripts/forgejo-admin-pat-provision.sh ` writes field API_TOKEN to platform/workloads/forgejo/forgejo-admin; shred the input file." - "Confirm the new PAT works (fetch --field API_TOKEN into env, call /api/v1/user — never print it), then delete the old token in Forgejo." - "Verify capabilities-safe on the data path (`bao token capabilities`); notify consumers (package-prune, operator-bootstrap, npm-smoke, reuse-webhook) to re-fetch." # --- tenant commercial secrets (mount tenants/; WARDEN-WP-0028) --- - id: binky-company-email-imap title: Binky company email IMAP credentials need_keywords: [binky, company, email, imap, mailbox, binky-hedgehog, mail, company-email] owner_repo: railiance-platform subsystem: OpenBao + email-connect warden_executes: false wiki_ref: wiki/playbooks/binky-company-email-imap.md#worker-checklist canon_ref: railiance-platform/docs/workload-kv-access-lanes.md reviewed: "2026-07-17" status: active delegation: mode: interim intended_owner: tenant-engine blocked_on: "Custody at tenants/binky/... but rotation owner is binky-control — split lifecycle, no front door reconciling it" reviewed: "2026-08-11" risk: high # CCR-2026-0007: tenants/ mount + policy + OIDC role applied; founder provisioned # values via UI (version ≥2, not placeholder). Capabilities-safe verify 2026-07-17: # lane-policy read; default deny. Host: imap.ionos.de:993 (binky-control config). auth_method: "caller's own OpenBao token (OIDC netkingdom role binky-company-email-imap-workload-kv-read)" path_template: "tenants/binky/company-email/imap" fetch_command: "bao kv get -field=IMAP_PASSWORD tenants/binky/company-email/imap" exec_capable: true lane: secret rotation: method: rotate owner: binky-control automatable: false steps: - "At the mail provider, revoke the old app password / mailbox password and mint a new one (do not paste it into chat or Git)." - "`bao kv put tenants/binky/company-email/imap IMAP_PASSWORD=@file` (and IMAP_USERNAME=@file if the login changed); shred the mode-0600 input file(s)." - "Re-run email-connect read-only scan with warden access --exec / env inject; confirm metadata-only evidence under binky-control/mailmeta/." - "Verify capabilities-safe on tenants/data/binky/company-email/imap; if EXPOSED taint was set, clear custom_metadata after rotation." - id: binky-qonto-api title: Binky Qonto bank API credentials (read-only MCP) need_keywords: [binky, qonto, bank, api, finance, cost-run-rate, mcp, organization] owner_repo: railiance-platform subsystem: OpenBao + qonto-mcp-server warden_executes: false wiki_ref: wiki/playbooks/binky-qonto-api.md#worker-checklist canon_ref: binky-control/integrations/qonto-mcp.md reviewed: "2026-07-21" status: active delegation: mode: interim intended_owner: tenant-engine blocked_on: "Same split lifecycle as binky-company-email-imap; no tenant-engine front door" reviewed: "2026-08-11" risk: high # CCR-2026-0008: policy + OIDC role applied; secret at tenants/binky/qonto-api # (fields API_KEY, API_USER). Map to QONTO_API_KEY / QONTO_ORGANIZATION_ID for # qonto-mcp-server. First read-only pull 2026-07-21 (BINKY-WP-0005-T05). # Read-only is harness tool allow-list — Qonto keys are not scope-limited server-side. auth_method: "caller's own OpenBao token (OIDC netkingdom role binky-qonto-api-workload-kv-read)" path_template: "tenants/binky/qonto-api" fetch_command: "bao kv get -field=API_KEY tenants/binky/qonto-api" exec_capable: true lane: secret rotation: method: rotate owner: binky-control automatable: false steps: - "In the Qonto dashboard, revoke the old API key and mint a new one under /settings/integrations (do not paste it into chat or Git)." - "`bao kv put tenants/binky/qonto-api API_KEY=@file` (and API_USER=@file if the login/org slug changed); shred the mode-0600 input file(s)." - "Re-run read-only pull with warden access --exec (map API_KEY→QONTO_API_KEY, API_USER→QONTO_ORGANIZATION_ID); update binky-control finance/CostRunRate.md metadata only." - "Verify capabilities-safe on tenants/data/binky/qonto-api; if EXPOSED taint was set, clear custom_metadata after rotation." - id: rapp-qonto-keycape-client title: rapp-qonto KeyCape workload client need_keywords: [rapp-qonto, qonto, keycape, oidc, client-credentials, service-token, workload-identity, binky] owner_repo: key-cape subsystem: KeyCape + OpenBao warden_executes: false wiki_ref: wiki/CredentialRouting.md#routing-catalog-index canon_ref: key-cape/docs/qonto-runtime-identity-contract.md reviewed: "2026-07-27" status: active delegation: mode: interim intended_owner: key-cape blocked_on: "client_secret_basic exchange is a key-cape protocol procedure, not a KV read; KEY-WP-0008 finished 2026-08-15 without a key-cape-native exchange/rotation command, and the workplan that would add one is not yet opened (key-cape acked interim 2026-08-15)" reviewed: "2026-08-17" risk: high auth_method: "OpenBao platform workload lane; KeyCape client_secret_basic exchange" path_template: "platform/workloads/rapp-qonto/keycape-client" fetch_command: "bao kv get -field=client_secret platform/workloads/rapp-qonto/keycape-client" exec_capable: true lane: secret rotation: method: rotate owner: key-cape automatable: true steps: - "Generate a fresh newline-free secret through an approved execution transport; never print it." - "Write the same value to OpenBao and sso/keycape-rapp-qonto-client, then restart KeyCape." - "Verify positive qonto:read exchange plus wrong-secret and excessive-scope denial without printing tokens." - id: agent-harness-forgejo-deploy title: agent-harness Forgejo deploy key (write sandbox; binky-control at cutover) need_keywords: [agent-harness, forgejo, deploy, key, ssh, executor-sandbox, railiance, binky-control, deploy-key] owner_repo: railiance-platform subsystem: OpenBao + Forgejo + agent-harness warden_executes: false wiki_ref: wiki/playbooks/agent-harness-secrets.md#lane-2-forgejo-deploy-key canon_ref: binky-control/integrations/executor-worker-secrets.md reviewed: "2026-07-17" status: active delegation: mode: interim intended_owner: railiance-platform blocked_on: "re-establish plus an alternative host-local key path; two ways in, neither owner-fronted (also agent-harness)" reviewed: "2026-08-11" risk: high # Provisioned 2026-07-17 on railiance01: ed25519 keypair on host, OpenBao copy at # platform/workloads/agent-harness/forgejo-deploy-key, write deploy key on # coulomb/executor-sandbox (title agent-harness-railiance01). Git push verified. auth_method: "caller's own OpenBao token (policy workload-kv-read-agent-harness-forgejo) or host-local key at ~/.local/agent-harness/ssh/forgejo-deploy" path_template: "platform/workloads/agent-harness/forgejo-deploy-key" fetch_command: "bao kv get -field=SSH_PUBLIC_KEY platform/workloads/agent-harness/forgejo-deploy-key" policy_ref: "flex-auth check secret.read:agent-harness-forgejo" # Assist proxy for public key metadata field (private key stays host-local / high-risk). exec_capable: true lane: secret rotation: method: re-establish owner: railiance-platform automatable: false steps: - "On railiance01 generate a new ed25519 keypair under ~/.local/agent-harness/ssh/ (mode 600); do not paste the private key into chat or Git." - "`bao kv put platform/workloads/agent-harness/forgejo-deploy-key SSH_PRIVATE_KEY=@file SSH_PUBLIC_KEY=@file` then register the public key as a write deploy key on coulomb/executor-sandbox (and binky-control at cutover); remove the old deploy key." - "Verify `ssh -p 30022 -i -T git@forgejo.coulomb.social` authenticates as the deploy key; test push to executor-sandbox only." - id: agent-harness-binky-mail-approle title: agent-harness AppRole for non-interactive Binky company-email IMAP read need_keywords: [agent-harness, approle, binky, mail, imap, EXECUTOR_APPROLE_DIR, unattended] owner_repo: railiance-platform subsystem: OpenBao AppRole + agent-harness + email-connect warden_executes: false wiki_ref: wiki/playbooks/agent-harness-secrets.md#lane-3-mail-approle canon_ref: binky-control/integrations/executor-worker-secrets.md reviewed: "2026-07-17" status: active delegation: mode: interim intended_owner: railiance-platform blocked_on: "AppRole is a host-standing credential; no owner front door for minting or rotating role_id+secret_id" reviewed: "2026-08-15" risk: high # Provisioned 2026-07-17: role agent-harness-binky-mail bound to existing policy # workload-kv-read-binky-company-email-imap; role_id/secret_id delivered to # railiance01 ~/.local/agent-harness/approle-binky-mail (0600). Positive IMAP field # lengths verified; negative forgejo-admin deny verified. token_ttl=15m max=30m # token_num_uses=8. Human OIDC role unchanged. auth_method: "AppRole login role=agent-harness-binky-mail (role_id+secret_id on worker host via EXECUTOR_APPROLE_DIR)" path_template: "tenants/binky/company-email/imap" fetch_command: "bao write -field=token auth/approle/login role_id=$ROLE_ID secret_id=$SECRET_ID # then bao kv get -field=IMAP_PASSWORD tenants/binky/company-email/imap" exec_capable: false lane: secret rotation: method: rotate owner: railiance-platform automatable: false steps: - "bao write -f auth/approle/role/agent-harness-binky-mail/secret-id → new secret_id; deliver mode-0600 to railiance01 EXECUTOR_APPROLE_DIR; shred old secret_id file." - "Optionally re-mint IMAP password (see binky-company-email-imap) if the mailbox credential itself rotated." - "Verify AppRole login + field presence (lengths only); confirm default/other policies still deny sibling paths." # --- draft: owner path not yet shipped; hidden from default lookup --- - id: object-storage-sts title: Object-storage STS / temporary S3 credentials need_keywords: [s3, sts, object-storage, minio, artifact-store, temporary, credentials, bucket, vending] owner_repo: net-kingdom subsystem: flex-auth + OpenBao + artifact-store warden_executes: false wiki_ref: wiki/playbooks/object-storage-sts.md#worker-checklist canon_ref: net-kingdom/docs/object-storage-sts-credential-vending.md reviewed: "2026-06-24" status: draft delegation: mode: native intended_owner: net-kingdom reviewed: "2026-08-15" - id: database-dynamic-credentials title: Database dynamic credentials (OpenBao secrets engine) need_keywords: [database, db, postgres, cnpg, dynamic, credentials, password, lease, openbao] owner_repo: rapp-postgres subsystem: rapp-postgres + railiance-platform OpenBao broker warden_executes: false wiki_ref: wiki/playbooks/database-dynamic-credentials.md#worker-checklist canon_ref: rapp-postgres/docs/canon-drafts/shared-platform-relational-storage_v0.1-draft.md reviewed: "2026-08-10" status: active delegation: mode: native intended_owner: rapp-postgres reviewed: "2026-08-15" risk: high exec_capable: false - id: rein-openweights-openrouter-approle title: rein-openweights AppRole for non-interactive OpenRouter key read need_keywords: [rein-openweights, approle, openrouter, glas-harness, unattended, REIN_OPENWEIGHTS_APPROLE_DIR] owner_repo: ops-mason subsystem: OpenBao AppRole + rein-openweights warden_executes: false wiki_ref: wiki/playbooks/rein-openweights-openrouter-approle.md#worker-checklist canon_ref: ops-mason/plans/rein-openweights-openrouter-approle.md reviewed: "2026-07-27" status: active delegation: mode: interim intended_owner: ops-mason blocked_on: "AppRole is a host-standing credential; no owner-fronted exec for the OpenRouter key read" reviewed: "2026-08-15" risk: standard # Built 2026-07-27 by ops-mason (MASON-WP-0001-T05), approved by Bernd # Worsch 2026-07-27. Policy + AppRole live; reins/ KV v2 mount created # (no existing mount fit without widening scope beyond what was # approved). token_num_uses corrected from OpenBao's own default (0 = # unlimited) to 8, matching agent-harness-binky-mail. Policy path shape # also corrected post-build: originally written against the bare KV # path (KV v1 shape), which silently denies everything on a v2 mount -- # fixed to grant on /data/ + /metadata/. # platform-admin's own policy also needed a new "reins/*" entry before # the founder's paste-once-provision could write the value (every # other KV mount was already listed there; this one predated the fix). # Promoted draft -> active: founder completed paste-once-provision and # glas-harness/GLAS-WP-0002-T02's live verification succeeded -- # real AppRole login, real KV v2 read, real OpenRouter call, real # commit, with OPENROUTER_API_KEY unset throughout. auth_method: "AppRole login role=rein-openweights (role_id+secret_id via REIN_OPENWEIGHTS_APPROLE_DIR)" path_template: "reins/rein-openweights/openrouter" fetch_command: "bao write -field=token auth/approle/login role_id=$ROLE_ID secret_id=$SECRET_ID # then bao kv get -field=api_key reins/rein-openweights/openrouter" exec_capable: false lane: secret rotation: method: rotate owner: ops-mason automatable: false steps: - "bao write -f auth/approle/role/rein-openweights/secret-id -> new secret_id; deliver mode-0600 to REIN_OPENWEIGHTS_APPROLE_DIR; shred old secret_id file." - "Optionally re-mint the OpenRouter key itself if it rotated independently." - "Verify AppRole login + field presence (length only); confirm default/other policies still deny sibling paths." - id: coulomb-social-runtime-env title: coulomb.social runtime env Secret (SECRET_KEY, DATABASE_URL, USER_ENGINE_PROXY_SECRET) need_keywords: - coulomb-social - coulomb.social - coulomb social - csoc - runtime-env - coulomb-social-env - django secret_key - user-engine-proxy - apps-pg coulomb owner_repo: railiance-platform subsystem: K8s Secrets + apps-pg (OpenBao path planned) warden_executes: false wiki_ref: wiki/playbooks/coulomb-social-runtime-env.md#worker-checklist canon_ref: railiance-platform/docs/apps-pg.md reviewed: "2026-08-09" status: active delegation: mode: interim intended_owner: railiance-apps blocked_on: "Runtime Secret applied via railiance-apps make target; OpenBao path planned but CCR not applied" reviewed: "2026-08-17" # USER_ENGINE_PROXY_SECRET ownership settled 2026-08-16 (Bernd; State Hub decision # 8fe22037-5bbb-4487-bb86-e4beccee454b, USER-WP-0021): it is infrastructure trust # between ingress and workload, not a user-domain fact. intended_owner stays # railiance-apps; user-engine is consumer-only and claims no lane here. consumers: [user-engine] risk: standard # K8s assembly is the live handoff today (same pattern as vergage-teilnahme-env). # OpenBao KV platform/workloads/coulomb/coulomb-social/runtime-env is the # future custody home — CCR not yet applied; resolvable via operator script. auth_method: "kubectl as platform operator (or bao OIDC when OpenBao lane is provisioned)" path_template: "k8s:coulomb-social/coulomb-social-env" fetch_command: "cd ~/railiance-apps && make coulomb-social-env-secret-dry-run # then make coulomb-social-env-secret (values never printed)" exec_capable: false lane: secret resolvable: true rotation: method: rotate owner: railiance-apps automatable: false steps: - "SECRET_KEY: make coulomb-social-env-secret COULOMB_SOCIAL_ENV_SECRET_ARGS='--rotate-secret-key' then rollout restart deploy/coulomb-social." - "USER_ENGINE_PROXY_SECRET: rotate user-engine/user-engine-runtime, re-run make coulomb-social-env-secret, restart app." - "DATABASE_URL: platform rotates apps-pg role password secret; re-run make coulomb-social-env-secret; restart app." - id: audit-core-senders title: audit-core sender registry (write and operator-read tokens) need_keywords: [audit-core, senders, sender registry, ingest token, AUDIT_CORE_SENDERS] owner_repo: ops-mason subsystem: OpenBao + audit-core warden_executes: false wiki_ref: wiki/playbooks/audit-core-senders.md#worker-checklist canon_ref: audit-core/docs/operator-runbook.md reviewed: "2026-08-13" status: draft delegation: mode: native intended_owner: ops-mason reviewed: "2026-08-15" auth_method: "in-cluster generated Secret audit-core-senders; later OpenBao KV via Mason wrap-migrate" path_template: "platform/workloads/audit-core/senders" policy_ref: "external-secrets-audit-core" exec_capable: false resolvable: false lane: secret - id: email-connect-transactional title: email-connect transactional SMTP and caller ingest token need_keywords: [email-connect, transactional, smtp, ionos, starttls, ingest, invitation, verification, EMAIL_CONNECT_SMTP_PASSWORD, EMAIL_CONNECT_INGEST_TOKEN] owner_repo: railiance-platform subsystem: OpenBao + email-connect warden_executes: false wiki_ref: wiki/playbooks/email-connect-transactional.md#worker-checklist canon_ref: railiance-platform/docs/workload-kv-access-lanes.md reviewed: "2026-08-12" status: active delegation: mode: interim intended_owner: secrets-engine blocked_on: "secrets-engine has not confirmed whether exec --catalog generalizes over arbitrary OpenBao lanes (asked 2026-08-11, msg 7d55d332)" reviewed: "2026-08-15" risk: high # CCR-2026-0010 approved 2026-08-12; applied same day (EMAIL-WP-0004-T03): # policies external-secrets-email-connect + workload-kv-read-email-connect-transactional, # KV platform/workloads/email-connect/transactional v1, ESO token Secret, # ClusterSecretStore openbao-email-connect Ready, ExternalSecret SecretSynced, # Deployment Ready on railiance01. Positive: user-engine /healthz 200 and # bearer allow-list checks; negative: non-user-engine Connection refused, # unauth 401. user-engine must receive ingest token under its own custody # (not SMTP fields) for production outbox wiring (NK-WP-0024). auth_method: "caller's own OpenBao token (operator OIDC, or ESO child token openbao-email-connect-eso-token)" path_template: "platform/workloads/email-connect/transactional" fetch_command: "bao kv get -field=EMAIL_CONNECT_SMTP_PASSWORD platform/workloads/email-connect/transactional" policy_ref: "flex-auth check secret.read:email-connect" exec_capable: true resolvable: true lane: secret rotation: method: rotate owner: railiance-platform automatable: false steps: - "At IONOS, mint a new mailbox app password for the transactional identity; keep the old password until ESO refresh and pod Ready." - "`bao kv put platform/workloads/email-connect/transactional EMAIL_CONNECT_SMTP_PASSWORD=@file` (and USERNAME/INGEST_TOKEN if those rotate); shred mode-0600 files." - "ESO re-syncs email-connect/email-connect-runtime; roll email-connect. If INGEST_TOKEN changed, update user-engine runtime and roll user-engine." - "Verify capabilities-safe on platform/data/workloads/email-connect/transactional; confirm /healthz Ready without printing secret values." - id: scaleway-bootstrap title: Scaleway org/project API key for reef-storage bucket create need_keywords: [scaleway, s3, object-storage, bootstrap, reef-storage, backup, nl-ams] owner_repo: railiance-platform subsystem: OpenBao + Scaleway warden_executes: false wiki_ref: wiki/playbooks/scaleway-bootstrap.md#worker-checklist canon_ref: ops-mason/plans/reef-storage-scaleway-bootstrap.md reviewed: "2026-08-14" status: draft delegation: mode: interim intended_owner: railiance-platform blocked_on: "Founder bootstrap API key; draft until provisioned; no owner-fronted exec" reviewed: "2026-08-15" risk: high # CCR-2026-0011. Values via founder paste-once or local tfvars ingest. # Not the Barman runtime key (platform-pg-backup-s3). auth_method: "caller's own OpenBao token (founder / operator workstation)" path_template: "platform/workloads/railiance/scaleway/bootstrap" fetch_command: "bao kv metadata get platform/workloads/railiance/scaleway/bootstrap" exec_capable: false resolvable: false lane: secret rotation: method: rotate owner: railiance-platform automatable: false steps: - "In Scaleway IAM, revoke the bootstrap API key after the scoped bucket key exists." - "Delete or overwrite platform/workloads/railiance/scaleway/bootstrap; do not copy values into chat." - "Confirm metadata gone or version bumped; capabilities-safe only."