warden route find "state hub read private repository" returned nothing, which is why the need had to be reasoned out from first principles instead of looked up. Pointer-only (warden_executes: false): ops-mason builds the AppRole, policy, and KV path under MASON-WP-0003; the forge owner mints the value; paste_once_provision delivers it. ops-warden routes and executes nothing. Graded high on breadth, not on write authority — the token is read-only but organisation-wide, so a leak reads every private repository. Approved at that breadth 2026-08-26 (ops-mason plan §6). status: draft until MASON-WP-0003-T02 has created the structure and the negative capability check passes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 3377672@bnt-lap001 Assistant-Session: 15463ccf-238f-4e13-b163-93aa25c6d166
107 lines
4.1 KiB
Markdown
107 lines
4.1 KiB
Markdown
# State Hub Forge Derivation Read Token
|
|
|
|
Date: 2026-08-26 (proposed)
|
|
Catalog: `state-hub-forge-derivation-read` (status `draft` until built)
|
|
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 AppRole, policy, and KV path
|
|
are ops-mason's build; the token value is minted by the forge owner and
|
|
delivered through `paste_once_provision`.
|
|
|
|
**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) |
|
|
| AppRole | `state-hub-forge-derivation` (`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 AppRole identity can read the data path
|
|
bao token capabilities <approle-token> platform/data/workloads/state-hub/forge-derivation
|
|
# → expect: read
|
|
|
|
# Negative: it can read nothing else, including the admin lane
|
|
bao token capabilities <approle-token> platform/data/workloads/forgejo/forgejo-admin
|
|
# → expect: deny
|
|
```
|
|
|
|
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
|