feat(server): tenant-registry skeleton boots against dev stack #4
Reference in New Issue
Block a user
Delete Branch "feat/skeleton"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
:8080in dev):GET /healthz→{"status":"ok"}GET /v1/tenants/by-slug/{slug}→ seededacmetenant or 404GET /v1/tenants/{id}→ same by UUID or 404acme) matching the seed user in the dev-stack Keycloak realm.migrations/0001_init.up.sqllands the full M4.1 schema for review but is unapplied by the skeleton.Why
The
portalmiddleware needs to call this service to resolve<slug>.localhost:3000→ tenant during the OIDC redirect dance. Without a running tenant-registry, portal can't even render/[slug]/dashboardin dev. Skeleton-mode unblocks portal work today; full pg-backed CRUD + JWT validation + audit endpoints land in the M4.1 follow-up.Linked milestone: M4.1 (skeleton — full implementation in follow-up)
How
cmd/server/main.go— graceful-shutdown server, slog JSON logger.internal/config/— env-driven config (APP_ENV,ADDR,KEYCLOAK_ISSUER,DATABASE_URL).internal/server/— handlers + a tiny request-logging middleware. Stdlib mux with Go 1.22 method routing.internal/store/memory.go— interface-shaped so the M4.1 follow-up swaps it forpgxwithout touching handlers. Pre-seeded with one tenant.httptest.Server: healthz, by-slug acme, by-slug 404.gcr.io/distroless/static-debian12:nonroot— final image is ~10 MB; CGO disabled.Test plan
go test -race ./...✅ (3 tests in internal/server)go vet ./...cleangofmt -l .emptygo build✅ (8.4 MB static binary)acme.localhost:3000, observe portal callingtenant-registry /v1/tenants/by-slug/acmeRisk
Blast radius: dev only. Service has no production deployment yet (the manifest stub in
orca-platform/manifests/vm-control/tenant-registry.tomlstill saysplaceholderimage).What could break:
/v1/tenants/*is open. Fine for dev/loopback; must not ship to stage without the JWT middleware. The M4.1 follow-up adds it.Rollback plan: revert the PR. Nothing depends on this service yet.
Checklist
.env.localgitignoredgolang-migrateMinimal Go service so platform/portal has something to resolve in local dev. Stdlib net/http with Go 1.22 enhanced ServeMux (method+path patterns); no third-party deps yet. Layout: cmd/server/main.go entry point with graceful shutdown internal/config/ env-driven config (APP_ENV, ADDR, KC issuer) internal/server/ http handlers + request-logging middleware internal/store/memory.go in-memory tenant store, seeded with acme migrations/0001_init.up.sql schema for the M4.1 follow-up (unapplied) Makefile dev/test/build/lint/docker targets Dockerfile multi-stage distroless build Endpoints (under :8080 in dev): GET /healthz GET /v1/tenants/by-slug/{slug} 200 acme | 404 GET /v1/tenants/{id} 200 by uuid | 404 JWT validation and the real Postgres-backed store land in the M4.1 follow-up PR — keeping this PR strictly to 'boots, replies, tests pass'. Refs: M4.1 (skeleton)The runner's golangci-lint binary is built with Go 1.24 and refuses to lint modules targeting a higher Go version ('the Go language version (go1.24) used to build golangci-lint is lower than the targeted Go version (1.25)'). 1.24 is current stable and covers everything the skeleton uses (slog, ServeMux method routing). Dockerfile pinned to golang:1.24-alpine to match. Refs: M4.1CI's coverage gate is 70% (line-level, package average per the matrix). The skeleton only had handler tests so most files at 0% = 65% average and CI red. Adds: internal/store/memory_test.go seeded fixture, ErrNotFound paths, pointer-copy isolation check internal/config/config_test.go defaults, overrides, invalid APP_ENV Refs: M4.1