diff --git a/k8s/railiance/README.md b/k8s/railiance/README.md index c1bed99..5f3d23d 100644 --- a/k8s/railiance/README.md +++ b/k8s/railiance/README.md @@ -48,11 +48,13 @@ claim auth. | --- | --- | --- | | `actcore-issue-core-runtime` | `platform/workloads/issue-core/issue-core/issue-core-runtime` | `ISSUE_CORE_API_KEY` | | `actcore-forgejo-admin` | `platform/workloads/forgejo/forgejo-admin` (`API_TOKEN`) | `FORGEJO_TOKEN` | +| `actcore-backup-offsite` | `platform/workloads/railiance/backup/offsite-lane` | `NC_WEBDAV_TOKEN`, `NC_WEBDAV_URL` | +| `llm-connect-provider-secrets` | `platform/workloads/activity-core/llm-connect/llm-connect-provider-secrets` | `OPENROUTER_API_KEY` | Prereqs: `ClusterSecretStore/openbao-activity-core` and ESO token bootstrap with -both read policies (`OPENBAO_TOKEN_FILE=~/.local/openbao/platform-admin.token -./scripts/openbao-eso-token-apply.sh` — attaches -`workload-kv-read-issue-core-runtime` + `workload-kv-read-forgejo-admin`). +the four exact-path read policies (`OPENBAO_TOKEN_FILE=~/.local/openbao/platform-admin.token +./scripts/openbao-eso-token-apply.sh`). The llm-connect `ExternalSecret` remains +owned by the llm-connect deployment package rather than activity-core. Roll back to audit mode by setting `ISSUE_SINK_TYPE=null` and restarting worker and event-router deployments. See `docs/issue-core-emission-boundary.md`. @@ -94,8 +96,12 @@ OPENBAO_TOKEN_FILE=~/.local/openbao/platform-admin.token ./scripts/openbao-eso-t kubectl apply -f ~/railiance-platform/argocd/platform-addons/openbao-secretstore/openbao-activity-core.clustersecretstore.yaml kubectl apply -f k8s/railiance/15-externalsecret-issue-core.yaml kubectl apply -f k8s/railiance/15-externalsecret-forgejo-admin.yaml +kubectl apply -f k8s/railiance/15-externalsecret-backup-offsite.yaml +kubectl apply -f ~/llm-connect/deploy/k8s/activity-core-llm-connect/externalsecret.yaml kubectl -n activity-core wait --for=condition=Ready externalsecret/actcore-issue-core-runtime --timeout=120s kubectl -n activity-core wait --for=condition=Ready externalsecret/actcore-forgejo-admin --timeout=120s +kubectl -n activity-core wait --for=condition=Ready externalsecret/actcore-backup-offsite --timeout=120s +kubectl -n activity-core wait --for=condition=Ready externalsecret/llm-connect-provider-secrets --timeout=120s kubectl -n activity-core wait --for=condition=ready pod -l app.kubernetes.io/name=actcore-app-db --timeout=180s kubectl -n activity-core wait --for=condition=ready pod -l app.kubernetes.io/name=actcore-temporal-db --timeout=180s kubectl -n activity-core wait --for=condition=ready pod -l app.kubernetes.io/name=actcore-nats --timeout=180s diff --git a/scripts/openbao-eso-token-apply.sh b/scripts/openbao-eso-token-apply.sh index f65956d..86e1ed0 100755 --- a/scripts/openbao-eso-token-apply.sh +++ b/scripts/openbao-eso-token-apply.sh @@ -4,15 +4,17 @@ # - actcore-issue-core-runtime (ISSUE_CORE_API_KEY) # - actcore-forgejo-admin (FORGEJO_TOKEN for package prune) # - actcore-backup-offsite (NC_WEBDAV_* for Option A backups) +# - llm-connect-provider-secrets (OPENROUTER_API_KEY for llm-connect) # # Default policies (already present in OpenBao; files re-written when present): # workload-kv-read-issue-core-runtime # workload-kv-read-forgejo-admin # workload-kv-read-railiance-backup-offsite-lane +# workload-kv-read-llm-connect-provider-secrets set -euo pipefail # Space-separated policy names. Override with OPENBAO_ACTIVITY_CORE_POLICIES. -DEFAULT_POLICIES="workload-kv-read-issue-core-runtime workload-kv-read-forgejo-admin workload-kv-read-railiance-backup-offsite-lane" +DEFAULT_POLICIES="workload-kv-read-issue-core-runtime workload-kv-read-forgejo-admin workload-kv-read-railiance-backup-offsite-lane workload-kv-read-llm-connect-provider-secrets" POLICIES="${OPENBAO_ACTIVITY_CORE_POLICIES:-$DEFAULT_POLICIES}" POLICY_DIR="${OPENBAO_POLICY_DIR:-$HOME/railiance-platform/openbao/policies}" BAO_ADDR="${BAO_ADDR:-https://bao.coulomb.social}" diff --git a/tests/test_openbao_eso_token_contract.py b/tests/test_openbao_eso_token_contract.py new file mode 100644 index 0000000..3f61aa7 --- /dev/null +++ b/tests/test_openbao_eso_token_contract.py @@ -0,0 +1,26 @@ +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] + + +def test_activity_core_eso_token_covers_every_declared_runtime_lane(): + script = (ROOT / "scripts" / "openbao-eso-token-apply.sh").read_text(encoding="utf-8") + required_policies = { + "workload-kv-read-issue-core-runtime", + "workload-kv-read-forgejo-admin", + "workload-kv-read-railiance-backup-offsite-lane", + "workload-kv-read-llm-connect-provider-secrets", + } + + default_line = next( + line for line in script.splitlines() if line.startswith("DEFAULT_POLICIES=") + ) + for policy in required_policies: + assert policy in default_line + + +def test_railiance_runbook_applies_and_waits_for_llm_connect_external_secret(): + runbook = (ROOT / "k8s" / "railiance" / "README.md").read_text(encoding="utf-8") + assert "llm-connect/deploy/k8s/activity-core-llm-connect/externalsecret.yaml" in runbook + assert "externalsecret/llm-connect-provider-secrets --timeout=120s" in runbook diff --git a/workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md b/workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md index 0e9bc66..074396e 100644 --- a/workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md +++ b/workplans/ACTIVITY-WP-0031-production-execution-reliability-cleanup.md @@ -39,6 +39,16 @@ HTTP 401. Credential ownership is the `railiance-platform` OpenBao lane Track rotation/reconciliation, restart, and a successful fixture smoke as the exit evidence. +Progress 2026-08-20: railiance-platform repaired the delivery half. The +activity-core ESO bootstrap default now includes the approved exact-path +llm-connect policy, its replacement token reports read capability, and the +reviewed `ExternalSecret` is `Ready=True` / `SecretSynced` on railiance01. It +took ownership of the one-key Secret, llm-connect rolled out, and the real +actcore-worker reaches `/health` through the Service. The post-restart fixture +still returns sanitized OpenRouter HTTP 401, proving the canonical key itself +is rejected. T01 remains `wait` on an attended OpenRouter account owner to mint +and safely provision a replacement key; no key value was read or printed. + ## Emergency-pause weekly SBOM fan-out ```task