ops-warden/registry/routing/catalog.yaml
tegwick a9086ad6b6
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Route dynamic database credentials to rapp-postgres
2026-08-10 19:37:05 +02:00

641 lines
37 KiB
YAML

# 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 — see 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
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
cert_command: "warden sign <actor> --pubkey <path>"
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 <actor> --pubkey <path>` — 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
# 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 -- <cmd>"
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
# 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=<domain>"
path_template: "platform/workloads/<domain>/<workload>/<bundle>"
fetch_command: "bao kv get -field=<FIELD> <path_template>"
policy_ref: "flex-auth check secret.read:<domain>"
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 <path> <FIELD>=@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
# 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 -- <cmd>"
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
- 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
# 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=<domain>"
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
- 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
- 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
- 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
- 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
# 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
# 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
# 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
# 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
# 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 <mode-0600-file>` 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
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
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#credential-routing-catalog
canon_ref: key-cape/docs/qonto-runtime-identity-contract.md
reviewed: "2026-07-27"
status: active
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
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 <key> -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
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
- 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
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
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 <mount>/data/<path> + <mount>/metadata/<path>.
# 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
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."