Compare commits
3 commits
main
...
mason/stat
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e66a56653 | |||
| 6294e4b521 | |||
| 3a4333d850 |
3 changed files with 164 additions and 4 deletions
|
|
@ -10,12 +10,12 @@
|
||||||
# declares it, and is null where the field set has not been established --
|
# declares it, and is null where the field set has not been established --
|
||||||
# null means unknown, never 'one field'.
|
# null means unknown, never 'one field'.
|
||||||
|
|
||||||
generated_at: "2026-08-22T23:31:10Z"
|
generated_at: "2026-08-26T19:56:48Z"
|
||||||
source: ops-warden/registry/routing/catalog.yaml
|
source: ops-warden/registry/routing/catalog.yaml
|
||||||
catalog_revision: "0fae0904ce8d8694338dd53a8a79abec5fec788d"
|
catalog_revision: "3a4333d850295d2bed39136bfe53f786564eec03"
|
||||||
catalog_revision_date: "2026-08-23T01:31:05+02:00"
|
catalog_revision_date: "2026-08-26T21:56:44+02:00"
|
||||||
catalog_dirty: false
|
catalog_dirty: false
|
||||||
high_risk_lane_count: 21
|
high_risk_lane_count: 24
|
||||||
concrete_path_count: 14
|
concrete_path_count: 14
|
||||||
|
|
||||||
# Graded high but not a single KV address -- a routing pattern, a broker
|
# Graded high but not a single KV address -- a routing pattern, a broker
|
||||||
|
|
@ -23,11 +23,14 @@ concrete_path_count: 14
|
||||||
no_concrete_path:
|
no_concrete_path:
|
||||||
- database-dynamic-credentials
|
- database-dynamic-credentials
|
||||||
- inter-hub-bootstrap-ssh
|
- inter-hub-bootstrap-ssh
|
||||||
|
- net-kingdom-lldap-bind-credential
|
||||||
|
- net-kingdom-privacyidea-admin-token
|
||||||
- object-storage-sts
|
- object-storage-sts
|
||||||
- openbao-api-key
|
- openbao-api-key
|
||||||
- openbao-platform-admin-login
|
- openbao-platform-admin-login
|
||||||
- openbao-shamir-recovery-ceremony
|
- openbao-shamir-recovery-ceremony
|
||||||
- ops-warden-warden-sign-token
|
- ops-warden-warden-sign-token
|
||||||
|
- state-hub-forge-derivation-read
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
- id: agent-harness-binky-mail-approle
|
- id: agent-harness-binky-mail-approle
|
||||||
|
|
|
||||||
|
|
@ -574,6 +574,44 @@ entries:
|
||||||
- "Verify capabilities-safe on the data path (`bao token capabilities`); run a restore drill against a re-encrypted artifact."
|
- "Verify capabilities-safe on the data path (`bao token capabilities`); run a restore drill against a re-encrypted artifact."
|
||||||
- "After rotation, clear EXPOSED taint: remove custom_metadata exposed_at/exposed_version (see `warden taint railiance-backup-offsite-lane`)."
|
- "After rotation, clear EXPOSED taint: remove custom_metadata exposed_at/exposed_version (see `warden taint railiance-backup-offsite-lane`)."
|
||||||
|
|
||||||
|
- id: state-hub-forge-derivation-read
|
||||||
|
title: Forgejo read-only token for State Hub projection derivation
|
||||||
|
# Organisation-wide repository read: if the value leaks, every private
|
||||||
|
# repository is readable. Read-only, no write, no admin, no persistence —
|
||||||
|
# but the breadth is the grade (approved knowingly 2026-08-26).
|
||||||
|
risk: high
|
||||||
|
workload_ref:
|
||||||
|
applicability: applicable
|
||||||
|
unknown_reason: "The state-hub deployment has no authoritative workload identity declaration yet; the AppRole is the identity until it does."
|
||||||
|
need_keywords: [state-hub, statehub, forge, forgejo, derivation, derive, projection, private, repository, clone, FORGE_READ_TOKEN, ADR-012, work-records, unreadable, kubernetes-auth]
|
||||||
|
owner_repo: ops-mason
|
||||||
|
subsystem: OpenBao + Forgejo
|
||||||
|
warden_executes: false
|
||||||
|
wiki_ref: wiki/playbooks/state-hub-forge-derivation-read.md#worker-checklist
|
||||||
|
canon_ref: ops-mason/plans/state-hub-forge-derivation-read.md
|
||||||
|
reviewed: "2026-08-26"
|
||||||
|
status: draft
|
||||||
|
delegation:
|
||||||
|
mode: native
|
||||||
|
intended_owner: ops-mason
|
||||||
|
blocked_on: "Policy and Kubernetes auth role built and capability-verified 2026-08-27 (MASON-WP-0003-T02). Still draft: the KV path holds no token until paste_once_provision delivers one, and ServiceAccount state-hub/state-hub does not exist yet (STATE-WP-0084-T02). Promote to active once both land."
|
||||||
|
reviewed: "2026-08-26"
|
||||||
|
verified: unverified
|
||||||
|
# ops-warden routes this and executes nothing: it issues SSH certificates
|
||||||
|
# only and owns no secret store. ops-mason builds the structure; the forge
|
||||||
|
# owner mints the value; paste_once_provision delivers it.
|
||||||
|
auth_method: "Kubernetes auth (role state-hub-forge-derivation, ServiceAccount state-hub/state-hub) from the in-cluster state-hub workload"
|
||||||
|
path_template: "platform/workloads/state-hub/forge-derivation (field FORGE_READ_TOKEN)"
|
||||||
|
rotation:
|
||||||
|
method: rotate
|
||||||
|
owner: ops-mason
|
||||||
|
automatable: false
|
||||||
|
steps:
|
||||||
|
- "Mint a replacement read-only token in Forgejo — repository read, organisation-wide, no other scope."
|
||||||
|
- "Deliver it to platform/workloads/state-hub/forge-derivation, field FORGE_READ_TOKEN, via paste_once_provision. ops-mason does not handle the value."
|
||||||
|
- "Revoke the previous token in Forgejo."
|
||||||
|
- "Confirm a derivation pass still reads a known private repository; rotation must not require a chart change or a redeploy."
|
||||||
|
|
||||||
- id: forgejo-admin-api-token
|
- id: forgejo-admin-api-token
|
||||||
title: Forgejo operator/admin API token (PAT)
|
title: Forgejo operator/admin API token (PAT)
|
||||||
need_keywords: [forgejo, admin, pat, package, prune, FORGEJO_ADMIN_TOKEN, forgejo-package-prune, forgejo-tegwick, webhook, forgejo-npm]
|
need_keywords: [forgejo, admin, pat, package, prune, FORGEJO_ADMIN_TOKEN, forgejo-package-prune, forgejo-tegwick, webhook, forgejo-npm]
|
||||||
|
|
|
||||||
119
wiki/playbooks/state-hub-forge-derivation-read.md
Normal file
119
wiki/playbooks/state-hub-forge-derivation-read.md
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
# State Hub Forge Derivation Read Token
|
||||||
|
|
||||||
|
Date: 2026-08-26 (policy and auth role built and verified 2026-08-27)
|
||||||
|
Catalog: `state-hub-forge-derivation-read` (status `draft` until the token and ServiceAccount land)
|
||||||
|
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) |
|
||||||
|
| 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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue