cli-guard grew an ops-orchestration engine (stepflow health/canary/rollback) it should not own; eco-server spec reaches infra by hardcoded host path #190

Open
opened 2026-07-05 21:47:55 +00:00 by coilysiren · 0 comments
Owner

Summary

cli-guard is a security-boundary framework: it sits between a semi-trusted agent and the host and decides what may run. It has quietly grown an ops-orchestration engine that does not belong at that layer, and the Eco pipeline that consumes it reaches the host by hardcoded absolute filesystem path. Both ends are wrong. Kai wants this recorded and redesigned so the Eco ops surface can be rebuilt sturdy.

The two problems

1. cli-guard owns primitives a guard should never own.

pkg/stepflow (pkg/stepflow/stepflow.go) is a full sequencing-plus-rollback-plus-health-watch engine:

  • ordered Steps with a Compensation (reverse-order rollback on failure),
  • a Canary that re-samples a "health" leaf every Every up to Window, judging DegradedWhen / HealthyWhen via JMESPath and driving the rollback path mid-window.

That is a deploy/ops-pipeline concern (snapshot, promote, canary, roll back), not a security-gate concern. A framework whose job is "should this argv be allowed to touch the host" has no business also being the thing that decides a service is healthy or that a rollout should be reverted. The http/specverb/action_rollback.go + exec-dialect actions are the same accretion on the HTTP side. cli-guard is meant to be the engine external contributors clone with no upstream knowledge (lowest layer of the gradient), so a healthcheck/canary primitive living here is a layering inversion.

2. The eco-server spec reaches the host by hardcoded path.

The consuming guardfile (ward/cmd/ward-kdl/ward-kdl.eco-server.guardfile.kdl) wires every step to an absolute path on kai-server:

argv bash "/home/kai/projects/coilyco-flight-deck/infrastructure/scripts/eco-server-snapshot.sh"
argv bash "/home/kai/projects/coilyco-flight-deck/infrastructure/scripts/eco-server-apply-staged.sh"
...

So the "guarded" contract is really "run whatever bytes currently sit at this filesystem path on the box." There is no versioned or content-addressed contract between the spec and the infra scripts it fires. Move the scripts, rename a repo dir, or drift the box, and the guarantee silently changes.

Why it matters now

