diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index e4bba2e..00990ba 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -191,7 +191,6 @@ entries: reviewed: "2026-06-18" status: active - # --- draft: owner path not yet shipped; hidden from default lookup --- - 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] @@ -200,8 +199,20 @@ entries: 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-06-24" - status: draft + 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 - id: openrouter-llm-connect title: OpenRouter API key for llm-connect in activity-core @@ -211,8 +222,23 @@ entries: 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-06-24" - status: draft + reviewed: "2026-07-02" + status: active + # 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 + + # --- draft: owner path not yet shipped; hidden from default lookup --- - id: object-storage-sts title: Object-storage STS / temporary S3 credentials diff --git a/tests/test_routing.py b/tests/test_routing.py index 2c18c17..ad1f836 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -249,13 +249,19 @@ def test_handoff_template_with_placeholders_accepted(tmp_path): def test_find_active_excludes_draft(): catalog = load_catalog(_repo_catalog()) - ids = [e.id for e in catalog.find("issue core api key")] - assert "issue-core-ingestion-api-key" not in ids + ids = [e.id for e in catalog.find("s3 temporary credentials")] + assert "object-storage-sts" not in ids def test_find_all_includes_draft(): catalog = load_catalog(_repo_catalog()) - ids = [e.id for e in catalog.find("issue core api key", include_draft=True)] + ids = [e.id for e in catalog.find("s3 temporary credentials", include_draft=True)] + assert "object-storage-sts" in ids + + +def test_find_issue_core_lane_active(): + catalog = load_catalog(_repo_catalog()) + ids = [e.id for e in catalog.find("issue core api key")] assert "issue-core-ingestion-api-key" in ids @@ -313,13 +319,14 @@ def test_cli_list_active_only(repo_catalog_env): result = runner.invoke(app, ["route", "list", "--json"]) assert result.exit_code == 0 ids = [e["id"] for e in json.loads(result.stdout)] - assert "issue-core-ingestion-api-key" not in ids + assert "object-storage-sts" not in ids + assert "issue-core-ingestion-api-key" in ids def test_cli_list_all_includes_draft(repo_catalog_env): result = runner.invoke(app, ["route", "list", "--all", "--json"]) ids = [e["id"] for e in json.loads(result.stdout)] - assert "issue-core-ingestion-api-key" in ids + assert "object-storage-sts" in ids def test_cli_show_ssh_json_includes_cert_pattern(repo_catalog_env): diff --git a/wiki/CredentialRouting.md b/wiki/CredentialRouting.md index 6d262c4..6406c61 100644 --- a/wiki/CredentialRouting.md +++ b/wiki/CredentialRouting.md @@ -94,6 +94,8 @@ run the owner's tool as the caller and preserve owner custody. | `railiance-infra-principals` | "railiance-infra deploys host principals" | Run the infra Ansible | | `activity-core-issue-sink` | "activity-core + issue-core own emission — pair `ISSUE_CORE_*` env vars" | See `wiki/playbooks/activity-core-issue-sink.md` | | `inter-hub-bootstrap-ssh` | "Inter-Hub bootstrap SSH envelope — attended vs unattended branches" | See `wiki/InterHubBootstrapAccessLane.md` | +| `issue-core-ingestion-api-key` | "railiance-platform OpenBao KV + ESO deliver `ISSUE_CORE_API_KEY` — here is the path" | ESO consumes in-cluster; `warden access issue-core-ingestion-api-key --fetch ISSUE_CORE_API_KEY` as yourself | +| `openrouter-llm-connect` | "railiance-platform OpenBao KV + ESO deliver `OPENROUTER_API_KEY` to activity-core" | ESO consumes in-cluster; `warden access openrouter-llm-connect --fetch OPENROUTER_API_KEY` as yourself | Promotion criteria: `wiki/playbooks/catalog-lane-promotion.md`. @@ -101,8 +103,6 @@ Promotion criteria: `wiki/playbooks/catalog-lane-promotion.md`. | Catalog `id` | Routing focus | Playbook | | --- | --- | --- | -| `issue-core-ingestion-api-key` | OpenBao KV + ESO for `ISSUE_CORE_API_KEY` | `wiki/playbooks/issue-core-ingestion-api-key.md` | -| `openrouter-llm-connect` | OpenRouter key → `llm-connect` in activity-core | `wiki/playbooks/openrouter-llm-connect.md` | | `object-storage-sts` | NK-WP-0007 STS vending path | `wiki/playbooks/object-storage-sts.md` | | `database-dynamic-credentials` | OpenBao database secrets engine | `wiki/playbooks/database-dynamic-credentials.md` | @@ -117,7 +117,7 @@ value; the owner remains OpenBao, key-cape, flex-auth, or the routed subsystem. | Request | Correct path | | --- | --- | | "`VAULT_TOKEN` for ops-warden production sign / policy-gate smoke" | `railiance-platform` credential broker — `warden route show ops-warden-warden-sign-token` | -| "Populate `OPENROUTER_API_KEY` for llm-connect" | Operator → OpenBao/K8s Secret in `activity-core` namespace | +| "Populate `OPENROUTER_API_KEY` for llm-connect" | Operator → OpenBao custody; delivery via `warden route show openrouter-llm-connect` | | "Store Inter-Hub admin key for bootstrap" | Operator → OpenBao or `IHUB_OPERATOR_KEY_FILE` (`CUST-WP-0049`) | | "Give me Vault root token" | Break-glass ceremony → `railiance-platform/docs/openbao.md` | | "S3 credentials for artifact upload" | NK-WP-0007 / artifact-store consumer path | diff --git a/wiki/playbooks/catalog-lane-promotion.md b/wiki/playbooks/catalog-lane-promotion.md index be324c7..7efd811 100644 --- a/wiki/playbooks/catalog-lane-promotion.md +++ b/wiki/playbooks/catalog-lane-promotion.md @@ -28,7 +28,7 @@ Promotion PR touches: `registry/routing/catalog.yaml`, playbook, optional --- -## Worked example (already active) +## Worked examples (already active) **`ops-warden-warden-sign-token`** — promoted 2026-07-01 after RAILIANCE-WP-0005: @@ -37,14 +37,21 @@ Promotion PR touches: `registry/routing/catalog.yaml`, playbook, optional - Playbook: `wiki/playbooks/ops-warden-warden-sign-token.md` - Smoke: `make credential-exec-ops-warden-smoke` +**`issue-core-ingestion-api-key`** — promoted 2026-07-02 after RAILIANCE-WP-0009 +(CCR-2026-0002): KV path live, ExternalSecret `issue-core/issue-core-runtime` +SecretSynced, positive + negative verification audit-logged. + +**`openrouter-llm-connect`** — promoted 2026-07-02 after RAILIANCE-WP-0010 +(CCR-2026-0003): KV path live, ExternalSecret +`activity-core/llm-connect-provider-secrets` SecretSynced, llm-connect rolled +out on the OpenBao-delivered value, positive + negative verification audit-logged. + --- -## Draft lanes — none ready yet (2026-07-01) +## Draft lanes (2026-07-02) | Catalog `id` | Blocker | | --- | --- | -| `issue-core-ingestion-api-key` | OpenBao KV path + ESO wiring not owner-signed off | -| `openrouter-llm-connect` | activity-core secret mount path still placeholder | | `object-storage-sts` | NK-WP-0007 vending path not production-exercised | | `database-dynamic-credentials` | OpenBao database engine role paths TBD per workload | diff --git a/wiki/playbooks/issue-core-ingestion-api-key.md b/wiki/playbooks/issue-core-ingestion-api-key.md index cd42d0d..79476dd 100644 --- a/wiki/playbooks/issue-core-ingestion-api-key.md +++ b/wiki/playbooks/issue-core-ingestion-api-key.md @@ -1,8 +1,8 @@ # issue-core Ingestion API Key — OpenBao Custody -Date: 2026-06-24 -Workplan: WARDEN-WP-0012 T1 -Catalog: `issue-core-ingestion-api-key` (draft until path ships) +Date: 2026-06-24 (promoted active 2026-07-02) +Workplan: WARDEN-WP-0012 T1 · RAILIANCE-WP-0009 / CCR-2026-0002 +Catalog: `issue-core-ingestion-api-key` (**active** — path live, ESO delivering) Pointer playbook for agents and operators wiring the **shared ingestion key** between `activity-core` IssueSink emission and `issue-core` REST ingestion. @@ -54,8 +54,14 @@ GITEA_BACKEND_TOKEN The ExternalSecret manifest belongs in `issue-core` workload manifests (tenant repo owns runtime deployment). Platform owns mount policy and path provisioning. -**Promotion gate:** catalog entry stays `status: draft` until this path exists -in the live OpenBao cluster and an owner-repo ExternalSecret is merged. +**Promotion gate (met 2026-07-02):** the path exists in the live OpenBao +cluster and `ExternalSecret issue-core/issue-core-runtime` is merged and +`SecretSynced` (read policy `workload-kv-read-issue-core-runtime`, k8s auth +role `external-secrets-issue-core`, auth subject +`external-secrets/external-secrets`). Positive + negative access verified with +OpenBao audit evidence (RAILIANCE-WP-0009 T05). Lifecycle +(deactivate/rotate/compromise): +`railiance-platform/docs/credential-lane-lifecycle-runbook.md`. --- @@ -110,8 +116,7 @@ scoped tokens only, never root token for routine workload secret inspection. | `issue-core` | Merge ExternalSecret + Deployment env from synced Secret | | `activity-core` | Mirror `ISSUE_CORE_API_KEY` injection for REST sink mode | -When the path ships, ops-warden promotes `issue-core-ingestion-api-key` to -`status: active` with this `wiki_ref`. +Promoted to `status: active` on 2026-07-02 (RAILIANCE-WP-0009 T06). --- diff --git a/wiki/playbooks/openrouter-llm-connect.md b/wiki/playbooks/openrouter-llm-connect.md index 8c14094..dd9d9fe 100644 --- a/wiki/playbooks/openrouter-llm-connect.md +++ b/wiki/playbooks/openrouter-llm-connect.md @@ -1,8 +1,8 @@ # OpenRouter API Key — llm-connect in activity-core -Date: 2026-06-24 -Workplan: WARDEN-WP-0012 T4 -Catalog: `openrouter-llm-connect` (draft until OpenBao path ships) +Date: 2026-06-24 (promoted active 2026-07-02) +Workplan: WARDEN-WP-0012 T4 · RAILIANCE-WP-0010 / CCR-2026-0003 +Catalog: `openrouter-llm-connect` (**active** — OpenBao path live, ESO delivering) Pointer playbook for LLM provider credentials consumed by `llm-connect` in the `activity-core` namespace. ops-warden issues SSH certs only — API keys are an @@ -25,16 +25,14 @@ OpenBao → Kubernetes Secret action owned by `railiance-platform` and ```bash warden route show openbao-api-key --json -warden route show openrouter-llm-connect --json # after promotion +warden route show openrouter-llm-connect --json ``` `OPENROUTER_API_KEY` must not appear in Git, State Hub, workplans, logs, or chat. --- -## Expected custody shape - -Documented platform path convention (coordinate before writing secrets): +## Custody shape (live since 2026-07-02) ```text platform/workloads/activity-core/llm-connect/llm-connect-provider-secrets @@ -42,12 +40,19 @@ platform/workloads/activity-core/llm-connect/llm-connect-provider-secrets Property name: `OPENROUTER_API_KEY` -Until the OpenBao path is provisioned, operators may create the K8s Secret -directly for pilot smoke (`llm-connect` README) — that is a bootstrap bridge, -not the long-term custody model. +Delivery: `ExternalSecret activity-core/llm-connect-provider-secrets` +(ClusterSecretStore `openbao-activity-core`, read policy +`workload-kv-read-llm-connect-provider-secrets`, k8s auth role +`external-secrets-activity-core`) syncs to Secret +`llm-connect-provider-secrets`; the llm-connect Deployment consumes it. +Positive + negative access verified with OpenBao audit evidence +(RAILIANCE-WP-0010 T05). Lifecycle (deactivate/rotate/compromise): +`railiance-platform/docs/credential-lane-lifecycle-runbook.md`. -**Promotion gate:** catalog entry stays `status: draft` until the OpenBao path -exists and ESO (or approved equivalent) delivers the Secret in cluster. +**Promotion gate (met 2026-07-02):** the OpenBao path exists and ESO delivers +the Secret in cluster. The earlier manually created bootstrap Secret has been +taken over by ESO on the CoulombCore cluster; the railiance01 k3s llm-connect +instance still uses its bootstrap Secret (separate migration, not this lane). ---