Implement WP-0022 audit trail and WP-0023 INTENT–SCOPE closeout

Add unified metadata-only audit.jsonl with secret-material guard, instrument
sign/access/worker paths, and expose warden activity CLI. Surface broker hint
when VAULT_TOKEN is unset, refresh INTENT/SCOPE docs, and add production
integration checklists plus catalog lane promotion playbook.
This commit is contained in:
2026-07-01 23:32:38 +02:00
parent f47d632d8e
commit d6088e4e16
18 changed files with 875 additions and 59 deletions

72
wiki/AuditTrail.md Normal file
View File

@@ -0,0 +1,72 @@
# Audit Trail — Unified ops-warden Activity
Date: 2026-07-01
Workplan: WARDEN-WP-0022
ops-warden records **metadata only** for every action it performs. No token, key,
cert body, or other secret value ever lands in the audit log.
---
## What is recorded
| Kind | Source actions | Typical fields |
| --- | --- | --- |
| `sign` | `warden sign`, `warden issue`, `cert_command` | actor, backend, TTL, `policy_decision_id` |
| `access` | `warden access --fetch` / `--exec` | need id, owner repo, subject, decision id, outcome |
| `worker` | `warden worker` tick, approve, full-auto execute | triage counts, draft id, outcome |
| `hub` | State Hub progress notes (`--hub`) | summary, author, event type |
### Storage
- **Primary:** `{state_dir}/audit.jsonl` — append-only JSONL (default
`~/.local/state/warden/audit.jsonl`)
- **Legacy (merged for back-compat):** `signatures.log`, `access-audit.log`
Rotation: when `audit.jsonl` exceeds 5 MiB it is renamed to `audit.jsonl.1` and a
fresh file starts.
### Secret-material guard
`record_event()` rejects fields that look like secret values (known token prefixes,
high-entropy runs). Signing and proxy paths swallow audit failures so gatekeeping
never blocks the primary action — but tests prove values cannot be written.
---
## Query
```bash
# Human table — last 7 days
warden activity
# Filter and JSON for agents
warden activity --days 3 --kind sign --json
warden activity --days 7 --hub --json
```
| Flag | Purpose |
| --- | --- |
| `--days N` | Look back N days (default 7) |
| `--kind sign\|access\|worker\|hub` | Filter by event kind |
| `--json` | Stable JSON array for automation |
| `--hub` | Include recent State Hub progress notes mentioning ops-warden |
---
## Linger and login independence
The coordination worker can run under a `systemd --user` timer with linger enabled
(WARDEN-WP-0021). Audit events from worker ticks appear with `kind: worker`.
Full **logged-out** operational value still depends on State Hub and tunnels being
reachable without an interactive login (State Hub on railiance01, `cust-wp-0011`).
The audit trail is local-first; `--hub` adds narrative context when the hub is up.
---
## See also
- `wiki/OperatorAccessAssist.md` — metadata-only principle for access proxy
- `wiki/PolicyGatedSigning.md``policy_decision_id` on sign events
- `wiki/playbooks/scheduled-worker.md` — worker timer and review loop

View File

@@ -95,6 +95,8 @@ run the owner's tool as the caller and preserve owner custody.
| `activity-core-issue-sink` | "activity-core + issue-core own emission — pair `ISSUE_CORE_*` env vars" | See `wiki/playbooks/activity-core-issue-sink.md` |
| `inter-hub-bootstrap-ssh` | "Inter-Hub bootstrap SSH envelope — attended vs unattended branches" | See `wiki/InterHubBootstrapAccessLane.md` |
Promotion criteria: `wiki/playbooks/catalog-lane-promotion.md`.
**Draft** (hidden from default lookup until owner path ships — `warden route list --all`):
| Catalog `id` | Routing focus | Playbook |

View File

@@ -230,6 +230,19 @@ Cross-repo references:
4. Keep `fail_closed: true` unless an explicit break-glass procedure exists.
5. Smoke allow and deny paths; preserve non-secret evidence only.
### Rollback
If signs are blocked after enabling the gate:
1. Set `policy.enabled: false` in `warden.yaml` (inventory + TTL gate only).
2. Confirm `warden sign` succeeds without flex-auth.
3. File a State Hub note to `flex-auth` with non-secret symptoms (HTTP status,
`fail_closed` behaviour, actor name).
4. Re-enable only after flex-auth runtime and registry are verified.
Evidence fields for the flip: flex-auth health URL, smoke script exit codes,
`warden activity --kind sign --json` showing `policy_decision_id` on allow path.
---
## See also

View File

@@ -0,0 +1,59 @@
# 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 |
Promotion PR touches: `registry/routing/catalog.yaml`, playbook, optional
`tests/test_routing.py`, and a one-line note in `wiki/CredentialRouting.md` draft table.
---
## Worked example (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`
---
## Draft lanes — none ready yet (2026-07-01)
| Catalog `id` | Blocker |
| --- | --- |
| `issue-core-ingestion-api-key` | OpenBao KV path + ESO wiring not owner-signed off |
| `openrouter-llm-connect` | activity-core secret mount path still placeholder |
| `object-storage-sts` | NK-WP-0007 vending path not production-exercised |
| `database-dynamic-credentials` | OpenBao database engine role paths TBD per workload |
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

View File

@@ -135,9 +135,35 @@ pilot. Migrate per-tunnel when ops-bridge owner prioritizes them.
---
## Live cutover evidence template
When ops-bridge completes the pilot cutover, record **non-secret** evidence only.
Post a State Hub progress note or save under `history/` with these fields:
| Field | Example / instruction |
| --- | --- |
| Tunnel id | `state-hub-coulombcore` |
| Actor | `agt-state-hub-bridge` |
| Readiness gate | `check_tunnel_cert_readiness.py` exit code + date |
| First `bridge up` success | ISO timestamp (tunnel established) |
| First warden-signed connection | ISO timestamp from `signatures.log` or `warden activity --kind sign` |
| `cert_command` in use | yes / no |
| Rollback tested | yes / no — static-key path still available until verified |
| Operator | human handle or agent id |
| Cross-links | ops-bridge session notes, this playbook |
**Do not** include `VAULT_TOKEN`, private keys, cert bodies, or host passwords in
evidence. Use `warden activity --days 1 --kind sign --json` for sign metadata.
Coordination: message `ops-bridge` on State Hub with pointer to this template when
starting cutover (WARDEN-WP-0023).
---
## See also
- `wiki/CertCommandInterface.md`
- `wiki/OpsWardenConfig.md` — cert_command example
- `wiki/playbooks/operator-openbao-token-hygiene.md`
- `wiki/AuditTrail.md` — query recent signs via `warden activity`
- `warden route show ops-bridge-tunnel --json`