Skip to content

SCRUM-197 — admin-auth service foundation

Plan ref: AA-1 (docs/11-admin-plane-plan.md). New service services/admin_auth, a port of services/auth's skeleton with the player-specific parts removed.

What exists

Piece Notes
admin_auth serve (default) / migrate goose migrations embedded; migrate is a separate one-shot step
Config ADMIN_AUTH_* listen/metrics addrs, DB URL + pool size, issuer (https://admin-auth.otomo.internal), audience (otomo:staff), timeouts, log level; all problems reported at once
Public listener :8080 no routes yet: every path → COM-5 404 not_found (so /healthz, /metrics look absent)
Internal listener :9090 /healthz, /readyz, /metrics (admin_auth_*), pprof
/readyz startup flag and DB ping and signing-key check. The key check is a placeholder that always fails with no signing key loaded until SCRUM-199 — 503 is the expected state for now
migrations/00001_init.sql intentional no-op; SCRUM-198 adds the schema
dockerfile, .env.example, README.md modelled on services/auth
services/go.work ./admin_auth added

How to verify

cd services/admin_auth
go vet ./... && go test -race -count=1 ./...

# with a database (any PG 16+; an empty DB is fine)
export ADMIN_AUTH_TEST_DATABASE_URL='postgres://USER:PASS@127.0.0.1:5433/admin_auth_test?sslmode=disable'
go test -race -count=1 ./internal/store/

# the binary
go build -o /tmp/aa . && export ADMIN_AUTH_DATABASE_URL="$ADMIN_AUTH_TEST_DATABASE_URL" \
  ADMIN_AUTH_LISTEN_ADDR=127.0.0.1:18180 ADMIN_AUTH_METRICS_ADDR=127.0.0.1:18181
/tmp/aa migrate && /tmp/aa migrate          # second run: "no migrations to run"
/tmp/aa serve &
curl -i 127.0.0.1:18181/readyz              # 503 {"error":{"code":"not_ready","message":"no signing key loaded",…}}
curl -i 127.0.0.1:18181/healthz             # 200 ok
curl -i 127.0.0.1:18180/healthz             # 404 COM-5 (not on the public port)
curl -s 127.0.0.1:18181/metrics | grep ^admin_auth_

Results at time of writing

  • go vet, go test -race: pass (4 packages, 16 tests), including the migration idempotency test against local Postgres 16.
  • Binary: migrate twice (second a no-op), /readyz 503 with the key message, /healthz 200 internal / 404 public, 16 admin_auth_* series.

Not in this ticket

Schema (SCRUM-198), signing key + JWKS + making /readyz green (SCRUM-199), endpoints (SCRUM-203+), compose/provisioning (SCRUM-240/241).

How it was built

DeepSeek run scoped (Landlock) to services/admin_auth (166 s, ~30k output tokens), adapting services/auth. Claude: go.work entry, review by diffing each file against services/auth, DB-backed test run and binary smoke.