Every execution position is now explicit. Catalog entries carry delegation.mode (permanent / native / interim) with intended owner and blocker. warden route gaps lists the interim set. Promotion requires the ownership question. Doctrine lives in AccessRouting.md; the register was published to the named owner repos.
129 lines
No EOL
6 KiB
Markdown
129 lines
No EOL
6 KiB
Markdown
# Catalog Lane Promotion — draft → active
|
|
|
|
Date: 2026-07-01
|
|
Workplan: WARDEN-WP-0023 T05
|
|
|
|
`registry/routing/catalog.yaml` entries start as **`draft`** until an owner-confirmed
|
|
concrete path exists. Draft lanes are hidden from default `warden route find` unless
|
|
`--all` is passed.
|
|
|
|
---
|
|
|
|
## Promotion checklist
|
|
|
|
Before changing `status: draft` → `status: active`:
|
|
|
|
| # | Criterion | Evidence |
|
|
| --- | --- | --- |
|
|
| 1 | **Owner confirmed** | Owner repo workplan or State Hub note naming the lane ready |
|
|
| 2 | **Concrete path** | Real OpenBao path, grant id, or exec command — no unresolved `<placeholders>` in the primary handoff |
|
|
| 3 | **Playbook** | `wiki/playbooks/<id>.md` with `#worker-checklist` section |
|
|
| 4 | **Exec routing** | `exec_owner` + native command **or** `exec_capable: true` with tested `warden access` proxy |
|
|
| 5 | **Resolvable** | `warden route show <id> --json` shows `resolvable: true` when placeholders are documented |
|
|
| 6 | **Tests** | Routing test or smoke proving lookup + handoff shape (no secret values in fixtures) |
|
|
| 7 | **Review date** | Update `reviewed:` in catalog entry |
|
|
| 8 | **Verification** | Positive + negative proof via **`bao token capabilities`** — never `bao kv get` (see below) |
|
|
| 9 | **Rotation guidance** | Secret-vending lanes carry a `rotation:` block; `warden rotate-guide <id>` returns steps. Enforced by the `catalog_rotation_coverage` scorecard check (WP-0026 T06) |
|
|
| 10 | **Delegation** | Entry carries a `delegation:` block (WP-0030). `mode: permanent` only for ops-warden's own front door. `mode: native` when the owner already fronts it. `mode: interim` requires `intended_owner` and `blocked_on`; the promotion note must name both and the retirement condition |
|
|
|
|
Promotion PR touches: `registry/routing/catalog.yaml`, playbook, optional
|
|
`tests/test_routing.py`, and a one-line note in `wiki/CredentialRouting.md` draft table.
|
|
|
|
If `delegation.mode` is `interim`, the promotion note (PR body or State Hub
|
|
progress) must state:
|
|
|
|
1. who the intended owner is
|
|
2. what is missing (`blocked_on`)
|
|
3. what would let ops-warden step back (`exec_owner` + proven owner front door)
|
|
|
|
A proxy that works is not enough to promote without answering the ownership
|
|
question. `warden route gaps` must list the lane after merge if it is interim.
|
|
|
|
---
|
|
|
|
## Capabilities-safe lane verification (WARDEN-WP-0026 T01)
|
|
|
|
**Verifying a lane must never read the secret *data*.** A negative deny-test that
|
|
runs `bao kv get <path>` will, if the deny fails (e.g. a privileged token
|
|
fallback), print the secret value into a logged context — this is exactly the
|
|
2026-07-16 CCR-2026-0004 disclosure. Prove *allow/deny* with
|
|
`bao token capabilities`, which returns the capability list, not the value.
|
|
|
|
For KV v2, capabilities are checked against the **API data path**
|
|
(`<mount>/data/<lane-path>`), not the `kv get` logical path.
|
|
|
|
```bash
|
|
# Positive: the lane's own OIDC identity can read the data path.
|
|
bao login -method=oidc -path=netkingdom role=<lane-role> # caller identity
|
|
bao token capabilities "$(bao print token)" platform/data/<lane-path>
|
|
# → expect the list to include: read
|
|
|
|
# Negative: a default-only identity is denied — no value is ever read.
|
|
DEFAULT_TOKEN=$(bao token create -policy=default -field=token) # if denied, STOP — do not fall back
|
|
bao token capabilities "$DEFAULT_TOKEN" platform/data/<lane-path>
|
|
# → expect: deny
|
|
```
|
|
|
|
- **Never** substitute `bao kv get` for the checks above. Reading a value to
|
|
"confirm it's there" is the anti-pattern; presence is proven by `read` in the
|
|
capability list.
|
|
- If `bao token create -policy=default` is itself denied for your identity, that
|
|
is a *pass for the deny direction* — **do not** fall back to your privileged
|
|
login token to force the read.
|
|
- Fetching a value **for use** (`--field` into an env var or file, or
|
|
`warden access … --field`) is a separate, intended action — not verification.
|
|
|
|
Record the capability lists (allow/deny) as the promotion evidence; they contain
|
|
no secret material and are safe for CCRs, State Hub, and Git.
|
|
|
|
---
|
|
|
|
## Worked examples (already active)
|
|
|
|
**`ops-warden-warden-sign-token`** — promoted 2026-07-01 after RAILIANCE-WP-0005:
|
|
|
|
- Owner: `railiance-platform` credential broker
|
|
- Concrete grant: `ops-warden/warden-sign`
|
|
- Playbook: `wiki/playbooks/ops-warden-warden-sign-token.md`
|
|
- Smoke: `make credential-exec-ops-warden-smoke`
|
|
|
|
**`issue-core-ingestion-api-key`** — promoted 2026-07-02 after RAILIANCE-WP-0009
|
|
(CCR-2026-0002): KV path live, ExternalSecret `issue-core/issue-core-runtime`
|
|
SecretSynced, positive + negative verification audit-logged.
|
|
|
|
**`openrouter-llm-connect`** — promoted 2026-07-02 after RAILIANCE-WP-0010
|
|
(CCR-2026-0003): KV path live, ExternalSecret
|
|
`activity-core/llm-connect-provider-secrets` SecretSynced, llm-connect rolled
|
|
out on the OpenBao-delivered value, positive + negative verification audit-logged.
|
|
|
|
---
|
|
|
|
## Draft lanes (2026-07-17)
|
|
|
|
| Catalog `id` | Blocker |
|
|
| --- | --- |
|
|
| `object-storage-sts` | NK-WP-0007 vending path not production-exercised |
|
|
| `database-dynamic-credentials` | OpenBao database engine role paths TBD per workload |
|
|
|
|
**Promoted 2026-07-16:** `railiance-backup-offsite-lane` — CCR-2026-0004
|
|
capabilities-safe re-verify (WP-0026 T07); primary field `NC_WEBDAV_TOKEN`;
|
|
`risk: high` + EXPOSED taint on version 2 (operator may rotate optionally).
|
|
|
|
**Promoted 2026-07-17:** `binky-company-email-imap` — CCR-2026-0007 on mount
|
|
`tenants/`; founder provisioned (KV version ≥2); capabilities-safe verify;
|
|
primary field `IMAP_PASSWORD`; `risk: high`. Host `imap.ionos.de:993`.
|
|
|
|
**Tenant path (WP-0028):** new client secrets use mount `tenants/`, not
|
|
`platform/workloads/`. See `wiki/playbooks/tenant-secret-onboarding.md`.
|
|
|
|
Re-run promotion when the owning repo closes the blocker; do not promote on
|
|
playbook prose alone.
|
|
|
|
---
|
|
|
|
## See also
|
|
|
|
- `wiki/CredentialRouting.md` — draft table index
|
|
- `wiki/playbooks/ops-warden-warden-sign-token.md` — promotion reference
|
|
- `wiki/AccessRouting.md#interim-custodianship` — delegation register doctrine
|
|
- `warden route gaps` — queryable interim register |