v0.19.0: bootstrap contract v2 — relay hub retrieval passphrase (no host key in guest)

Lockstep with felhom-controller v0.40.0. The agent now bakes a v2 bootstrap.json
carrying only what the controller needs to PULL its config from the hub:
customer.id + hub.url + hub.retrieval_password + the per-guest local_api. Stops
baking the agent's host hub key/host_id (and customer name/domain/email) into the
guest — the controller gets the customer-scoped key from the hub pull.

- internal/provision/doc.go: SchemaV2; DocCustomer{id}; DocHub{url,retrieval_password}.
- backhalf.go: render v2; require customer.id + hub.url + hub.retrieval_password.
- cmd/.../main.go --selftest=provision: new required -hub-password flag; stop
  baking APIKey/HostID; -customer-domain/name/email accepted but not baked.
- configs/build-golden.sh: default CONTROLLER_IMAGE off stale :v0.35.0 -> :0.40.0.
- doc_test.go/backhalf_test.go updated to v2 shape.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-11 13:22:51 +02:00
parent e4dfe5ccc7
commit e5a18194f4
7 changed files with 88 additions and 48 deletions
+6 -3
View File
@@ -54,8 +54,8 @@ func testLogger() *slog.Logger { return slog.New(slog.NewTextHandler(io.Discard,
func newInput() Input {
return Input{
VMID: 8200,
Customer: DocCustomer{ID: "cust-8200", Domain: "cust8200.felhom.eu", Name: "Teszt"},
Hub: DocHub{URL: "https://hub.felhom.eu", APIKey: "HUBKEY", HostID: "demo-felhom-01"},
Customer: DocCustomer{ID: "cust-8200"},
Hub: DocHub{URL: "https://hub.felhom.eu", RetrievalPassword: "five-word-passphrase"},
Endpoint: "192.168.0.162:8443",
Fingerprint: "ab12cd",
}
@@ -95,9 +95,12 @@ func TestProvision_WritesChownsAndAttaches(t *testing.T) {
if err := json.Unmarshal(raw, &doc); err != nil {
t.Fatalf("bootstrap not valid JSON: %v", err)
}
if doc.Schema != SchemaV1 || doc.Customer.ID != "cust-8200" || doc.LocalAPI.Token != "SECRET-TOKEN-XYZ" {
if doc.Schema != SchemaV2 || doc.Customer.ID != "cust-8200" || doc.LocalAPI.Token != "SECRET-TOKEN-XYZ" {
t.Fatalf("bootstrap content wrong: %+v", doc)
}
if doc.Hub.URL != "https://hub.felhom.eu" || doc.Hub.RetrievalPassword != "five-word-passphrase" {
t.Fatalf("hub wrong (want url + retrieval_password, no host key): %+v", doc.Hub)
}
if doc.LocalAPI.Endpoint != "192.168.0.162:8443" || doc.LocalAPI.Fingerprint != "ab12cd" {
t.Fatalf("local_api wrong: %+v", doc.LocalAPI)
}