# Review of the Setu phase 1 spec and plan (2026-10-09)

Published 2026-10-21 · Canonical: https://setucp.com/docs/specs/10-09-setu-review

---

An independent reviewer (fresh context, read-only) reviewed revision 1 of the spec and plan. Verdict: architecture sound; plan not executable without security-critical guessing. Every Critical and Important finding below was resolved in revision 2 of the spec and plan; the resolution is recorded here so the reasoning survives.

## Critical

## Important

## Minor (all applied)

Domain normalisation specified; agent derives paths from the id only; agent refuses `http://` without `--insecure`; join token on stdin/env; join idempotent for 60 s; e2e manifests rendered per version; server status computed only; `JobCtx` logging is async; `DbAgentClient` defined once (Task 8); `setup/local-server` in Task 14's interfaces; job kinds for restart/stop/start; `setu backup` in Task 14; TOTP cut; disk quota reported only; `metrics.prune` called by the scheduler; rust-embed `allow_missing`; CI uses `test-pg.sh`; task count fixed; skeleton file list corrected; clippy block copied; package names declared; operator password on stdin; capacity rule includes overhead.

## Scope cuts accepted

Container image of Setu, aarch64, Swagger UI, TOTP, operator tokens and CLI, audit UI page, metric charts, fleet rollout batches, `update.strategy = "command"`, enforced disk quotas.

## Items the reviewer could not verify — checked 2026-10-09

## Second pass (revision 2 → revision 3)

A second independent reviewer checked revision 2 against the first pass's claimed resolutions and found the gaps below. All are resolved in spec revision 3 and plan revision 3.

Minors from the second pass applied: setuid entries refuse the whole install; `Health{site}` only; reveal audited per call; alphanumeric `password20`; once/health app contract documented; lock literal `0x5e7a`; install semaphore tested; agent unit without `NoNewPrivileges`; apt installs `sudo gnupg`; every task has a run command and an expected count; scheduler and join tests use an injected clock or a direct `UPDATE`; e2e on a dedicated Docker network; Vyasa provisioning held to 60 s; CLAUDE.md remote and layout lines corrected; ui-implementer points at §7; skills corrected.

Still unverified (for the implementing session): Vyasa 0.2.0's login route and any Origin requirement (e2e assertion 12 sends `Origin`); `visudo -cf` ownership checks on a non-root-owned file (Task 10b ledgers the outcome); Caddy admin `Host` handling over a unix socket; GitHub-runner behaviour with `--cgroupns=private`.

## Revision 3 → as built (spec revision 4, 2026-10-10)

Phase 1 was built on branch `mvp` against revision 3 (gap work list `docs/plans/2026-10-09-rev3-gap.md`, work sets WS1–WS12). Where the build had to depart from revision 3, the departure is a ruling in `the ledger (private planning repository)`; spec revision 4 folds them in and cites each one inline. The rulings that changed the spec text:

Ledger rulings superseded along the way (R30, R35, R36, R37, R41 and R62) are marked at the end of the ledger.

### The four "still unverified" items

Also measured: provisioning `hello` took 8.2 s and Vyasa 0.2.0 about 9 s in the e2e container on this host; a Hetzner measurement is still open.
