Add ward ops passthrough surface (blocker for coily removal) #104

Closed
opened 2026-06-17 06:47:55 +00:00 by coilysiren · 3 comments
Owner

Why

ward has no ops command, but coily ops aws|gh|kubectl|forgejo|flyctl|gcloud|mcporter|netlify is load-bearing fleet-wide (27 repos pre-approve coily ops flyctl/coily ops gcloud; the global agent overlay + SSM rules lean on coily ops aws ssm and coily ops forgejo). This is the hard blocker for fully deprecating coily. Tracks alongside infrastructure#351 (coily uninstall gate) and ward#62 (fold the generated KDL path into ward proper).

Finding: mostly wiring, not a logic port

The argv-rejection, audit-row, binary-resolution, and HTTP-egress primitives all live in cli-guard and ward already consumes them. The spec/exec-driven ops mechanism is already designed, generated, and proven in ward's cmd/ward-kdl/ proving-ground binary.

  • coily ops umbrella: (*Runner).opsCommand() in coily cmd/coily/ops_ops.go, binaries via the ptOps registry in passthroughs.go -> passthrough.Command.
  • Reusable in cli-guard (already imported by ward): cli/passthrough, cli/verb (argv-rejection + audit via verb.Wrap, policy.ValidateArgs), pkg/audit, cli/execverb + http/specverb (the KDL engines).
  • ward command registration: cmd/ward/main.go Commands: slice; ward pkg/ward git show the mirror pattern.

Per-subcommand shape

  • kubectl, flyctl, gcloud: plain passthrough + egress. Trivial.
  • netlify: plain + one EnvFromSSM (NETLIFY_AUTH_TOKEN from /coilysiren/netlify/token).
  • aws: passthrough + awsReadGate sensitive-read deny (already in cli-guard cli/awsgate and the KDL aws guardfile).
  • mcporter: ArgvRewriter (--args-file) + SecretResolver (SSM scan, coily-only helpers to port).
  • gh: ArgvRewriter (REST/jq) + ReadCache + ghPreflightGate (Actions playwright-only, blocks gh issue create). coily-only, not yet in cli-guard.
  • forgejo: NOT a binary passthrough. coily uses in-pod kubectl exec; ward already has a REST client (forgejo_issue.go); the KDL track makes it spec-REST. Hardest, least uniform.

Audit + lockdown

