ops-warden/wiki/playbooks/state-hub-forge-derivation-read.md
tegwick 4ebd241d88
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Register the State Hub Forgejo derivation-read routing lane.
Pointer-only catalog entry so warden route find "state hub read
private repository" resolves. ops-warden routes and does not execute.
MASON-WP-0003-T03.

Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
2026-09-14 04:57:55 +02:00

120 lines
5 KiB
Markdown

# State Hub Forge Derivation Read Token
Date: 2026-08-26 (policy and auth role built and verified 2026-08-27; catalog active 2026-09-14)
Catalog: `state-hub-forge-derivation-read` (status `active`)
Owner: `ops-mason` (built under `ops-mason/plans/state-hub-forge-derivation-read.md`, approved 2026-08-26)
Read-only Forgejo token so the State Hub can clone **private** repositories and
derive their work records. `CUST-ADR-012` makes the forge the projection source;
that premise held only for repositories central could read, and nine private
repositories were invisible to derivation entirely (`STATE-WP-0083-T04`,
2026-08-26).
**This lane is a pointer.** ops-warden routes it and executes nothing: it issues
SSH certificates only and owns no secret store. The Kubernetes auth role, policy,
and KV path are ops-mason's build; the token value is minted by the forge owner
and delivered through `paste_once_provision`. The credential was delivered
2026-08-27; `STATE-WP-0084` mounted it into State Hub.
**Ask first:** `warden plan "state hub read private repository" --json`.
---
## OpenBao pointers
| Field | Value |
| --- | --- |
| Mount | `platform` |
| Path | `platform/workloads/state-hub/forge-derivation` |
| Secret field | `FORGE_READ_TOKEN` |
| Policy | `workload-kv-read-state-hub-forge-derivation` (read on that path alone) |
| Auth | Kubernetes auth role `state-hub-forge-derivation`, bound to ServiceAccount `state-hub/state-hub` (`token_ttl=15m`, `token_max_ttl=30m`) |
**Forgejo token scope:** repository **read**, organisation-wide. No push, no
administration, no other Forgejo resource. Approved at that breadth on
2026-08-26 — the maintenance cost of per-repository grants lands on whoever adds
a private repository later, and the leak radius (every private repository,
read-only) was accepted knowingly. Reasoning in the construction plan §6.
**Not the admin PAT.** `forgejo-admin-api-token` is a site-admin credential
owned by `railiance-platform`. Reusing it here was considered and rejected: a
projection that only reads must not hold an identity that can write.
---
## Worker checklist
1. **Plan** (agents — always):
```bash
warden plan "state hub read private repository" --json
# expect lane=state-hub-forge-derivation-read
```
2. **In-cluster consumers do nothing here.** The `state-hub` deployment receives
the credential as a Kubernetes Secret; `derive_from_forge()` picks it up on
its own. If derivation reports a repository as unreadable, the lane is the
thing to check — not the repository.
3. **Never put the token in a clone URL.** Embedded userinfo lands in logs and
process listings. Use a credential helper or an HTTP header.
4. **Reading the value directly** (operators, rare — verification only):
```bash
bao kv get -field=FORGE_READ_TOKEN platform/workloads/state-hub/forge-derivation
```
---
## Verify the lane (capabilities-safe — never read the value)
```bash
# Positive: the lane identity can read the data path
bao token capabilities <lane-token> platform/data/workloads/state-hub/forge-derivation
# → expect: read
# Negative: it can read nothing else, including the admin lane
bao token capabilities <lane-token> platform/data/workloads/forgejo/forgejo-admin
# → expect: deny
```
Verified 2026-08-27 through a 2-minute test token, revoked after use: `read` on
its own path; `deny` on `forgejo-admin`, on the shared `llm-connect` provider
secrets, and on the parent metadata path (no listing).
**Why Kubernetes auth and not an AppRole.** The construction plan proposed an
AppRole; the phase-4 live survey found `kubernetes/` auth already enabled on
this cluster, and the founder ruled for it on 2026-08-27. The pod authenticates
with its own projected ServiceAccount token, so this lane has no `role_id`
/`secret_id` pair to deliver, store, or rotate. The role binds to
`state-hub/state-hub` and deliberately **not** to `default`, which would grant
the lane to every pod in the namespace.
The negative check is the one that matters. The whole argument for building this
lane instead of reusing `forgejo-admin-api-token` is that it cannot do what that
one can.
---
## Rotation
Re-mint in Forgejo, then overwrite the KV field. Rotation must not require a
chart change or a redeploy — if it does, the delivery in
`STATE-WP-0084-T02` is wrong and should be fixed rather than worked around.
1. Mint a replacement read-only token in Forgejo (same scope: repository read,
organisation-wide).
2. Deliver it to `platform/workloads/state-hub/forge-derivation`, field
`FORGE_READ_TOKEN`, via `paste_once_provision`.
3. Revoke the previous token in Forgejo.
4. Confirm a derivation pass still reads a known private repository.
---
## See also
- `ops-mason/plans/state-hub-forge-derivation-read.md` — the construction plan
- `ops-mason/workplans/MASON-WP-0003-state-hub-forge-read-lane.md` — the build
- `state-hub/workplans/STATE-WP-0084-forge-read-for-private-repositories.md` — the consumer
- `wiki/playbooks/forgejo-admin-api-token.md` — the lane this one is deliberately not