Skip to content

SCRUM-221 — Config seed namespaces and config seed

Plan ref: CFG-C1 (docs/11-admin-plane-plan.md). Stacked on SCRUM-220.

What exists

Piece Notes
internal/seed/seed/<ns>/{namespace,schema,draft}.json features.flags, balance.player, ui.motd, ui.presentation (schema identical to the adminui fixture; draft gives presentation entries for the other three). Embedded in the binary (//go:embed), so the distroless image needs no files
seed.Load checks name (API regexp), audience, schema compiles, draft validates; errors name the file
seed.Apply idempotent: missing → create + schema + draft (actor seed); existing → skipped, never overwritten. A namespace left half-seeded (schema v1 {}, draft at revision 1) is finished rather than skipped
config seed [--dry-run] same DB env as migrate, no listeners; one JSON log line per namespace; exit 1 on any error

How to verify

cd services/config
. ../../handoff/pg-env.sh
gofmt -l . && go vet ./...
CONFIG_TEST_DATABASE_URL=postgres://auth_rw:pw@127.0.0.1:5433/config_test?sslmode=disable \
  go test -race -count=1 ./...
CONFIG_DATABASE_URL=… go run . seed --dry-run   # then without --dry-run, twice

Tests: the embedded folder loads with exactly the four names; bad draft / bad schema / bad name / bad audience each fail naming the file; first Apply creates (schema v2, draft saved, 3 audit rows), second Apply skips with no new audit rows; an edited draft is left alone; Plan writes nothing; a half-seeded namespace is finished; the real folder applies.

Results at time of writing

  • gofmt, go vet, go test -race with the DB (9 packages): pass.

How it was built

DeepSeek run scoped (Landlock) to services/config (185 s, ~31k output tokens, reasoning effort low). Claude review added the resume rule: a crash between creating a namespace and saving its seed schema left it stuck empty, because every later run skipped it. Regression test added.