feat: alive UI wave, galaxy presence, spread and fleet enhancements
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Dashboard ambient layer, comrade presence, Mission Deck and War Room, Emberwake supply chain, spread/docs publishing, fleet policy and modules API, CI docker mining, and refreshed USB pack.
This commit is contained in:
87
server/internal/api/modules_test.go
Normal file
87
server/internal/api/modules_test.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
func TestListModulesAPI(t *testing.T) {
|
||||
store := NewModuleStore(t.TempDir(), func() string { return "list-secret" })
|
||||
h := NewModuleHandler(store)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/fleet/modules", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
h.ListModules(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status %d: %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
var mods []ModuleManifest
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &mods); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(mods) < 3 {
|
||||
t.Fatalf("expected at least 3 default packs, got %d", len(mods))
|
||||
}
|
||||
names := map[string]ModuleManifest{}
|
||||
for _, m := range mods {
|
||||
names[m.Name] = m
|
||||
}
|
||||
for _, want := range []string{"crucible_ops", "spread", "gpu"} {
|
||||
m, ok := names[want]
|
||||
if !ok {
|
||||
t.Fatalf("missing pack %q", want)
|
||||
}
|
||||
if m.DisplayName == "" || m.Summary == "" || len(m.Capabilities) == 0 {
|
||||
t.Fatalf("pack %q missing UI metadata: %+v", want, m)
|
||||
}
|
||||
if len(m.Features) == 0 {
|
||||
t.Fatalf("pack %q missing features", want)
|
||||
}
|
||||
if m.Signature == "" {
|
||||
t.Fatalf("pack %q unsigned", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAgentModuleAPI(t *testing.T) {
|
||||
store := NewModuleStore(t.TempDir(), func() string { return "agent-mod-secret" })
|
||||
h := NewModuleHandler(store)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/agent/module/gpu", nil)
|
||||
rctx := chi.NewRouteContext()
|
||||
rctx.URLParams.Add("name", "gpu")
|
||||
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))
|
||||
rec := httptest.NewRecorder()
|
||||
h.GetAgentModule(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status %d: %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
var m ModuleManifest
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if m.Name != "gpu" || m.Features["gpu_enabled"] != true {
|
||||
t.Fatalf("unexpected gpu manifest: %+v", m)
|
||||
}
|
||||
if !VerifyModuleSignature(m, "agent-mod-secret") {
|
||||
t.Fatal("agent module signature invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyModuleSignatureRejectsTamper(t *testing.T) {
|
||||
store := NewModuleStore(t.TempDir(), func() string { return "tamper-secret" })
|
||||
m, err := store.Get("crucible_ops")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !VerifyModuleSignature(m, "tamper-secret") {
|
||||
t.Fatal("expected valid signature")
|
||||
}
|
||||
m.Features["auto_spread"] = true
|
||||
if VerifyModuleSignature(m, "tamper-secret") {
|
||||
t.Fatal("expected tampered manifest to fail verification")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user