From 4f8405495b04f400f77b93fb6adfc1ccbd3bbade Mon Sep 17 00:00:00 2001 From: Indra Gunawan <1284811+coderbuzz@users.noreply.github.com> Date: Thu, 15 Oct 2026 14:55:10 +0700 Subject: [PATCH] docs: record the Wave 7 re-audit result and the 0.7.0 release checklist Waves 0-5 (PRs #87-#92) are merged; this adds section 10 of the Fable audit: verification on final main, real-worker and production-copy checks, findings status, and the operator checklist for the 0.6.22 -> 0.7.0 release. Co-Authored-By: Claude Fable 5.1 --- audits/DOCKIFY-AUDIT-FABLE-5.1.md | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/audits/DOCKIFY-AUDIT-FABLE-5.1.md b/audits/DOCKIFY-AUDIT-FABLE-5.1.md index f39a78d..d1fb5df 100644 --- a/audits/DOCKIFY-AUDIT-FABLE-5.1.md +++ b/audits/DOCKIFY-AUDIT-FABLE-5.1.md @@ -656,6 +656,43 @@ deploy in flight; (4) run `update.sh`; (5) after start: `journalctl -u dockify` the migration log, `/api/apps` lists 26 apps, both workers show their routes on disk, one staging redeploy succeeds. +## 10. Wave 7 result — re-audit of `main` after Waves 0–5 (2026-10-15) + +Merged, in order, each reviewed and re-verified in a temporary worktree before merge: +#87 (Wave 0), #88 (Wave 1), #89 (Wave 2), #90 (Wave 3), #91 (Wave 4), #92 (Wave 5). +Code by Claude Opus 5.5 sessions, review and merge by Fable 5.1. Final `main`: +`1d79787`. + +### Verification on final main + +| Check | Result | +|---|---| +| `go build`, `go vet`, `gofmt -l cmd internal`, `go test -race ./...` | clean, all 11 packages pass | +| `govulncheck ./...` | 0 reachable vulnerabilities (x/crypto 0.56, Go 1.26 latest patch in CI) | +| CI (`build` job on PRs and `main`) | green on every wave PR | +| Mock-mode end-to-end with the final binary (curl / raw sockets) | CSP + nosniff + referrer headers; login 302; cross-site POST 403; cross-origin WebSocket handshake 403, same-origin 101, no cookie 302; server created without key returns `public_key`, init → online; app with `"`, space, `$`, `#` in an env value and a mixed-case domain deploys → running, domain lowercased; bad domain / `..` path / bad env key → 400; second redeploy while one runs → 409; `/static/htmx.min.js` served, `/static/` 404; export carries `domains`; undeploy → 404 afterwards; server delete 200 once empty; 11th bad login → 429; SIGTERM → clean shutdown | +| Vendored assets | sha256 of the four files re-checked against unpkg/jsdelivr: identical | +| Real workers (staging root/Photon, prod-heavy-1 dockify/Debian), `/tmp` only | TOFU pins the host key, reconnect accepted, a different key is rejected with "host key mismatch"; `WriteFile` round-trips byte-identical with mode 0600 for both users | +| Real compose parsers (v2.18.1 standalone, v5.3.1 plugin) | the new quoted `.env` yields the same values as the old unquoted format for plain, spaces, inner quotes, `$`, backslash; `#` after a space is kept (was truncated), newlines now work | +| Migration against a consistent copy of the production DB (twice, Wave 2 binary and final binary) | 14 s, `integrity_check` ok, 0 FK violations, routes 57 → 25 with no duplicates, all other counts unchanged, indexes created, dead server deletable, server with apps refused | + +### Findings status + +- Closed: S1–S15, S17, B1–B22, A1, A2, A4–A7. S14 was done in Wave 2. +- Not scheduled (by design): S16 (secrets at rest), P1/P2/A3 (Wave 6, only if measured; `PRAGMA synchronous=NORMAL` is the one-liner to start with). +- Verified only in mock mode / unit tests, to confirm after the release: B14 (live stats after a container restart), B11 (init against a worker that has a foreign Caddy), S7 (`systemd-run` self-update on the real controller; it also needs the first release that ships `dockify-linux-amd64.sha256`). + +### Release checklist (0.6.22 → 0.7.0) + +1. On the controller, before updating: `systemctl stop dockify`, copy `/var/lib/dockify/dockify.db` and its `-wal`/`-shm` files aside (5.7 GB free, the DB grows to ~350 MB during the rebuild), `systemctl start dockify`. +2. Add to `/opt/dockify/.env`: `DOCKIFY_TRUST_PROXY=true` (Caddy is in front: without it every browser shares the client key `127.0.0.1` and ten bad logins lock everyone out for 15 minutes) and `DOCKIFY_HOST=127.0.0.1` (Caddy already proxies to it; closes the plain-HTTP port 8080 to the internet). +3. Make sure no deploy is running, then from `main`: `./scripts/release.sh minor`; wait for the tag workflow (binary + `.sha256` + image). +4. Update the controller with `curl -fsSL https://raw.githubusercontent.com/coderbuzz/dockify/main/scripts/update.sh | bash` (verifies the checksum) or the Settings page. +5. After start: `journalctl -u dockify` shows `migrating database from version 0 to 4` … `database at version 4` and `pinned host key for …` on the first connections; `/api/apps` lists 26 apps; the dead server `production-1` can now be deleted from the UI. +6. Redeploy one staging app and compare the container's env with the previous values (the 24 values with quotes/spaces/`$`/`#` are now written quoted); then check that `/opt/dockify/caddy/config.json` on that worker contains its routes. +7. Optional on both workers: delete `~/.ssh/dockify` and `~/.ssh/dockify.pub` (the private keys generated by the old setup script); keep their lines in `authorized_keys`. +8. Docker-compose installs (none in production) must re-download `docker-compose.yml` to pick up B10. + ## 8. Repository hygiene done during this audit - Deleted remote branch `claude/trusting-volta-c2xw1b` (merged in PR #79) and, on