Identical audit format (shared cli-guard pkg/audit), different dir (~/.ward vs ~/.coily). Stamp verb names ops.<bin> / ops.<api>.<verb> to keep dashboards working. Lockdown: cli-guard cli/lockdown/defaults.yaml already denies bare aws/gh/kubectl/flyctl/gcloud/mcporter; add Bash(netlify:*) deny and a Bash(ward ops:*) allow entry.

  1. Trivial passthroughs (kubectl/flyctl/gcloud + netlify): new cmd/ward/ops.go + cmd/ward/ops_passthroughs.go, register in main.go. ~1/2 day. Lands a usable surface.
  2. aws via existing KDL track (execverb.Mount) or plain passthrough + ported awsReadGate. ~1/2-1 day.
  3. gh + mcporter: port the rewriters/gates from coily. ~1 day.
  4. forgejo: fold specverb.Mount into ward (ward#62). ~1-2 days. Only piece with real design surface.

Decision to flag

ward ops aws can be a plain passthrough + ported sensitive-read gate (Track A, matches coily 1:1) OR an execverb KDL allowlist (Track B, stricter: operations not listed are denied). Track B is a deliberate posture change from coily's "pass everything, gate the sensitive reads", not a mechanical port. Pick before building.

Authored by an investigation agent during the coily deprecation work.

## Why `ward` has no `ops` command, but `coily ops aws|gh|kubectl|forgejo|flyctl|gcloud|mcporter|netlify` is load-bearing fleet-wide (27 repos pre-approve `coily ops flyctl`/`coily ops gcloud`; the global agent overlay + SSM rules lean on `coily ops aws ssm` and `coily ops forgejo`). This is the hard blocker for fully deprecating coily. Tracks alongside infrastructure#351 (coily uninstall gate) and ward#62 (fold the generated KDL path into ward proper). ## Finding: mostly wiring, not a logic port The argv-rejection, audit-row, binary-resolution, and HTTP-egress primitives all live in cli-guard and ward already consumes them. The spec/exec-driven `ops` mechanism is already designed, generated, and proven in ward's `cmd/ward-kdl/` proving-ground binary. - `coily ops` umbrella: `(*Runner).opsCommand()` in coily `cmd/coily/ops_ops.go`, binaries via the `ptOps` registry in `passthroughs.go` -> `passthrough.Command`. - Reusable in cli-guard (already imported by ward): `cli/passthrough`, `cli/verb` (argv-rejection + audit via `verb.Wrap`, `policy.ValidateArgs`), `pkg/audit`, `cli/execverb` + `http/specverb` (the KDL engines). - ward command registration: `cmd/ward/main.go` `Commands:` slice; `ward pkg`/`ward git` show the mirror pattern. ## Per-subcommand shape - kubectl, flyctl, gcloud: plain passthrough + egress. Trivial. - netlify: plain + one `EnvFromSSM` (NETLIFY_AUTH_TOKEN from /coilysiren/netlify/token). - aws: passthrough + `awsReadGate` sensitive-read deny (already in cli-guard `cli/awsgate` and the KDL aws guardfile). - mcporter: `ArgvRewriter` (--args-file) + `SecretResolver` (SSM scan, coily-only helpers to port). - gh: ArgvRewriter (REST/jq) + ReadCache + `ghPreflightGate` (Actions playwright-only, blocks `gh issue create`). coily-only, not yet in cli-guard. - forgejo: NOT a binary passthrough. coily uses in-pod kubectl exec; ward already has a REST client (`forgejo_issue.go`); the KDL track makes it spec-REST. Hardest, least uniform. ## Audit + lockdown Identical audit format (shared cli-guard `pkg/audit`), different dir (~/.ward vs ~/.coily). Stamp verb names `ops.<bin>` / `ops.<api>.<verb>` to keep dashboards working. Lockdown: cli-guard `cli/lockdown/defaults.yaml` already denies bare aws/gh/kubectl/flyctl/gcloud/mcporter; add `Bash(netlify:*)` deny and a `Bash(ward ops:*)` allow entry. ## Recommended sequencing 1. Trivial passthroughs (kubectl/flyctl/gcloud + netlify): new `cmd/ward/ops.go` + `cmd/ward/ops_passthroughs.go`, register in main.go. ~1/2 day. Lands a usable surface. 2. aws via existing KDL track (execverb.Mount) or plain passthrough + ported awsReadGate. ~1/2-1 day. 3. gh + mcporter: port the rewriters/gates from coily. ~1 day. 4. forgejo: fold specverb.Mount into ward (ward#62). ~1-2 days. Only piece with real design surface. ## Decision to flag `ward ops aws` can be a plain passthrough + ported sensitive-read gate (Track A, matches coily 1:1) OR an execverb KDL allowlist (Track B, stricter: operations not listed are denied). Track B is a deliberate posture change from coily's "pass everything, gate the sensitive reads", not a mechanical port. Pick before building. Authored by an investigation agent during the coily deprecation work.
coilyco-ops added
P1
and removed
P2
labels 2026-06-24 17:19:49 +00:00
Member

Re-triage (goose-triage method, claude-macos-kais-macbook-pro-2 as the judgment engine, 2026-06-24)

  • P1 - Add the ward ops passthrough surface, the hard blocker for fully deprecating coily, committed near-term, clear path (mostly wiring).
  • interactive - Load-bearing fleet-wide surface, agent works it and a human verifies parity before coily comes off.
<!-- goose-triage --> **Re-triage** (goose-triage method, claude-macos-kais-macbook-pro-2 as the judgment engine, 2026-06-24) - **P1** - Add the ward ops passthrough surface, the hard blocker for fully deprecating coily, committed near-term, clear path (mostly wiring). - **interactive** - Load-bearing fleet-wide surface, agent works it and a human verifies parity before coily comes off.
Member

Re-triage (goose-triage method, claude-macos-kais-macbook-pro-2 as the judgment engine, 2026-06-24)

  • P1 - Add the ward ops passthrough surface, the hard blocker for fully deprecating coily, committed near-term, clear path (mostly wiring).
  • interactive - Load-bearing fleet-wide surface, agent works it and a human verifies parity before coily comes off.
<!-- goose-triage --> **Re-triage** (goose-triage method, claude-macos-kais-macbook-pro-2 as the judgment engine, 2026-06-24) - **P1** - Add the ward ops passthrough surface, the hard blocker for fully deprecating coily, committed near-term, clear path (mostly wiring). - **interactive** - Load-bearing fleet-wide surface, agent works it and a human verifies parity before coily comes off.
coilysiren added
P4
and removed
P1
labels 2026-07-01 04:29:59 +00:00
Author
Owner

ward ops passthrough shipped and is in use fleet-wide (ward ops forgejo/aws/kubectl and friends), and coily is retired (the coily ops spelling is gone, agentic-os#261). The coily-removal blocker is resolved, so closing as done. Any remaining sub-verb gap belongs in its own issue.

(automated triage prune, coilyco-ops director session)

ward ops passthrough shipped and is in use fleet-wide (ward ops forgejo/aws/kubectl and friends), and coily is retired (the coily ops spelling is gone, agentic-os#261). The coily-removal blocker is resolved, so closing as done. Any remaining sub-verb gap belongs in its own issue. (automated triage prune, coilyco-ops director session)
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/ward#104
No description provided.