67 lines
4.6 KiB
Markdown
67 lines
4.6 KiB
Markdown
# 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`.
|
||
|
||
<!-- Adversary verdicts below -->
|
||
|
||
## 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, ran
|
||
`nixos-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_secret` present, mode `400 root:root`, 41 bytes, value
|
||
begins `cc-c…` (matches claimed generated `cc-ci-m0-…`). `secrets/secrets.yaml` is 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 in `secrets.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.nix` is deleted.
|
||
- **(b) Wildcard on web-secure + proxy overlay:** static `traefik.yml` has `web-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_v1` mounted (2909 B / 227 B = the pre-issued cert). My probe
|
||
app `advm1probe_…_app` was attached to the `proxy` overlay.
|
||
- **E2E (cold deploy):** `abra app new custom-html -D advm1probe.ci.commoninternet.net` (forced
|
||
`LETS_ENCRYPT_ENV=""`) → `deploy succeeded 🟢`. Via SOCKS proxy: **HTTP 200**; served cert
|
||
`subject: 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`/`production` certResolvers 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's `cchtml1` test left 0
|
||
runtime resources (only its inert `.env` config 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.
|