Files
cc-ci/JOURNAL-1c.md
autonomic-bot f972bc1dc4
All checks were successful
continuous-integration/drone/push Build is passing
1c/W2: cc-ci-secrets repo created + populated (cert+infra in sops, verified)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:16:58 +01:00

4.6 KiB
Raw Blame History

JOURNAL — Phase 1c (Builder)

Append-only. Each entry: what I did + verifying command/output + next.

2026-05-27 — Phase 1c kickoff / orientation

Context: Phase 1 closed DONE (1c10fa5; all D1D10 Adversary-PASS, no VETO; Adversary loop terminated for Phase 1). Starting Phase 1c per plan-phase1c-full-reproducibility.md.

Did:

  • Read the phase plan in full + plan.md §6.1/§7/§9. Verified access & surveyed current state.
  • ssh cc-ci 'hostname && nixos-version && systemctl is-system-running'nixos / 24.11.20250630.50ab793 (Vicuna) / running. Healthy.
  • Surveyed secrets layout:
    • secrets/secrets.yaml holds 6 infra secrets: test_secret, drone_rpc_secret, drone_gitea_client_secret, bridge_drone_token, bridge_gitea_token, bridge_webhook_hmac.
    • .sops.yaml: recipients = &host (ssh-to-age of cc-ci ed25519 host key) + &master (off-box recovery, private at /srv/cc-ci/.sops/master-age.txt, sandbox-only).
    • modules/secrets.nix: defaultSopsFile = ../secrets/secrets.yaml, age.sshKeyPaths = ["/etc/ssh/ssh_host_ed25519_key"].
    • Wildcard cert OUT-OF-BAND at cc-ci:/var/lib/ci-certs/live/{fullchain.pem,privkey.pem} (fullchain 2909 B, privkey 227 B → privkey looks like an EC key). modules/proxy.nix reconcile reads it from there and inserts as traefik ssl_cert/ssl_key swarm secrets; treats a missing cert as FATAL (operator precondition).
    • flake.nix: nixpkgs pinned 50ab793, sops-nix pinned; single local nixosConfigurations.cc-ci.
  • Tooling note: sandbox host has NO sops/nix/age/ssh-to-age (which → only git). sops/age work must run on cc-ci (has nix + host age key) or via a sops binary fetched there with the master key.
  • Bootstrapped Phase-1c state: STATUS-1c.md, BACKLOG-1c.md, JOURNAL-1c.md (this file). REVIEW-1c.md left for the Adversary (its file per §6.1). Appended Phase-1c decisions to DECISIONS.md.

Decisions recorded (DECISIONS.md): secrets linkage = git submodule (deviates from the flake-input default — rationale: no private-repo fetch credential needed at nix-eval on every rebuild, keeps defaultSopsFile a local path = minimal change + trivially byte-identical); bootstrap key for throwaway = recovery age key via sops.age.keyFile.

Next (W2): create private recipe-maintainers/cc-ci-secrets; move secrets + wildcard cert into sops there as a submodule of the base; wire secrets.nix (cert→/var/lib/ci-certs/live via path=); prove byte-identical build + clean switch with TLS from the git cert. Then claim Gate W2.

2026-05-27 — W2 step 1: cc-ci-secrets repo created + populated (DONE)

Did:

  • Created private recipe-maintainers/cc-ci-secrets via Gitea API (bot, org admin). HTTP 201, private=True.
  • Confirmed cc-ci host SSH key → age identity == &host recipient age1h90utd…: ssh cc-ci 'nix shell nixpkgs#ssh-to-age --command ssh-to-age -i /etc/ssh/ssh_host_ed25519_key.pub' → exact match. So I can decrypt/re-encrypt on cc-ci with the host key (master stays sandbox-only).
  • Built secrets.yaml on cc-ci (script with file redirections, no key material in argv): sops -d existing 6 secrets → append wildcard_cert/wildcard_key as YAML block scalars from /var/lib/ci-certs/live/{fullchain.pem,privkey.pem}sops -e. Verified round-trip:
    • recipients: 2 (host+master)
    • keys: test_secret, drone_rpc_secret, drone_gitea_client_secret, bridge_drone_token, bridge_gitea_token, bridge_webhook_hmac, wildcard_cert, wildcard_key
    • cert sha256 file==decrypt c1d96d61…; key sha256 file==decrypt 9ec25d00…; test_secret decrypts OK
  • Retrieved ciphertext (7219 B) to sandbox; created cc-ci-secrets repo (root secrets.yaml, own .sops.yaml w/ path_regex: secrets\.yaml$, README). Pushed to main (auth via per-command http.extraHeader; verified .git/config has NO creds). Remote lists .sops.yaml/README.md/secrets.yaml.
  • Cleaned /root/cc-ci-secrets.yaml + build script off cc-ci.

Layout decision: cc-ci-secrets has secrets.yaml at ROOT → submodule mounts at base secrets/ → base sees secrets/secrets.yaml, so defaultSopsFile = ../secrets/secrets.yaml is UNCHANGED.

Next (W2 step 2): in base repo — replace tracked secrets/ with the submodule; add wildcard_cert/wildcard_key sops secrets in secrets.nix (path= → /var/lib/ci-certs/live, + recovery keyFile); adjust proxy.nix framing; switch cc-ci to new config via nixos-rebuild switch --flake 'git+file:///root/cc-ci?submodules=1#cc-ci'; prove byte-identical + TLS-from-git-cert; then claim Gate W2. (Riskier — touches live server config; fresh iteration.)