HyperFleet API is a stateless REST API serving as the pure CRUD data layer for HyperFleet cluster lifecycle management. It persists clusters, node pools, and adapter statuses to PostgreSQL - no business logic, no events. Sentinel handles orchestration; adapters execute and report back.
- Language: Go 1.26+ with FIPS crypto (
CGO_ENABLED=1 GOEXPERIMENT=boringcrypto) - Database: PostgreSQL 14.2 with GORM ORM
- API Spec: TypeSpec ->
hyperfleet-api-specGo module -> oapi-codegen -> Go models - Architecture: Container-based dependency injection, config-driven route registration, service-owned mutation transactions
Generated code is not checked into git. Before building, testing, or even running go mod download:
make generate-all # Generates OpenAPI types + mock implementationsSetup sequence for a fresh clone:
make generate-all- generate OpenAPI models and mocksgo mod download- fetch dependenciesmake install-hooks- install pre-commit hooksmake db/setup- start local PostgreSQL containermake build- build binary./bin/hyperfleet-api migrate- apply database migrationsmake run-no-auth- start server without authentication
Tool versions are pinned in tools/go.mod and invoked via go tool -modfile=tools/go.mod <name>.
| Command | What it does | Requires DB? |
|---|---|---|
make verify |
go vet + gofmt check | No |
make lint |
golangci-lint | No |
make test |
Unit tests | No |
make test-integration |
Integration tests (testcontainers) | No (auto-creates) |
make test-helm |
Helm chart lint + template validation | No |
make verify-all |
verify + lint + test (single command) | No |
make test-all |
lint + test + test-integration + test-helm | Auto-creates |
Quick feedback: make verify-all. Full pre-push: make test-all.
| Topic | Where to look |
|---|---|
| OpenAPI spec & code generation | openapi/README.md |
| Handler pipeline & validation | pkg/handlers/CLAUDE.md |
| Service interface & status aggregation | pkg/services/CLAUDE.md |
| DAO patterns & session access | pkg/dao/CLAUDE.md |
| SessionFactory & transactions | pkg/db/CLAUDE.md |
| Error constructors & RFC 9457 | pkg/errors/CLAUDE.md |
| Test conventions & factories | test/CLAUDE.md |
| Helm chart testing | charts/CLAUDE.md |
| Development setup | docs/development.md |
| Deployment | docs/deployment.md |
| Authentication | docs/authentication.md |
| Contributing | CONTRIBUTING.md |
Request flow: Router -> Middleware (logging, auth, timeout) -> Handler -> Service transaction -> DAO -> GORM -> PostgreSQL
- Startup wiring:
servecmd.runServeloads config ->container.NewContainer(cfg, closer)->BuildAPIServer(...)->server.NewRouterFromConfig+server.NewAPIServer. Shutdown usespkg/closer(LIFO order): readiness probe -> health drain -> metrics drain -> API drain -> JWT close -> OTel flush -> DB pool close - Entity routes are config-driven: declared in
config.yamlunderentities:, registered at startup viaregistry.LoadDescriptors(), routes auto-generated byRegisterEntityRoutes. No per-entity Go code needed. - Service transactions: each mutation service opens one
db.TxRunner.Doboundary and commits before returning success; reads skip explicit transactions for performance. Request middleware applies timeouts only. - Status aggregation: Service layer synthesizes
Available,Reconciled, andLastKnownReconciledconditions from adapter reports - Public routes (
/openapi,/openapi.html, metadata) bypass auth and schema validation; everything else is gated by both, auth outermost - Container (
cmd/hyperfleet-api/container) lazily constructs and caches dependencies. Holds DAOs, services, schema validator, JWT handler - but does NOT own their lifecycle. Shutdown ordering is handled bypkg/closerin the composition root. - Server package (
cmd/hyperfleet-api/server) deliberately does not importpkg/config- takes narrowcfginterfaces instead. Put anything needing*config.ApplicationConfigin the composition root.
- Never edit files in
pkg/api/openapi/or*_mock.go- regenerate withmake generate-all - Never set
status.phasemanually - calculated from adapter conditions - Never create direct DB connections - use
SessionFactory.New(ctx)for transaction participation - FIPS required: build with
CGO_ENABLED=1 GOEXPERIMENT=boringcrypto - Spec source of truth:
hyperfleet-api-specGo module; updatego.modto change spec versions - see openapi/README.md - Tool versions pinned in
tools/go.mod- don't manually install oapi-codegen or golangci-lint
make generate-allis mandatory - build and tests fail without it; generated code is gitignoredpkg/api/openapi/is read-only - never hand-edit, always regenerate- Service methods return
*errors.ServiceError, not stdliberror- use constructor functions frompkg/errors/errors.go; seepkg/errors/CLAUDE.mdfor the full reference apiServer.Close()severs in-flight requests - always useShutdown(ctx)with a drain budget;Close()is only the force-close fallback afterShutdowntimes out- Container has no
Close()- lifecycle (JWT handler, session factory, OTel) is managed bypkg/closerin the composition root, not onContainer - Integration tests share a single testcontainer -
test.NewHelper(t)initializes once per process viasync.Once; the PostgreSQL container, API server, and JWK mock are shared across all tests in the suite - Schema validation requires the OpenAPI spec file - if
HYPERFLEET_SERVER_OPENAPI_SCHEMA_PATHis unset, validation is skipped;TestMainin integration tests auto-sets it totest/validation-schema.yaml