Kai is rebuilding the Eco ops surface (revive of the read-only observe capability in ward#547, plus the full-clone-URL dep work) and wants it sturdy. That rebuild should not sit on top of an orchestration engine mislocated in the security boundary, nor on host-path coupling. Get the layering right first.

Ask (design, then land)

  1. Decide where sequencing / compensating-rollback / canary-health belongs. Candidates: up in ward (guardfile-runtime orchestration), a dedicated orchestration package outside the guard boundary, or dropped in favor of the infra scripts owning their own health/rollback. cli-guard should keep only the guard decision (is this argv/leaf allowed), not the ops verdict loop.
  2. Replace hardcoded host-path invocation with an addressed contract (a pinned/versioned reference to the infra scripts, or the scripts invoked through a stable indirection the box guarantees), so "guarded" means a known artifact, not "whatever is at this path today."
  3. Land the migration without breaking the live promote pipeline (ward ops eco server promote) or the read-only observe verbs being added in ward#547.

Refs

  • Engine: cli-guard/pkg/stepflow/stepflow.go, cli-guard/http/specverb/action_rollback.go.
  • Consumer: ward/cmd/ward-kdl/ward-kdl.eco-server.guardfile.kdl, ward/docs/ops-eco.md (records the "landed in cli-guard as pkg/stepflow + exec-dialect actions" decision this issue reverses).
  • Related: ward#547 (read-only observe revive), ward#611 (Eco source hydration), the full-clone-URL dep issue filed alongside this. Origin: eco-ops director session, 2026-07-05.

Design steer from Kai (2026-07-05)

Some orchestration IS valuable - do not throw the sequencing baby out with the bathwater. The problem is first-class health-check and rollback primitives, not orchestration as such.

So the target is not "delete stepflow." It is: keep a generic step-sequencing capability (ordered steps, threading data between them) available to whatever layer owns pipelines, but do not bake domain concepts like "healthcheck" and "rollback" in as first-class engine primitives. A canary that judges service health and a compensating rollback are domain/ops policy, expressed in the pipeline definition, not verbs the guard engine itself understands.

Concretely for the recommendation:

  • Generic sequencing / step-threading: fine to keep as a primitive, but it belongs outside the security-boundary layer (cli-guard should stay the guard decision only). Up in ward's guardfile runtime, or a standalone orchestration package.
  • Health-watch (Canary, DegradedWhen/HealthyWhen) and compensating rollback: not first-class. Express them as ordinary steps / config the pipeline author writes, or push them down into the infra scripts that already know how to probe and restore. The engine should not have a health or rollback concept.

Recommend the split accordingly, and show how the eco-server promote pipeline re-expresses its canary + rollback as pipeline-author policy rather than engine primitives.

## Summary cli-guard is a **security-boundary** framework: it sits between a semi-trusted agent and the host and decides what may run. It has quietly grown an **ops-orchestration engine** that does not belong at that layer, and the Eco pipeline that consumes it reaches the host by **hardcoded absolute filesystem path**. Both ends are wrong. Kai wants this recorded and redesigned so the Eco ops surface can be rebuilt sturdy. ## The two problems **1. cli-guard owns primitives a guard should never own.** `pkg/stepflow` (`pkg/stepflow/stepflow.go`) is a full sequencing-plus-rollback-plus-health-watch engine: - ordered `Step`s with a `Compensation` (reverse-order rollback on failure), - a `Canary` that re-samples a "health" leaf every `Every` up to `Window`, judging `DegradedWhen` / `HealthyWhen` via JMESPath and driving the rollback path mid-window. That is a **deploy/ops-pipeline** concern (snapshot, promote, canary, roll back), not a security-gate concern. A framework whose job is "should this argv be allowed to touch the host" has no business also being the thing that decides a service is healthy or that a rollout should be reverted. The `http/specverb/action_rollback.go` + exec-dialect actions are the same accretion on the HTTP side. cli-guard is meant to be the engine external contributors clone with **no upstream knowledge** (lowest layer of the gradient), so a healthcheck/canary primitive living here is a layering inversion. **2. The eco-server spec reaches the host by hardcoded path.** The consuming guardfile (`ward/cmd/ward-kdl/ward-kdl.eco-server.guardfile.kdl`) wires every step to an absolute path on kai-server: ``` argv bash "/home/kai/projects/coilyco-flight-deck/infrastructure/scripts/eco-server-snapshot.sh" argv bash "/home/kai/projects/coilyco-flight-deck/infrastructure/scripts/eco-server-apply-staged.sh" ... ``` So the "guarded" contract is really "run whatever bytes currently sit at this filesystem path on the box." There is no versioned or content-addressed contract between the spec and the infra scripts it fires. Move the scripts, rename a repo dir, or drift the box, and the guarantee silently changes. ## Why it matters now Kai is rebuilding the Eco ops surface (revive of the read-only observe capability in ward#547, plus the full-clone-URL dep work) and wants it **sturdy**. That rebuild should not sit on top of an orchestration engine mislocated in the security boundary, nor on host-path coupling. Get the layering right first. ## Ask (design, then land) 1. Decide where sequencing / compensating-rollback / canary-health belongs. Candidates: up in ward (guardfile-runtime orchestration), a dedicated orchestration package outside the guard boundary, or dropped in favor of the infra scripts owning their own health/rollback. cli-guard should keep only the **guard** decision (is this argv/leaf allowed), not the ops verdict loop. 2. Replace hardcoded host-path invocation with an addressed contract (a pinned/versioned reference to the infra scripts, or the scripts invoked through a stable indirection the box guarantees), so "guarded" means a known artifact, not "whatever is at this path today." 3. Land the migration without breaking the live promote pipeline (`ward ops eco server promote`) or the read-only observe verbs being added in ward#547. ## Refs - Engine: `cli-guard/pkg/stepflow/stepflow.go`, `cli-guard/http/specverb/action_rollback.go`. - Consumer: `ward/cmd/ward-kdl/ward-kdl.eco-server.guardfile.kdl`, `ward/docs/ops-eco.md` (records the "landed in cli-guard as pkg/stepflow + exec-dialect actions" decision this issue reverses). - Related: ward#547 (read-only observe revive), ward#611 (Eco source hydration), the full-clone-URL dep issue filed alongside this. Origin: eco-ops director session, 2026-07-05. --- ## Design steer from Kai (2026-07-05) Some orchestration IS valuable - do not throw the sequencing baby out with the bathwater. The problem is **first-class health-check and rollback primitives**, not orchestration as such. So the target is not "delete stepflow." It is: keep a **generic** step-sequencing capability (ordered steps, threading data between them) available to whatever layer owns pipelines, but **do not bake domain concepts** like "healthcheck" and "rollback" in as first-class engine primitives. A canary that judges service health and a compensating rollback are **domain/ops policy**, expressed in the pipeline definition, not verbs the guard engine itself understands. Concretely for the recommendation: - Generic sequencing / step-threading: fine to keep as a primitive, but it belongs **outside the security-boundary layer** (cli-guard should stay the guard decision only). Up in ward's guardfile runtime, or a standalone orchestration package. - Health-watch (`Canary`, `DegradedWhen`/`HealthyWhen`) and compensating rollback: **not first-class**. Express them as ordinary steps / config the pipeline author writes, or push them down into the infra scripts that already know how to probe and restore. The engine should not have a `health` or `rollback` concept. Recommend the split accordingly, and show how the eco-server promote pipeline re-expresses its canary + rollback as pipeline-author policy rather than engine primitives.
coilyco-ops added
P3
and removed
P2
labels 2026-07-10 08:59:46 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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/cli-guard#190
No description provided.