fleets v2: final-review fixes — audit shape, help verb, ActiveNav, pools recipe, Hardening heading
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4 files changed,
+17
−8
docs/superpowers/specs/2026-08-10-fleets-console-design.md+10 −3internal/console/fleets.go+2 −1internal/console/templates/fleet_byo.html+1 −1main.go+4 −3
diff --git a/docs/superpowers/specs/2026-08-10-fleets-console-design.md b/docs/superpowers/specs/2026-08-10-fleets-console-design.md| index 8d04feed0..851b823c5 100644 |
| --- a/docs/superpowers/specs/2026-08-10-fleets-console-design.md |
| +++ b/docs/superpowers/specs/2026-08-10-fleets-console-design.md |
| @@ -132,9 +132,16 @@ grammar is validated server-side (reject, don't sanitize). |
| 1. **This branch** (stacked on #63): everything above. Merges after #63; |
| deploy = binary roll + console restart (new templates/endpoints). |
| -2. **Free-tier office box** (ops): office box joins with |
| - `CARLOS_POOLS=free`, free accounts' manifests get `pool: free`. Recipe in |
| - the BYO/ops docs; no code. |
| +2. **Free-tier office box** (ops): office box joins with `CARLOS_POOLS=free` |
| + in its host env; free-tier apps are enabled operator-side with |
| + `carlos instances enable -pool free` (store mode; signed-in mode refuses |
| + `-pool`) so every instance record created under that app inherits |
| + `pool: free` (`provision.Record.Pool`, stamped from the manifest at |
| + create, `apiinstances.go`); `poolServed` at reconcile |
| + (`internal/provision/reconcile.go`) then scopes that box's |
| + provision/adopt passes to instances whose pool it actually serves, so the |
| + office box only ever picks up free-tier instances. This paragraph is the |
| + canonical recipe; no code change. |
| 3. **Shared fleet build-out** (pinfra): `region-host` boxes for `us`, `ie`, |
| `uk`, `au`; console (control) pinned in the IE AZ. Region *placement |
| values* (`place=us|…`) remain future per v1 — day one, regions appear as |
diff --git a/internal/console/fleets.go b/internal/console/fleets.go| index 6c51ca487..5d010fd6f 100644 |
| --- a/internal/console/fleets.go |
| +++ b/internal/console/fleets.go |
| @@ -405,7 +405,7 @@ func (s *Server) handleAPIFleetTagBox(w http.ResponseWriter, r *http.Request) { |
| jsonError(w, http.StatusInternalServerError, "could not tag the box — try again") |
| return |
| } |
| - s.audit(acct, "", addr, "fleet", "tagged "+fleet.Name+"/"+label+" ["+tags+"] (cli)") |
| + s.audit(acct, fleet.Name, addr, "fleet-tag-box", "tagged "+fleet.Name+"/"+label+" ["+tags+"] (cli)") |
| writeJSON(w, http.StatusOK, map[string]any{}) |
| } |
| @@ -1071,6 +1071,7 @@ func (s *Server) handleFleetPage(w http.ResponseWriter, r *http.Request) { |
| } |
| p := s.accountPage(w, r, addr, raw, acct, role) |
| p.Title = fleet.Name |
| + p.ActiveNav = "fleet" |
| p.FleetDetail = fleet |
| boxes, apps, warn := s.loadFleetPage(r.Context(), reg, acct, fleet) |
| p.FleetBoxes = boxes |
diff --git a/internal/console/templates/fleet_byo.html b/internal/console/templates/fleet_byo.html| index 5fd76c0f2..5d88b38c2 100644 |
| --- a/internal/console/templates/fleet_byo.html |
| +++ b/internal/console/templates/fleet_byo.html |
| @@ -39,7 +39,7 @@ CARLOS_TUNNEL_NAME=<name>/<label></code></pre> |
| <code>CARLOS_TUNNEL_NAME</code>'s label half. <code>AWS_SHARED_CREDENTIALS_FILE</code> points at |
| an access key for the bucket above, written root-owned mode 600 alongside the env file.</p> |
| -<h2>Harden it</h2> |
| +<h2>Hardening</h2> |
| <ul> |
| <li>Run the agent as a dedicated non-root user, not root.</li> |
| <li>Make the env file root-owned, mode 600 — it holds the tunnel token.</li> |
diff --git a/main.go b/main.go| index 56844d97b..c69f51ff7 100644 |
| --- a/main.go |
| +++ b/main.go |
| @@ -142,9 +142,10 @@ Your deployment — stand up and administer boxes, routes and accounts |
| bootstrap prepare a host: units, dirs, user |
| accounts the tenancy primitive: create | list | migrate |
| fleets account-owned groups of remote boxes that dial this |
| - console: create | add-box | rotate-token | detach-box | |
| - ls — box tokens print exactly once, at mint or rotate, |
| - and a compromised box needs detach-box, not rotate-token |
| + console: create | add-box | rotate-token | tag-box | |
| + detach-box | ls — box tokens print exactly once, at mint |
| + or rotate, and a compromised box needs detach-box, not |
| + rotate-token |
| add route a hostname on this box to an app |
| remove drop one of this box's routes |
| route repoint a route's channel or config environment, grant or |