diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index 00990ba..46bb815 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -214,6 +214,25 @@ entries: exec_capable: true lane: secret + - 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.coulomb.social] + owner_repo: reuse-surface + subsystem: reuse-surface federation hub + 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 — REUSE-WP-0011 / RAILIANCE-WP-0007 (hub live + # 2026-06-15): token is the cluster Secret reuse-surface-env on Railiance01, + # not OpenBao. warden access proxies kubectl as the caller and never holds the value. + auth_method: "kubectl with Railiance01 kubeconfig (~/.kube/config-hosteurope)" + path_template: "reuse/reuse-surface-env" + fetch_command: "kubectl --kubeconfig ~/.kube/config-hosteurope get secret reuse-surface-env -n reuse -o jsonpath='{.data.REUSE_SURFACE_TOKEN}' | base64 -d" + exec_capable: true + lane: secret + - 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] diff --git a/tests/test_routing.py b/tests/test_routing.py index ad1f836..f75ed48 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -277,6 +277,21 @@ def test_find_openrouter_key(): assert matches and matches[0].id == "openrouter-llm-connect" +def test_find_reuse_surface_hub_write_token(): + catalog = load_catalog(_repo_catalog()) + matches = catalog.find("REUSE_SURFACE_TOKEN", limit=3) + assert matches and matches[0].id == "reuse-surface-hub-write-token" + + +def test_reuse_surface_hub_write_token_lane_is_resolvable(): + catalog = load_catalog(_repo_catalog()) + e = catalog.get("reuse-surface-hub-write-token") + assert e is not None and e.is_active and e.exec_capable + assert e.resolvable is True + assert e.owner_repo == "reuse-surface" + assert "reuse-surface-env" in e.fetch_command + + def test_find_object_storage_sts(): catalog = load_catalog(_repo_catalog()) matches = catalog.find("s3 temporary credentials", include_draft=True) diff --git a/wiki/CredentialRouting.md b/wiki/CredentialRouting.md index 6406c61..1f5f271 100644 --- a/wiki/CredentialRouting.md +++ b/wiki/CredentialRouting.md @@ -96,6 +96,7 @@ run the owner's tool as the caller and preserve owner custody. | `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 | +| `reuse-surface-hub-write-token` | "reuse-surface hub write bearer — K8s secret `reuse-surface-env` on Railiance01" | `kubectl` from `~/.kube/config-hosteurope`, or `warden access reuse-surface-hub-write-token --fetch` as yourself | Promotion criteria: `wiki/playbooks/catalog-lane-promotion.md`. diff --git a/wiki/playbooks/reuse-surface-hub-write-token.md b/wiki/playbooks/reuse-surface-hub-write-token.md new file mode 100644 index 0000000..9df9711 --- /dev/null +++ b/wiki/playbooks/reuse-surface-hub-write-token.md @@ -0,0 +1,68 @@ +# reuse-surface Hub Write Token + +Date: 2026-07-07 +Catalog: `reuse-surface-hub-write-token` (status `active`, `resolvable: true`) +Owner: `reuse-surface` (service) · deploy custody `railiance-apps` (K8s secret) + +Bearer token for authenticated writes to the production federation hub at +`https://reuse.coulomb.social` (`POST /v1/repos`, `reuse-surface hub register`). +ops-warden **does not hold this token** — it is a pointer lane to the cluster +secret that backs the hub Deployment. + +--- + +## Owner-confirmed lane (no placeholders) + +| Field | Value | +| --- | --- | +| Cluster | Railiance01 (`92.205.62.239`) | +| Namespace | `reuse` | +| Secret | `reuse-surface-env` | +| Field | `REUSE_SURFACE_TOKEN` | +| Kubeconfig | `~/.kube/config-hosteurope` | +| Deploy runbook | `railiance-apps/docs/reuse-surface-on-railiance01.md` | +| Hub API spec | `reuse-surface/specs/FederationHubAPI.md` | + +This is **not** an OpenBao KV path. The token is generated at deploy time and +stored only in the Kubernetes Secret consumed by the `reuse-surface` workload. + +--- + +## Worker checklist + +1. **Confirm kubeconfig reachability** (you act as yourself; ops-warden adds no credential): + ```bash + kubectl --kubeconfig ~/.kube/config-hosteurope get secret reuse-surface-env -n reuse + ``` + +2. **Export for a shell session** (value streams to your terminal — never paste into chat): + ```bash + export REUSE_SURFACE_URL=https://reuse.coulomb.social + export REUSE_SURFACE_TOKEN=$( + kubectl --kubeconfig ~/.kube/config-hosteurope get secret reuse-surface-env -n reuse \ + -o jsonpath='{.data.REUSE_SURFACE_TOKEN}' | base64 -d + ) + ``` + +3. **Or proxy via warden access** (same kubectl command, audited metadata only): + ```bash + warden route show reuse-surface-hub-write-token --json + warden access reuse-surface-hub-write-token --no-policy --fetch + ``` + +4. **Register a repo** after publish-check passes: + ```bash + reuse-surface hub status + reuse-surface hub register --repo \ + --url \ + --domain + ``` + +5. **Verify federated index** picked up the new source: + ```bash + curl -fsS "$REUSE_SURFACE_URL/v1/federated" | jq '.sources | map(.repo) | index("")' + ``` + +Never commit the token, paste it into State Hub or agent chat, or store it in a +workplan. Rotation: regenerate the secret on-cluster and roll the Deployment +(`reuse-surface/docs/deploy/reuse-kubernetes.md`). \ No newline at end of file