docs: S2 shipped — hub v0.33.0 CHANGELOG, peersync v1.0.1, 06 §3.2 wire shape + S2 status, CONTEXT, REPORT

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
2026-07-04 01:20:10 +02:00
parent 99246c3c7d
commit 265f46c0e7
5 changed files with 164 additions and 82 deletions
@@ -63,11 +63,31 @@ New trust-boundary rows (extends 01 §5):
endpoint-mutation credential (out-of-band secret, never in desired-state).
- **Per-host peer entry** (joins the customer/host record, 01 §6): `wg_pubkey` (box-generated,
box-registered), `assigned_ip` (the box's tunnel `/32`, hub-assigned), `status`.
- **On the wire:** a `wireguard` block on `WireDesiredState` (`report.go:289` — sibling to
`Guests`/`RestoreDirective`, same forward-compat carriage rule as `report.go:284-288`: carried +
cached by old agents, acted on by new ones): endpoint coords + this box's assignment. Delivery
needs **zero new plumbing** — bump `DesiredGeneration`, the agent's existing syncer fetches
(`syncer.go:44-61`).
- **On the wire (S2-final — the shape S3 consumes; golden:
`hub/internal/api/testdata/desired-state-wireguard.golden.json`, agent copy must stay
byte-identical):** a `wireguard` key on the served desired-state, **merged at READ time**
the stored `desired_json` stays a pure operator blob (the hub REJECTS an admin PUT containing
a top-level `wireguard` key), hosts without a peer get byte-identical pass-through, and old
agents drop the unknown key in `encoding/json` (live-proven on v0.63.0):
```json
"wireguard": {
"endpoint": {
"dns_name": "ep0.felhom.eu",
"wg_port": 443,
"server_pubkey": "<44-char base64>",
"pbs_tunnel_ip": "10.77.0.1"
},
"pubkey": "<the box's registered pubkey>",
"assigned_ip": "10.77.0.2/32"
}
```
Client-side `AllowedIPs`, `PersistentKeepalive=25`, and `MTU 1420` are deliberately NOT wire
fields — S3 agent constants derived from `pbs_tunnel_ip` + §4. Delivery needs **zero new
plumbing** — registration/re-key/unbind bump `DesiredGeneration`, the agent's existing syncer
fetches (`syncer.go:44-61`). Re-key replaces the pubkey IN PLACE and keeps the `/32` (stable
addressing); one bound peer per host is index-enforced.
### 3.3 Provisioning handshake (Day-0 join)
@@ -204,7 +224,7 @@ block slices 1-2.
| Slice | Scope | Done = |
|---|---|---|
| **S1 — endpoint provisioning + peer-sync surface** — **SHIPPED 2026-07-04** (dev endpoint; hub v0.32.1). Peer-sync design point RESOLVED: **hub pushes over SSH** (`x/crypto/ssh`, `FixedHostKey` pin + pinned-type `HostKeyAlgorithms`) to a forced-command reconcile script; runbook `documentation/runbooks/offsite-endpoint.md`. Done-criterion met live: hub add/remove → `wg show` on the endpoint; tunnel `ep0.felhom.eu:443` → PBS through the wg0-only 8007 rule. | ~~provision the production VM…~~ (see runbook; production endpoint = a later re-run) | hub can add/remove a peer on the live endpoint via its credential; runbook re-creates the VM from nothing ✓ |
| **S2 — hub schema + desired-state** | endpoint coords + peer registry; `wireguard` block on `WireDesiredState`; box-facing pubkey-registration endpoint; generation bump on peer changes | a registered box's desired-state carries its assignment; hub UI shows the peer registry |
| **S2 — hub schema + desired-state** — **SHIPPED 2026-07-04** (hub v0.33.0). `POST /hosts/{id}/wg` (self-scoped) + merge-at-read `wireguard` block (§3.2 shape = the golden) + one-per-host index + re-key-in-place + `/offsite` UI page. Live-proven against the real felhom-pve record incl. old-agent (v0.63.0) tolerance. | ~~endpoint coords + peer registry…~~ | a registered box's desired-state carries its assignment; hub UI shows the peer registry |
| **S3 — agent WG service (the agent-managed-unit pilot)** | keygen + registration; reconcile `wg-felhom` from desired-state (sudoers additions on the `:16-18` pattern); re-resolve watchdog (§4.2); MTU 1420; IdentityBundle `+ WGPrivateKey`; tunnel-health into the report. **Risky/supervised class** (host service + sudoers + escrow change) | fresh box joins by §3.3 end-to-end; tunnel survives agent restart + endpoint re-IP; unhealthy tunnel alerts |
| **S4 — PBS over the tunnel** | point the box's PBS storage at `pbs_tunnel_ip:8007`; verify pin-through-tunnel | real backup lands in the box's namespace over the tunnel (nearly free — spike-proven path) |
| **S5 — DR re-establishment** | consume `WGPrivateKey` in restore mode; re-peer on re-provision | host-loss drill restores offsite connectivity with only the recovery code. *Merges with the DR-completeness arc.* |