4.6 KiB
REVIEW — cc-ci Adversary (append-only)
This file is owned by the Adversary loop (§6.1). The Builder seeds this stub at bootstrap and
does not edit it afterward. Adversary appends milestone/D-item verdicts (<id>: PASS @<ts> +
evidence, or FAIL + a finding in BACKLOG.md ## Adversary findings), and may write ## VETO.
M0 — Foundations: PASS @2026-05-26T21:35Z
Verified cold (fresh shell, own clone /srv/cc-ci/cc-ci-adv, isolated host build dir
/root/cc-ci-advverify, no reuse of Builder's /root/cc-ci).
Acceptance — "systemctl is-system-running healthy after a rebuild from the repo" + Builder's
sops claim:
- Repo rebuilds cc-ci: synced M0 commit
deb4a0f(git-archive, no .git) to host, rannixos-rebuild build --flake .#cc-ci→BUILD EXIT 0, produced…-nixos-system-nixos-24.11.20250630.50ab793. Current HEAD also builds clean. - System health:
systemctl is-system-running→running;systemctl --failed→ 0 units. - sops decrypt:
/run/secrets/test_secretpresent, mode400 root:root, 41 bytes, value beginscc-c…(matches claimed generatedcc-ci-m0-…).secrets/secrets.yamlis genuinely encrypted (2×ENC[…]+ sops metadata block). - D6 leak probe (early): the decrypted plaintext value appears 0 times across all git
history (
git grep -F over git rev-list --all) and 0× in plaintext insecrets.yaml. No leak.
Note (not a finding; context for the M1 gate): the running system is already ahead of M0 — its
closure includes docker, unit-swarm-init, and traefik units (traefik.yml,
traefik-stack.yml, unit-traefik-deploy) that are not yet committed (HEAD ab839ae is
swarm-only, no traefik). Expected mid-M1 churn, but the Traefik config must be committed to the
repo before M1 is claimed or it fails D8 reproducibility — will check at the M1 gate.
M1 — Swarm + abra target: PASS @2026-05-26T22:20Z
Verified cold from own clone; deployed my own probe recipe via abra (not trusting the Builder's
hand-test). Acceptance "a recipe deployed via abra is reachable over HTTPS at
*.ci.commoninternet.net, then fully torn down leaving no volumes" + orchestrator's M1 checklist
(a–d).
- (a) Real coop-cloud/traefik recipe (not hand-rolled):
docker service ls→traefik_…_app(traefik:v3.6.15) +…_socket-proxy(lscr.io socket-proxy) — the canonical recipe layout, deployed via abra (scripts/deploy-proxy.sh).modules/traefik.nixis deleted. - (b) Wildcard on web-secure + proxy overlay: static
traefik.ymlhasweb-secure: :443(web→web-secure 301 redirect, verified live). File provider/etc/traefik/file-provider.yml:tls.certificates: [{certFile:/run/secrets/ssl_cert, keyFile:/run/secrets/ssl_key}]; swarm secrets…_ssl_cert_v1/…_ssl_key_v1mounted (2909 B / 227 B = the pre-issued cert). My probe appadvm1probe_…_appwas attached to theproxyoverlay. - E2E (cold deploy):
abra app new custom-html -D advm1probe.ci.commoninternet.net(forcedLETS_ENCRYPT_ENV="") →deploy succeeded 🟢. Via SOCKS proxy: HTTP 200; served certsubject: CN=*.ci.commoninternet.net, SAN-matched,SSL certificate verify ok, issuer LE E8 — i.e. the pre-issued wildcard, NOT a per-host ACME cert. - (c) No Gandi/DNS token, no ACME credential: repo (all history) clean; on host the only
gandi/dns-challenge strings are commented-out recipe-template options (
#GANDI_…,#SECRET_GANDIV5_…) holding no value. Active traefik env =LETS_ENCRYPT_ENV=(empty),WILDCARDS_ENABLED=1,compose.wildcard.yml.staging/productioncertResolvers are defined in traefik.yml (stock template) but referenced by no router; both acme.json are 0 bytes; 0 ACME lines in traefik logs. No ACME ever fires. (Hardening risk filed — see findings.) - (d) Manual renewal documented: DECISIONS.md — operator re-issues at same paths, then
abra app secret rm … ssl_cert+ re-insert at bumped version; install.md "Renewed out-of-band; never ACME here." - Teardown:
abra app undeploy+volume remove→ post-teardown services/containers/volumes/ secrets for the probe all 0. Also independently confirmed the Builder'scchtml1test left 0 runtime resources (only its inert.envconfig file remains, harmless).
Verdict: M1 PASS. Not a hard fail on (c) — no token/credential exists and no ACME fires — but
the inert ACME resolvers + test-app default LETS_ENCRYPT_ENV=production are a latent hazard that
goes live when the harness deploys apps; filed as [adversary] for M4.