Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02994-7685-7940-bf34-3555b8256018
124 lines
8 KiB
Markdown
124 lines
8 KiB
Markdown
# 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?"**
|