railiance-infra/SCOPE.md
codex 969d42088d
All checks were successful
CI Smoke / source-contract (push) Successful in 14s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
SCOPE: record RAIL-HO-WP-0014 restricted agent host account
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 605711@bnt-lap001
Assistant-Session: 1f5e2256-181f-49ed-b7b1-a1c34bf37a61
2026-10-21 00:01:07 +02:00

262 lines
11 KiB
Markdown

# SCOPE
> This file describes the repository as it works today. Aspirational direction
> belongs in `INTENT.md`; known differences are recorded under `history/`.
---
## One-liner
The S1 host substrate for Railiance: source-backed inventory, Ansible OS
convergence, host firewall policy, SSH bootstrap, and recurring baseline
verification for the existing Railiance servers.
---
## Core Idea
`railiance-infra` owns host-level facts and controls below Kubernetes. It keeps
the current server identities in source, converges supported Linux hosts toward
a security baseline, and checks the resulting live state. A higher layer should
receive a reachable, hardened host rather than needing to configure the host
itself.
The two current managed hosts are existing Host Europe virtual servers. The
repository also contains a Hetzner Terraform and cloud-init path, but that path
is not an operable representation of the current inventory: it supports only
Hetzner and expects provisioning fields that the two adopted Host Europe
entries do not contain.
---
## In Scope
- Canonical connection inventory for `Railiance01` and `CoulombCore` in
`inventory/servers.yaml`
- Dynamic Ansible inventory, including per-host exceptions
- Debian/Ubuntu host convergence for base packages, SSH hardening, fail2ban,
timezone, swap, user resource limits, and host access keys
- Declared UFW management where `ufw_manage` is enabled
- Tunnel-only k3s API policy, source-restricted Flannel grants, and removal of
retired public grants
- Grant validation before opening public web ports 80/443 for a reef
- Installation of OpenBao SSH user-CA trust and per-user principals
- Restricted host accounts for supervised agents (principal, sshd `Match`
policy, allowed supplementary groups, Goss posture)
- Installation of SOPS/age tooling and SOPS-encrypted storage of the Hetzner
provider token
- Goss host checks, TAP evidence, and an hourly on-host pass/fail signal
- Non-secret `Railiance01` identity, capacity, utilization, and host-operations
evidence for downstream resource accounting
- Local age-encrypted snapshots of selected S1 OS configuration and installed
package selections
- A reference NetKingdom host-bootstrap capability declaration
---
## Out of Scope
- Kubernetes installation and runtime management (`railiance-cluster`, S2)
- OpenBao, databases, ingress, Forgejo, and other platform services
(`railiance-platform`, S3)
- Developer tooling and application deployment (S4/S5)
- Workload execution contracts (`rail-*`) and workload packaging (`rapp-*`)
- Reef topology, workload placement, and exposure decisions; this repo only
enforces a supplied substrate grant
- Provider billing, contracts, lifecycle dates, and cost records
- Secret issuance or live credential custody; this repo encrypts selected
material at rest and installs client tooling
- Host Europe provisioning or lifecycle automation; the current Host Europe
servers are adopted resources
- Cluster, database, or application backup and restore
Historical Forgejo migration and restore-drill material remains in this repo,
but it is not an S1 capability or an ownership precedent.
---
## Relevant When
- Adding or changing a managed host identity
- Converging or auditing host packages, SSH, fail2ban, UFW, swap, or resource
limits
- Changing host-level network grants or proving k3s API exposure remains
tunnel-only
- Installing SSH CA trust or automation public keys on a host
- Running or collecting host baseline checks
- Producing non-secret host-capacity evidence
- Developing or repairing the Hetzner provisioning path
---
## Not Relevant When
- The change is to Kubernetes objects, cluster components, platform services,
or applications
- The request is for a secret value, login token, provider contract, or invoice
- The decision concerns which workloads or rails belong in a reef
- A backup or restore concerns persistent application or cluster data
An already-provisioned host can still be in scope: convergence, firewall
maintenance, evidence collection, and drift checks are ongoing S1 work.
---
## Current State
- Status: maintained and operational for adopted-host convergence and
verification
- Managed inventory: `Railiance01` (`92.205.62.239`) and `CoulombCore`
(`92.205.130.254`), both reached as user `tegwick`
- `Railiance01`: UFW is managed from this repo; the k3s API is tunnel-only and
the Host Europe Nydus exception is declared
- `CoulombCore`: UFW is deliberately unmanaged because its live packet filter
has not been migrated safely to this repo's UFW model
- Verification: the executable baseline now resolves `ufw-managed` and
`external-firewall` profiles into both Ansible and Goss. The fail-closed
handoff command is remotely read-only, refuses a stale installed Goss
surface, and emits metadata-only receipts; a fresh attended all-host receipt
is still pending
- Provisioning: adopted and provider-managed records now have a validated
schema. Terraform selects only provider-managed Hetzner records, with mock
plan tests proving the current Host Europe records select no resources. It
does not provision either live Host Europe server
- Secrets: `secrets/hetzner-token.yaml` is SOPS-encrypted. The Ansible
`sops_agent` role installs tools but intentionally does not place a private
age key on a host
- Evidence: the latest committed `Railiance01` capacity observation is a
point-in-time record, not continuous resource telemetry
- Restricted agent account (RAIL-HO-WP-0014): `custodian-agt` on
`Railiance01`, principal `agt-custodian`, sshd `Match` allowing certificate
login only and no forwarding, Goss posture spec. Supplementary groups are
an explicit allow-list (`gexec-review`) set through `ssh_principals`
`restricted_account_groups` (`37ed8b0`). T02 was applied 2026-10-20. T03, which
retires `agt-task-bridge`/`agt-interhub-bootstrap` from `tegwick`, is open
---
## How It Fits
- Upstream tools: Ansible, Goss, SOPS/age, Terraform, SSH, and provider APIs
- Downstream: `railiance-cluster` depends on host reachability and an acceptable
S1 posture; higher layers depend on it transitively
- Access path: `ops-bridge` supplies the SSH tunnels used for private cluster
and State Hub access; this repo declares host-side SSH access and firewall
posture but does not own tunnel orchestration
- Resource accounting: `resource-control` consumes the non-secret evidence
interface under `docs/evidence/resource-hosteurope-railiance01/`; `fin-hub`
owns booked cost
---
## Terminology
- **Adopted host**: an existing provider resource represented and managed here,
but not created by this repo
- **Convergence**: applying Ansible roles to move a host toward declared state
- **Verification**: evaluating live host state with Goss
- **Substrate grant**: an approved host-level network opening supplied by the
owning reef declaration
- **S1**: the infrastructure-substrate layer below the cluster runtime
---
## Related / Overlapping
- `railiance-cluster` — owns the S2 Kubernetes runtime
- `railiance-platform` — owns S3 shared services and service data protection
- `ops-bridge` — owns workstation-to-host tunnel orchestration
- `resource-control` — owns the resource portfolio assembled from evidence
produced here
- `reef-*` repos — own substrate grouping and exposure intent
- `railiance-hosts` — superseded predecessor; not a second source of truth
---
## Getting Oriented
- Session and work routing: `AGENTS.md` and `.custodian-brief.md`
- Current host identities: `inventory/servers.yaml`
- Host convergence: `ansible/playbooks/bootstrap.yaml` and `ansible/roles/`
- Host-specific posture: `ansible/inventory/host_vars/`
- Firewall defaults: `ansible/roles/base/defaults/main.yml`
- Verification: `goss/baseline.yaml.j2`, `docs/verification.md`, and
`docs/conformance-loop.md`
- Hetzner prototype path: `terraform/hetzner/` and `docs/provisioning.md`
- Operator entry points: `make converge`, `make converge-check`,
`make converge-firewall`, `make verify`, and `make goss-status`
---
## Provided Capabilities
```capability
type: infrastructure
title: Adopted-host inventory and convergence
description: Resolve the two current server identities into Ansible inventory and converge supported Debian/Ubuntu host packages, SSH posture, fail2ban, swap, resource limits, and access keys.
keywords: [ansible, inventory, host, convergence, hardening, linux]
```
```capability
type: security
title: Host firewall grant enforcement
description: Converge declared UFW rules, keep the k3s API tunnel-only, restrict Flannel peers, revoke retired sources, and require a reef exposure grant before opening public web ports.
keywords: [ufw, firewall, k3s, tunnel, flannel, reef, exposure]
```
```capability
type: infrastructure
title: Recurring host baseline verification
description: Resolve host-specific profiles into Goss checks, run them on demand or hourly on-host, retain local failure state, collect TAP evidence, and support a fail-closed handoff receipt.
keywords: [goss, verification, drift, systemd-timer, tap, evidence]
```
```capability
type: security
title: SSH trust bootstrap
description: Install automation public keys and OpenBao SSH user-CA trust with host-specific authorized principals; certificate issuance remains with ops-warden.
keywords: [ssh, certificate-authority, openbao, principals, access]
```
```capability
type: security
title: Restricted agent host account
description: Converge a certificate-only host account for a supervised agent (custodian-agt, principal agt-custodian on Railiance01) with an sshd Match block that disables forwarding, an explicit supplementary-group allow-list via ssh_principals restricted_account_groups, and a Goss posture spec.
keywords: [ssh, restricted-account, supervised-agents, sshd-match, goss, principals]
```
```capability
type: infrastructure
title: Host capacity evidence interface
description: Collect a bounded, non-secret Railiance01 observation across provider metadata, operating-system capacity, and k3s allocatable state for resource-control.
keywords: [capacity, evidence, hosteurope, resource-control, inventory]
```
---
## Notes
The exact differences between this operational scope and the aspirational
mission in `INTENT.md` are assessed in
`history/2026-08-23-scope-against-intent.md`.
## Staged work-record generation — 2026-10-19
The repository explicitly opts into the shared staged work-record generator via
`.generated-work-records.json` and its dedicated `.generated-work-records.mk`.
`make generated-work-records` uses the existing State Hub renderer through the
Custodian adapter, stages only `WORK-RECORDS.md`, and refuses unreconciled
unstaged index edits. `make generated-work-records-check` checks without writes.
The shared commit hook retains its generated-only guard and repository-specific
scanner routing; meaningful source commits regenerate the index before any
configured scan.
Generation performs no Hub calls, commits, pushes, credential access or live
changes. Source inventories and other generated artifacts retain their owners.
## Local orientation brief policy — 2026-10-19
`.custodian-brief.md` is a local, ignored State Hub orientation snapshot. Its
existing bytes remain available for offline session startup; refreshing it does
not require a Git commit. Authored workplans and the generated WORK-RECORDS index
retain their existing source and staged-generation contracts. No runtime or
credential change follows from this repository hygiene policy.