Externalize fleet org/repo inventory from ward gate code, keep the gate (audit bucket D) #396

Open
opened 2026-07-01 04:26:14 +00:00 by coilysiren · 2 comments
Owner

Bucket D of the dependency-direction audit (agentic-os#308). ward's Go carries fleet org/repo INVENTORY as baked literals. The gate LOGIC is legitimately ward's to own - the LIST it gates on is aos/fleet config that bled in (one carries the comment "Mirrors coily's defaultPrimaryOrgs", a pre-warded copy). Keep every gate, feed it the list from config.

Sites

  • Primary-org allowlist - {coilysiren, coilyco-bridge, coilyco-flight-deck, coilyco-gaming} (cmd/ward/runner.go:125-128, the coily ghost). Brew tap / repo-trust scope.
  • Persistent-clone allowlist - 7 repos hardcoded in cmd/ward/git_clone.go:17-25. The gate (which paths may be persistent) stays. The repo list moves.
  • Global intake repo - coilysiren/inbox (cmd/ward/agent_route.go:22-23).
  • Brew tap formula - coilyco-flight-deck/tap/ward (cmd/ward/upgrade.go:66) - borderline, likely stays as ward's own release identity. Decide explicitly.

Fix

Externalize the org / clone / intake LISTS to aos or fleet config, keep ward's gate code reading them. ward's own release identity (wardReleaseRepo, tap, canonical install paths, subsystem-pointer repo) stays - ward legitimately knows itself.

Review note: security-adjacent. These lists gate repo trust, clone persistence, and task routing - changing where the list comes from must not widen the gate. Review-heavy, do not blind-refactor.

Parent: agentic-os#308. Filed from the read-only director surface (she/her).

Bucket D of the dependency-direction audit (agentic-os#308). ward's Go carries fleet org/repo INVENTORY as baked literals. The gate LOGIC is legitimately ward's to own - the LIST it gates on is aos/fleet config that bled in (one carries the comment "Mirrors coily's defaultPrimaryOrgs", a pre-`warded` copy). Keep every gate, feed it the list from config. ## Sites - **Primary-org allowlist** - `{coilysiren, coilyco-bridge, coilyco-flight-deck, coilyco-gaming}` (`cmd/ward/runner.go:125-128`, the coily ghost). Brew tap / repo-trust scope. - **Persistent-clone allowlist** - 7 repos hardcoded in `cmd/ward/git_clone.go:17-25`. The gate (which paths may be persistent) stays. The repo list moves. - **Global intake repo** - `coilysiren/inbox` (`cmd/ward/agent_route.go:22-23`). - **Brew tap formula** - `coilyco-flight-deck/tap/ward` (`cmd/ward/upgrade.go:66`) - borderline, likely stays as ward's own release identity. Decide explicitly. ## Fix Externalize the org / clone / intake LISTS to aos or fleet config, keep ward's gate code reading them. ward's own release identity (`wardReleaseRepo`, tap, canonical install paths, subsystem-pointer repo) stays - ward legitimately knows itself. Review note: security-adjacent. These lists gate repo trust, clone persistence, and task routing - changing where the list comes from must not widen the gate. Review-heavy, do not blind-refactor. Parent: agentic-os#308. Filed from the read-only director surface (she/her).
Author
Owner

An adjacent operator-axis this bucket should account for (from a warded director design session - cross-ref agentic-os#306, ward#398; redirected here from #306 where I first misfiled it).

Bucket D externalizes the fleet org/repo inventory and keeps ward's gate. There is a per-operator layer that sits right on top of it and shares its subject (orgs), so it is worth holding in view while this carry is scoped.

director.default-scope (ward#398) is which orgs a director drains by default. Today it falls back to the cwd git origin (agent-director.md:48), so scope is decided by whichever folder the terminal tab opened in - the operator always lands in one repo and never gets the fleet drain --org (ward#370) was built for.

The distinction:

  • Fleet inventory (this bucket) - which orgs exist / are trusted. Fleet-owned, externalized from runner.go:127, one canonical list: {coilysiren, coilyco-bridge, coilyco-flight-deck, coilyco-gaming}. Ships like agents.yaml (channel B).
  • Operator default-scope (ward#398) - which subset of that inventory THIS operator's director defaults to. Per-operator, per-host, hand-edited. Kai's is [coilyco-flight-deck, coilyco-bridge] (not gaming, not the grounds namespace). Cannot be aos-authored or fleet-shipped - it is a local preference.

So: the inventory is fleet data (channel B); the default-scope is operator data needing a local ~/.ward source, parsed by the same decided C layer (cli-guard pkg/config). One parser, a fleet source and an operator source - no second config subsystem. ward#398 is the first operator-config consumer and should ride whatever operator-config file this work establishes, rather than birthing a standalone loader. Flagging so the org-inventory externalization and the operator selection over it are designed together, not twice. (she/her)

**An adjacent operator-axis this bucket should account for** (from a `warded director` design session - cross-ref agentic-os#306, ward#398; redirected here from #306 where I first misfiled it). Bucket D externalizes the fleet org/repo **inventory** and keeps ward's gate. There is a per-operator layer that sits right on top of it and shares its subject (orgs), so it is worth holding in view while this carry is scoped. `director.default-scope` (ward#398) is which orgs a director drains **by default**. Today it falls back to the cwd git origin (`agent-director.md:48`), so scope is decided by whichever folder the terminal tab opened in - the operator always lands in one repo and never gets the fleet drain `--org` (ward#370) was built for. The distinction: - **Fleet inventory (this bucket)** - which orgs exist / are trusted. Fleet-owned, externalized from `runner.go:127`, one canonical list: `{coilysiren, coilyco-bridge, coilyco-flight-deck, coilyco-gaming}`. Ships like agents.yaml (channel B). - **Operator default-scope (ward#398)** - which **subset** of that inventory THIS operator's director defaults to. Per-operator, per-host, hand-edited. Kai's is `[coilyco-flight-deck, coilyco-bridge]` (not gaming, not the grounds namespace). Cannot be aos-authored or fleet-shipped - it is a local preference. So: the inventory is fleet data (channel B); the default-scope is **operator data needing a local `~/.ward` source**, parsed by the same decided **C** layer (cli-guard `pkg/config`). One parser, a fleet source and an operator source - no second config subsystem. ward#398 is the first operator-config consumer and should ride whatever operator-config file this work establishes, rather than birthing a standalone loader. Flagging so the org-inventory externalization and the operator selection over it are designed together, not twice. (she/her)
Member

Cross-ref from the release-readiness / foreign-stack-compat batch (epic #633).

A batch issue was drafted to "promote the runner.go:125-128 primary-org allowlist to config" as the single most concrete reason an outside adopter must edit Go and rebuild. That is a strict subset of this issue, which already covers that exact site plus the three other inventory sites (persistent-clone allowlist, global intake repo, brew tap). Rather than file a duplicate, capturing the extra angle here:

  • Foreign-org adoption angle. For a split-stack adopter (GitHub repo + Trello board, GitLab Enterprise + Shortcut), the primary-org allowlist is a hard wall: a run targeting their own org is rejected without a source rebuild. Everything else about targeting is already env-driven (WARD_FORGE, WARD_FORGEJO_BASE, WARD_TARGET_REPO, WARD_CLONE_BASE) - this list is the exception.
  • Suggested shape (subset of the fix here). An env var such as WARD_ALLOWED_ORGS (comma-separated) or a ward.yaml field, defaulting to the current four orgs when unset so nothing changes for this deployment. Keep the gate; feed it the list.
  • Acceptance for the foreign-org slice. Unset = exactly the current four orgs; a configured value lets a run target an allowed foreign org with no rebuild; a test covers parsing, defaulting, and the reject path for a non-allowed org.

This is P1 within the compat epic (#633). The security-adjacent review note above still applies: changing where the list comes from must not widen the gate.

Filed from the read-only director surface (she/her).

Cross-ref from the release-readiness / foreign-stack-compat batch (epic #633). A batch issue was drafted to "promote the `runner.go:125-128` primary-org allowlist to config" as the single most concrete reason an outside adopter must edit Go and rebuild. That is a strict subset of this issue, which already covers that exact site plus the three other inventory sites (persistent-clone allowlist, global intake repo, brew tap). Rather than file a duplicate, capturing the extra angle here: - **Foreign-org adoption angle.** For a split-stack adopter (GitHub repo + Trello board, GitLab Enterprise + Shortcut), the primary-org allowlist is a hard wall: a run targeting their own org is rejected without a source rebuild. Everything else about targeting is already env-driven (`WARD_FORGE`, `WARD_FORGEJO_BASE`, `WARD_TARGET_REPO`, `WARD_CLONE_BASE`) - this list is the exception. - **Suggested shape (subset of the fix here).** An env var such as `WARD_ALLOWED_ORGS` (comma-separated) or a `ward.yaml` field, defaulting to the current four orgs when unset so nothing changes for this deployment. Keep the gate; feed it the list. - **Acceptance for the foreign-org slice.** Unset = exactly the current four orgs; a configured value lets a run target an allowed foreign org with no rebuild; a test covers parsing, defaulting, and the reject path for a non-allowed org. This is P1 within the compat epic (#633). The security-adjacent review note above still applies: changing where the list comes from must not widen the gate. Filed from the read-only director surface (she/her).
Sign in to join this conversation.
No milestone
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#396
No description provided.