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
+31
View File
@@ -1,5 +1,36 @@
# Felhom Hub — Changelog
## v0.33.0 — S2 offsite connectivity: box-facing WG registration + wireguard desired-state block + /offsite UI (2026-07-04)
Doc 06 roadmap row S2 (commits `fcf84a0`/`ba52005`/`13203c2`); the S2 architectural decision:
the stored `desired_json` stays a pure OPERATOR blob — the WG assignment is HUB-owned state,
**merged into the served desired-state at READ time**, never written into the store.
- **Store** (`internal/store/wg.go` + `store.go`): `RegisterWGPeerForHost` (idempotent /
**re-key-in-place keeps the /32** — stable tunnel addressing across rotation/DR / adopt-unbound
S1 rows / typed `ErrWGPubkeyBoundElsewhere` — a key is never silently stolen); partial unique
index `idx_wg_peers_host` = one bound peer per host; `BumpHostDesired` bumps ONLY the
generation (the merge changes served state, not the blob); `allocateWGPeerTx` extracted from
the S1 path behavior-neutrally (S1 tests unmodified). `WGPeer` gains `CreatedAt`.
- **API** (`internal/api/wg.go` + `handler.go`): `POST /hosts/{id}/wg` — per-host key
SELF-SCOPED (global = operator/DR path); generation bump + endpoint push ONLY on real change
(idempotent re-register moves nothing — asserted negatives). `mergeWireguard` injects
`{endpoint{dns_name,wg_port,server_pubkey,pbs_tunnel_ip}, pubkey, assigned_ip}` into served
desired-state; no peer → **byte-identical pass-through** (the cross-repo golden test passes
UNMODIFIED); any merge failure → fail-safe unmerged serve (never 500 the control channel).
`handleAdminSetDesiredState` REJECTS a top-level `wireguard` key (400 — an operator
copy-paste-PUT can never clobber the hub-owned block). Admin DELETE of a BOUND peer bumps the
owning host; unbound deletes move no generation. NEW golden
`testdata/desired-state-wireguard.golden.json` = **the S3 cross-repo contract** (agent copy
must stay byte-identical).
- **UI** (`internal/web/offsite.go` + `templates/offsite.html`): read-only `/offsite` page —
endpoint card + peer table (truncated pubkeys, full value in title; bound peers link to
`/hosts/<id>`); Offsite nav link in all 9 page templates. Mutations stay on the admin API
(UI actions arrive with tunnel health, S3/S6).
- **Tests:** Groups A/B/C; five red-proofs run + reverted (self-scope drop, unconditional
merge, rejection drop, bump-on-idempotent, script exit-swallow — see scripts/CHANGELOG
v1.0.1). Old-agent (v0.63.0) tolerance proven live against the real felhom-pve record.
## v0.32.0 + v0.32.1 — S1 offsite connectivity: WG endpoint record + peer registry + pinned-SSH peer-sync (2026-07-04)
The hub side of doc 06's roadmap row S1 (`documentation/architecture/06-offsite-connectivity.md`),