railiance-infra/history/2026-08-23-scope-against-intent.md
codex 3734a1c3bc
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Document actual infrastructure scope and intent gaps
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a02994-7685-7940-bf34-3555b8256018
2026-08-23 10:45:02 +02:00

8 KiB

Scope Against Intent Assessment — 2026-08-23

Purpose

This assessment compares the repository's executable state on 2026-08-23 with the stable direction in INTENT.md. It describes gaps; it does not create or authorize implementation work.

The assessment was made after confirming that the repository had no actionable local work: no ready, active, or blocked workplan; no task assigned to railiance-infra in todo, progress, or wait; no unread inbox message; no active repo dispatch; and no open Forgejo issue or pull request.

Overall Assessment

The repository is a useful host-convergence and verification substrate, but it does not yet meet the full intent of reproducibly turning bare machines into a verified handoff. Its strongest implemented area is post-provisioning host control. Its largest gap is the seam before that: neither current Host Europe server is provisioned from source, and the only Terraform module cannot consume the current inventory.

The intent is therefore partially realized. The repo can maintain important parts of S1 for existing hosts; it cannot currently rebuild the live S1 estate from its declared source alone.

Principle-by-Principle Assessment

Intent principle Assessment Current evidence Gap
Declarative and reproducible Partial Ansible roles, firewall variables, a baseline spec, dynamic inventory, and a Hetzner Terraform module are source-controlled. The live hosts are adopted Host Europe resources. The Terraform module iterates every inventory entry but requires type, region, image, and role, which the current entries lack. Host Europe lifecycle is manual, and no source path can recreate the current estate end to end.
Hardened by default Partial SSH password/root login are disabled by Ansible; fail2ban and UFW policy exist; k3s API access is tunnel-only; public web ports require a reef grant. Hardening is applied after access exists rather than guaranteed as one provisioning transaction. CoulombCore deliberately bypasses UFW management. The generic cloud-init template still contains a placeholder SSH key and is not the Terraform template.
Verified before handoff Partial Goss renders inventory-aware checks, emits TAP, and runs hourly plus five minutes after boot. The uniform baseline intentionally fails on CoulombCore because UFW is inactive. Verification is not a mandatory provisioning/handoff gate, and no repository CI exercises the Ansible/Goss contract.
Recorded source of truth Partial inventory/servers.yaml records the two names, IPs, and SSH users; host variables record the CoulombCore exception; Railiance01 has a non-secret evidence interface. The inventory is authoritative for connection identity but not full resource shape or lifecycle. Current-host provider, location, flavor, image, and role are not modeled there. Evidence coverage is asymmetric and point-in-time.
Secure at rest Partial The Hetzner token is SOPS/age encrypted and repo hooks check files under secrets/. The host role installs SOPS/age without placing the private age key. Rotation is manual. inventory/group_vars/secrets.sops.yaml is a plaintext placeholder outside the hook's checked path, while the docs describe it as encrypted input. The implementation and documentation disagree about the provider-token source.
Foundation, not tenant Mostly met Active convergence, firewall, SSH, inventory, and verification code stay at host level; cluster and platform ownership are documented elsewhere. Historical Forgejo migration, runner, and restore-drill artifacts remain in the repo and blur discovery, although they do not form the current S1 execution path.

Direction-of-Evolution Assessment

Stronger reproducibility and drift detection — partial

The hourly Goss timer is a real drift detector and its firewall assertions are derived from the same inventory variables used for convergence. It records a host flag and journald event, with an optional State Hub progress post.

Gaps:

  • No central reaction is guaranteed; paging, task creation, and rollout blocking belong elsewhere and are not wired as a dependable end-to-end loop.
  • spec/server-baseline.yaml is described as authoritative but is not consumed by Ansible or Goss. Maintaining the spec, roles, and template remains a manual three-way synchronization task.
  • The declared spec and convergence are already imperfectly aligned: for example, the spec requires htop and a tegwick passwordless-sudo posture, while the base role does not establish both of those properties.
  • A known expected failure means the all-host signal cannot distinguish only new regressions without host-profile semantics.

Broader provider support — gap

Only Hetzner has Terraform resources. Host Europe is represented by adopted identity/evidence and manual lifecycle notes, not a provider implementation. The current single inventory cannot safely mix adopted Host Europe records with the Hetzner for_each model.

Continuous baseline verification — partial

The on-host hourly timer satisfies the cadence part of the direction. It is not yet a complete continuous assurance capability because deployment does not require a fresh green result, the failure route is optional, and one managed host is expected to remain red.

Automated rotation of at-rest secret material — gap

The repository provides sops --rotate as an operator command. It has no scheduled or policy-driven rotation, recipient-age enforcement, rotation receipt, or consumer rollout verification.

Self-evidencing, auditable provisioning — partial

Goss TAP reports, capacity observations, ADRs, and workplan evidence are useful records. The actual create/apply/converge sequence has no unified immutable receipt tying together source revision, provider plan, created resource, cloud-init completion, Ansible result, and a fresh verification result.

The local S1 backup command encrypts selected /etc files and package selections, but it is not scheduled, does not copy off-host, and has no restore procedure or drill in this repo. It should not be treated as proof that the substrate is recoverable.

Concrete Gaps, Ordered by Leverage

  1. Separate adopted and provisionable inventory semantics. Add an explicit provider/lifecycle mode and validate the schema, or give each provider a filtered declaration. A Terraform plan must never interpret an adopted Host Europe entry as a Hetzner resource.
  2. Make one baseline contract executable. Generate convergence and checks from a shared model, or add automated tests that fail when the human spec, Ansible roles, and Goss assertions diverge.
  3. Define host profiles and a real handoff gate. Express the CoulombCore firewall exception in verification rather than accepting a permanently red host, and require a fresh result before S2 handoff.
  4. Repair the secret-source contract. Remove or encrypt the plaintext placeholder file, extend plaintext checks to every declared secret path, and make the documentation name the provider-token source actually used by the Makefile.
  5. Capture provisioning receipts. Record source revision, plan/apply identity, provider resource identifiers, convergence result, and verification result without recording secrets.
  6. Close recovery and rotation loops. Automate age-recipient rotation with evidence, and give the local S1 backup a scheduled off-host copy plus a tested restore procedure if live-state backup remains part of this repo.
  7. Reduce scope noise. Archive or relocate historical Forgejo/platform artifacts so current S1 ownership is evident from the file tree as well as from SCOPE.md.

Bottom Line

Today the repo can answer: "How do we keep these existing Linux hosts closer to a hardened, observable S1 baseline?"

It cannot yet answer the full guiding question in INTENT.md: "Can we rebuild the live substrate from source and prove, through a mandatory auditable gate, that it is ready before higher layers use it?"