Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02994-7685-7940-bf34-3555b8256018
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.yamlis 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
htopand ategwickpasswordless-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
- 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.
- 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.
- 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.
- 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.
- Capture provisioning receipts. Record source revision, plan/apply identity, provider resource identifiers, convergence result, and verification result without recording secrets.
- 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.
- 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?"