railiance-infra/docs/conformance-loop.md
codex 40e295e3bd
All checks were successful
CI Smoke / source-contract (push) Successful in 8s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Make S1 handoff read-only by default
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a02994-7685-7940-bf34-3555b8256018
2026-08-23 12:41:23 +02:00

64 lines
2.8 KiB
Markdown

# Declared-vs-live conformance loop
This is the S1 slice of the unowned **Q7 Governance and Change Management**
gap recorded in `railiance-platform/ArchitectureBlueprint.md` §5.3. The
family owner of the loop is **`railiance-master`**. This repo owns the host
check and the first reaction path; it does not own rapp/rail/reef schema
conformance (that is 10c, blocked on the family declaration validator).
## What runs
| Piece | Where | Cadence |
| --- | --- | --- |
| Rendered Goss baseline | `/etc/goss/baseline.yaml` from `goss/baseline.yaml.j2` | reviewed converge or `make verify-refresh*` |
| On-host timer | `railiance-goss-baseline.timer` | hourly, plus 5 minutes after boot |
| Wrapper | `/usr/local/sbin/goss-baseline-check` | writes `/var/lib/railiance/goss/` |
| Operator collect | `make goss-status` | on demand |
| Operator run | `make verify` / `make verify-host HOST=…` | on demand; read-only remotely, writes transient TAP locally |
The firewall assertions are generated from the same inventory lists that
converge UFW (`k3s_api_allowed_sources`, `k3s_api_revoked_sources`,
`flannel_vxlan_allowed_sources`, `ufw_extra_allowed`). They assert:
- each declared source is present
- the **count** of non-Anywhere 6443/8472 allows equals the declared length
(extra hand grants fail)
- no `ALLOW Anywhere` on 6443 or 8472
- every revoked 6443 source is gone
That is the check that would have caught `89.244.90.248` appearing on
Railiance01 after T01.
## Where failures go
1. **journald**`logger -t railiance-goss`
2. **on-host flag**`/var/lib/railiance/goss/FAILED` and `last.status`
3. **optional State Hub POST** — set `RAILIANCE_GOSS_NOTIFY_URL` on the host
to a State Hub `/progress/` endpoint. The wrapper notifies only on a
pass↔fail transition, so a known-fail host (CoulombCore, UFW inactive)
does not spam.
4. **controller TAP**`make verify` writes ignored
`reports/goss-<host>-<ts>.tap`; reviewed durable evidence is promoted
deliberately under `docs/evidence/`
`make goss-status` fails the play if any host still has the `FAILED` flag.
## Routing to Q7
`railiance-master` owns the conformance loop as a family capability
(ArchitectureBlueprint §5.3; RAILIANCE-WP-0016 item 10b). This file is the
handoff:
- S1 check: **exists and is scheduled** in this repo
- S1 reaction: journald + flag + optional progress event
- Family reaction (page a human, open a task, block a rollout): **not here**
Do not build a second alert path in `railiance-telemetry` for the same
"check failed → someone sees it" plumbing. Item 9b should reuse this.
## Host profiles
`Railiance01` selects `ufw-managed`; `CoulombCore` selects
`external-firewall`. The latter does not turn an unmanaged control into a
pass: it asserts the documented replacement control, an iptables INPUT
default-drop policy. An absent replacement control is a failure.