Files
kms/embed_test.go
Hanzo AI ca66adc00a purge: rip remaining Infisical residue — docs, env examples, repo boilerplate
Following the earlier AdminShell+CollectionCRUD rewrite (PR #14) which
already deleted backend/, backend-go/, cloudformation/, helm-charts/,
nginx/, sink/, wasm/, upgrade-impact/, e2e/, migration/, package.json
and switched the frontend to a 184K Hanzo-first build, complete the
cleanup by deleting the remaining Infisical-era residue:

  - docs/                                   (1.0G Infisical mintlify docs)
  - .env.example, .env.dev.example,
    .env.migration.example, .env.test.example
                                            (legacy Postgres/Redis envs;
                                             no Go code references them)
  - .eslintignore, .husky/                  (TS toolchain leftovers)
  - CODE_OF_CONDUCT.md, CONTRIBUTING.md,
    SECURITY.md                             (Infisical repo boilerplate)

Working tree drops from ~1.0G to <600K of content (1.5G total is .git/
which `git gc --aggressive --prune=now` shrinks locally; the remote
keeps its history shape — anyone pulling gets the lean checkout).

Build + test verification:
  go build ./...                            (4 cmd binaries: green)
  go test ./... -count=1 -short             (all packages: ok)

Kept: cmd/, pkg/, sdk/, frontend/ (AdminShell), schema/, examples/,
root Go (audit.go, auth.go, consensus.go, embed.go, jwks.go, mount.go,
versioning.go + tests), Dockerfile, Dockerfile.kms-fetch, Makefile,
LLM.md, CLAUDE.md, DEPRECATED.md, SOVEREIGN-KMS-ARCHITECTURE.md,
TFHE-KMS-ARCHITECTURE.md, LICENSE, README.md, VERSION, .github/
(8 Hanzo workflows: build, build-kms-fetch, check-fe-ts-and-lint,
ci, pr-preview, release, validate-pr-title, workflow-sanity).
2026-06-07 14:23:12 -07:00

111 lines
3.3 KiB
Go

package kms
import (
"context"
"net/http"
"net/http/httptest"
"path/filepath"
"testing"
"time"
)
// TestEmbed asserts the public Embed() entry point boots a working
// KMS server (in-memory ZapDB, dev-mode auth, no listener) and the
// returned HTTPHandler answers /healthz with 200.
//
// Runs in <2s with no external services. Mirrors the iam.Embed()
// shape so a future fused hanzo binary can call Embed() the same way
// for both services.
func TestEmbed(t *testing.T) {
if testing.Short() {
t.Skip("skipping kms.Embed live test in -short mode")
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// Stand up a fake JWKS so Embed has somewhere to point ExpectedIssuer
// and JWKSURL. There is no permissive env any more — every Hanzo
// user supplies these four fields or Embed refuses to boot.
jwks := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"keys":[]}`))
}))
t.Cleanup(jwks.Close)
em, err := Embed(ctx, EmbedConfig{
DataDir: filepath.Join(t.TempDir(), "kms"),
AuditDB: filepath.Join(t.TempDir(), "audit.db"),
Env: "dev",
IAMEndpoint: jwks.URL,
ExpectedIssuer: jwks.URL,
ExpectedAudience: "kms-test",
JWKSURL: jwks.URL + "/.well-known/jwks",
SkipListen: true, // mount via httptest.Server
ZAPPort: -1, // disable ZAP (no master key in env)
})
if err != nil {
t.Fatalf("Embed: %v", err)
}
t.Cleanup(func() {
stopCtx, stopCancel := context.WithTimeout(context.Background(), 2*time.Second)
defer stopCancel()
if err := em.Stop(stopCtx); err != nil {
t.Errorf("Stop: %v", err)
}
})
srv := httptest.NewServer(em.HTTPHandler())
t.Cleanup(srv.Close)
t.Run("healthz", func(t *testing.T) {
resp, err := http.Get(srv.URL + "/healthz")
if err != nil {
t.Fatalf("GET /healthz: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Fatalf("GET /healthz: status %d, want 200", resp.StatusCode)
}
})
t.Run("v1_kms_health", func(t *testing.T) {
resp, err := http.Get(srv.URL + "/v1/kms/health")
if err != nil {
t.Fatalf("GET /v1/kms/health: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Fatalf("GET /v1/kms/health: status %d, want 200", resp.StatusCode)
}
})
t.Run("secret_route_requires_auth", func(t *testing.T) {
// Sanity check: even though Env=dev tolerates missing JWT config
// at boot, every secret route still demands a verified bearer
// token at request time. Unauthenticated → 401.
resp, err := http.Get(srv.URL + "/v1/kms/orgs/hanzo/secrets/foo/bar")
if err != nil {
t.Fatalf("GET secrets: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusUnauthorized {
t.Fatalf("unauthenticated GET: status %d, want 401", resp.StatusCode)
}
})
t.Run("stop_is_idempotent", func(t *testing.T) {
// Stop twice in a row must not panic or leak goroutines.
ctx1, c1 := context.WithTimeout(context.Background(), time.Second)
defer c1()
if err := em.Stop(ctx1); err != nil {
t.Errorf("first Stop: %v", err)
}
ctx2, c2 := context.WithTimeout(context.Background(), time.Second)
defer c2()
if err := em.Stop(ctx2); err != nil {
t.Errorf("second Stop: %v", err)
}
})
}