REPORT: slice 8A controller half (bootstrap ingestion + pinned local-API client, v0.35.0)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
|||||||
|
# REPORT — slice 8A (controller half): bootstrap.json ingestion + pinned agent local-API client (v0.35.0) (2026-06-10)
|
||||||
|
|
||||||
|
> Overwrite-latest report (most recent significant work only). Cumulative history lives in
|
||||||
|
> [CHANGELOG.md](CHANGELOG.md). Implements the in-guest controller half of `TASK — Slice 8A`. The
|
||||||
|
> host-agent half is in `felhom-agent` v0.10.0. No hub change.
|
||||||
|
|
||||||
|
## Outcome
|
||||||
|
|
||||||
|
The controller now ingests the host agent's stable **`bootstrap.json`** on first run and reaches the
|
||||||
|
agent's **local API** over the bridge with a pinned client. With the agent half, this completes the
|
||||||
|
provisioning chain: a freshly provisioned guest's controller **comes up configured (skipping the
|
||||||
|
setup wizard) and talks to the agent** — validated live end-to-end on the demo. No behaviour change
|
||||||
|
for an already-configured controller.
|
||||||
|
|
||||||
|
## What landed
|
||||||
|
|
||||||
|
- **`internal/bootstrap`** — first-run **`bootstrap.json` ingestion** (config-contract decision (c)).
|
||||||
|
On startup, if the controller is NOT yet configured AND the agent's back-half attached a
|
||||||
|
`bootstrap.json` config mount, the controller **seeds `controller.yaml` from it and comes up
|
||||||
|
configured, skipping setup mode**. **Idempotent** (an existing `controller.yaml` is never clobbered)
|
||||||
|
and **fail-safe** (a malformed / absent / missing-identity / unsupported-schema bootstrap leaves the
|
||||||
|
controller in setup mode — logs, never crashes). The agent emits the stable contract; the controller
|
||||||
|
owns the translation (decoupled — no shared config schema).
|
||||||
|
- **`internal/agentapi`** — a minimal **pinned client** for the agent local API: reaches the agent
|
||||||
|
over the bridge **pinning the agent leaf-cert SHA-256** from the bootstrap (fails closed on
|
||||||
|
mismatch — exact leaf-DER match in `VerifyPeerCertificate`, the same pin convention the agent uses
|
||||||
|
for the Proxmox/PBS host certs) + the per-guest bearer token. In 8A it exercises `GET /storage`
|
||||||
|
(connectivity + the controller learning its mounts); the `/backup/due` quiesce loop is 8B.
|
||||||
|
- **`config.LocalAPIConfig`** (`local_api`: endpoint, fingerprint, token) seeded from the bootstrap;
|
||||||
|
a startup **probe** proves the channel and logs this guest's mounts (non-fatal).
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
`go test ./...` green. bootstrap: seeds when unconfigured (reloads configured, skips setup); never
|
||||||
|
clobbers a configured controller; stays in setup on malformed / missing-identity / unsupported-schema
|
||||||
|
/ absent bootstrap. agentapi: correct pin + token reaches `/storage`; a **wrong pin fails closed**; a
|
||||||
|
bad fingerprint is rejected at construction; colon-separated fingerprints accepted.
|
||||||
|
|
||||||
|
## Live validation (demo-felhom)
|
||||||
|
|
||||||
|
The controller (v0.35.0, **baked into the new golden**, deployed by the golden's bootstrap unit with
|
||||||
|
no registry pull) **ingested `bootstrap.json` → seeded `controller.yaml` → came up CONFIGURED**
|
||||||
|
(`felhom-controller v0.35.0 starting (customer: cust-8201, …)`, not setup mode), then reached the
|
||||||
|
agent's real local-API `GET /storage` over the bridge (leaf-pin + token) → **channel up, 1 mount
|
||||||
|
visible**. The test guest was torn down after validation.
|
||||||
|
|
||||||
|
## Deferred (stated, not built)
|
||||||
|
|
||||||
|
The full local-API usage — the `GET /backup/due`-driven **quiesce → `POST /backup` → unquiesce**
|
||||||
|
app-consistent loop → 8B. Controller de-privileging (retire the disk-execution subsystem; customer
|
||||||
|
disk endpoints behind the slice-4 classifier) → 8C. No secrets committed (the per-guest token arrives
|
||||||
|
via the agent-written 0600 bootstrap mount; it is never logged or committed).
|
||||||
Reference in New Issue
Block a user