slice 8A (agent half): local-API server + provisioning back-half (v0.10.0)
internal/localapi: per-guest local-API server (doc 03 §6) — 7 self-scoped endpoints, hashed per-guest token store, persisted self-signed leaf with stable SHA-256 pin, optional 6th daemon goroutine. internal/provision: back-half — mint token, render bootstrap.json (no registry cred), write 0600, chown 100000:100000, attach pct-set bind mount (host-side, F3, no pct exec). --selftest=provision. build-golden.sh bakes the controller image + bootstrap unit. sudoers FELHOM_PROVISION; firewall narrowing artifact. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
package provision
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// The bootstrap.json key set is a CROSS-REPO contract: it must match felhom-controller's
|
||||
// internal/bootstrap.Bootstrap exactly. This test pins the emitted key set; the controller's
|
||||
// bootstrap_test.go ingests the same shape. A drift here (or there) breaks provisioning.
|
||||
func TestDoc_ContractKeySet(t *testing.T) {
|
||||
d := Doc{
|
||||
Schema: SchemaV1,
|
||||
Customer: DocCustomer{ID: "c", Name: "n", Domain: "d", Email: "e"},
|
||||
Hub: DocHub{URL: "u", APIKey: "k", HostID: "h"},
|
||||
LocalAPI: DocLocalAPI{Endpoint: "ep", Fingerprint: "fp", Token: "tok"},
|
||||
}
|
||||
b, err := d.render()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var m map[string]json.RawMessage
|
||||
if err := json.Unmarshal(b, &m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertKeys(t, "top", m, []string{"schema", "customer", "hub", "local_api"})
|
||||
|
||||
var full struct {
|
||||
Customer map[string]json.RawMessage `json:"customer"`
|
||||
Hub map[string]json.RawMessage `json:"hub"`
|
||||
LocalAPI map[string]json.RawMessage `json:"local_api"`
|
||||
}
|
||||
if err := json.Unmarshal(b, &full); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertKeys(t, "customer", full.Customer, []string{"id", "name", "domain", "email"})
|
||||
assertKeys(t, "hub", full.Hub, []string{"url", "api_key", "host_id"})
|
||||
assertKeys(t, "local_api", full.LocalAPI, []string{"endpoint", "fingerprint", "token"})
|
||||
|
||||
if SchemaV1 != "felhom.bootstrap/v1" {
|
||||
t.Fatalf("schema drift: %q", SchemaV1)
|
||||
}
|
||||
}
|
||||
|
||||
func assertKeys(t *testing.T, label string, m map[string]json.RawMessage, want []string) {
|
||||
t.Helper()
|
||||
got := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
got = append(got, k)
|
||||
}
|
||||
sort.Strings(got)
|
||||
sort.Strings(want)
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("%s: key set %v, want %v", label, got, want)
|
||||
}
|
||||
for i := range want {
|
||||
if got[i] != want[i] {
|
||||
t.Fatalf("%s: key set %v, want %v", label, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user