Right-size director/advisor container surface tiers after the 2026-07-10 rollback #448

Merged
coilyco-ops merged 6 commits from issue-447 into main 2026-07-10 23:18:35 +00:00
Member

closes #447

ward.workflow: pull-requests-and-merge

What

  • docs/role-surface-tiers.md - the intended per-role surface tiers written down as a deliberate, reviewed definition, with per-layer capability ownership (roles.kdl bindings / ward-embedded presets / dev-base image binaries / ward container bring-up) so a one-layer rollback reads as drift instead of silently disabling a role.
  • roles.kdl rebind - advisor gets its documented live-observe set back (guardfile.aws.kdl + new guardfile.tailscale.kdl), director gets live-observe + kubectl + runner-token mint (it fronted the infrastructure#538 recovery), ops gets runner-token mint.
  • guardfile.forgejo.runnertoken.kdl + .ward/forgejo-runner-token.sh - surfaces ward ops forgejo actions generate-runner-token (global/org/repo scopes), the operator path whose absence blocked the infrastructure#539 token restore. Kept out of the fleet-wide readactions overlay on purpose.
  • guardfile.tailscale.kdl - read-only tailnet observe surface (status/ping/netcheck/ip/whois/dns-status/version, state-changing verbs denied). ward#578 made tailnet reach a per-role guardfile set, and the bundle had no tailscale guardfile to bind.
  • .ward/surface-check.sh (+ ward exec surface-check) - bring-up self-check keyed on WARD_ROLE that probes binaries, creds, daemons, and mounted verbs and exits non-zero listing every miss. Run as director from this engineer container it reproduces exactly the drift the issue describes.

Verified

  • ward doctor passes all checks (smart defaults / repo authority / fleet / ops bundle / exec bundle) with WARD_CONFIG_REF pointed at this branch's .ward/.
  • pre-commit run --all-files green, pytest 446 passed.
  • surface-check: engineer passes on this surface, director fails loud listing the 5 expected misses.

Notes for review

  • The shipped ward runtime mounts only the hardcoded guardfile.forgejo.kdl monolith for ward ops forgejo (the actions logs leaf is ward-native Go). The runnertoken overlay (like the existing readactions runs/tasks leaves) is authored intent that ward's mount path must consume for the acceptance to be fully live - that ward-side wiring, plus invoking surface-check at bring-up, is called out as ward-side follow-up work in the doc.
  • Merge + commit-status stay deferred to the ward-native PR-workflow issue and agentic-os#446, per the issue.

🤖 Generated with Claude Code

closes #447 ward.workflow: pull-requests-and-merge ## What - **docs/role-surface-tiers.md** - the intended per-role surface tiers written down as a deliberate, reviewed definition, with per-layer capability ownership (roles.kdl bindings / ward-embedded presets / dev-base image binaries / ward container bring-up) so a one-layer rollback reads as drift instead of silently disabling a role. - **roles.kdl rebind** - advisor gets its documented live-observe set back (`guardfile.aws.kdl` + new `guardfile.tailscale.kdl`), director gets live-observe + kubectl + runner-token mint (it fronted the infrastructure#538 recovery), ops gets runner-token mint. - **guardfile.forgejo.runnertoken.kdl** + `.ward/forgejo-runner-token.sh` - surfaces `ward ops forgejo actions generate-runner-token` (global/org/repo scopes), the operator path whose absence blocked the infrastructure#539 token restore. Kept out of the fleet-wide readactions overlay on purpose. - **guardfile.tailscale.kdl** - read-only tailnet observe surface (status/ping/netcheck/ip/whois/dns-status/version, state-changing verbs denied). ward#578 made tailnet reach a per-role guardfile set, and the bundle had no tailscale guardfile to bind. - **.ward/surface-check.sh** (+ `ward exec surface-check`) - bring-up self-check keyed on `WARD_ROLE` that probes binaries, creds, daemons, and mounted verbs and exits non-zero listing every miss. Run as `director` from this engineer container it reproduces exactly the drift the issue describes. ## Verified - `ward doctor` passes all checks (smart defaults / repo authority / fleet / ops bundle / exec bundle) with `WARD_CONFIG_REF` pointed at this branch's `.ward/`. - `pre-commit run --all-files` green, `pytest` 446 passed. - surface-check: engineer passes on this surface, director fails loud listing the 5 expected misses. ## Notes for review - The shipped ward runtime mounts only the hardcoded `guardfile.forgejo.kdl` monolith for `ward ops forgejo` (the `actions logs` leaf is ward-native Go). The runnertoken overlay (like the existing readactions runs/tasks leaves) is authored intent that ward's mount path must consume for the acceptance to be fully live - that ward-side wiring, plus invoking surface-check at bring-up, is called out as ward-side follow-up work in the doc. - Merge + commit-status stay deferred to the ward-native PR-workflow issue and agentic-os#446, per the issue. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Write the intended per-role container surface tiers down as a deliberate,
reviewed definition (docs/role-surface-tiers.md) with per-layer capability
ownership, and restore the operationally-needed reach the rollback stripped:

- advisor gets guardfile.aws.kdl back (the aws half of its documented
  live-observe set; tailnet bring-up stays ward-side and is mapped as such)
- director gets aws + kubectl + runner-token mint (it fronts incident
  recovery, per the infrastructure#538 probe)
- ops gets runner-token mint (its absence blocked the infrastructure#539
  token restore)
- new guardfile.forgejo.runnertoken.kdl exec bridge surfaces
  `ward ops forgejo actions generate-runner-token` (global/org/repo scopes),
  kept out of the fleet-wide readactions overlay on purpose
- new .ward/surface-check.sh (+ ward exec surface-check) asserts a live
  surface matches its role tier and fails loud listing every miss, so an
  over-broad rollback is caught at bring-up, not mid-incident

Merge authority + commit-status read stay deferred to the ward-native PR
workflow capability and agentic-os#446. Refs #447

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(ward): add tailnet live-observe guardfile and bind it per role
All checks were successful
ci / gate (pull_request) Successful in 17s
5319c66d19
ward#578 made tailnet reach a per-role guardfile set, but the aos bundle
carried no tailscale guardfile, so the overlay could not express the
advisor/director/ops tailnet binding at all. Author the read-only observe
surface (status/ping/netcheck/ip/whois/dns-status/version, state-changing
verbs denied) and bind it to the three live-observe roles. Refs #447

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
docs: pin ward#1072 as the bring-up wiring follow-up
All checks were successful
ci / gate (pull_request) Successful in 15s
e251a2605a
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
docs: name the tailscale guardfile in the bundle inventory
All checks were successful
ci / gate (pull_request) Successful in 10s
adb111d95c
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix: merge main into issue-447; package new bundle files in the explicit ward-specs tar
All checks were successful
ci / gate (pull_request) Successful in 11s
72727fd8fd
Main's #437 replaced the wildcard ward-specs packaging with an explicit
tar member list plus a drift-guard. Fold the branch's four new bundle
files (runner-token bridge + guardfile, tailscale guardfile, surface
self-check) into both, and resolve the ward-specs.md / FEATURES.md prose
conflicts in favor of main's rewrite with this branch's additions folded
in. Refs #447

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(ward): right-size role surface tiers after rollback
All checks were successful
ci / gate (pull_request) Successful in 13s
cff2031b5b
Sign in to join this conversation.
No description provided.