feat(schema): M4.1 — full tenant_registry schema + migrate binary
PLATFORM_ARCHITECTURE.md §5c schema, end-to-end:
enums: tenant_status (demo/trial/active/frozen/archived),
tenant_kind (customer/demo), idp_kind (oidc/saml),
tenant_project_status (active/archived)
tables: tenants id/slug/name/status/kind/plan/erp_id/
stripe_id/trial_ends_at/contract_dates/
sales_owner
tenant_projects sub-tenancy (GCP-Project style); opt-in
via product manifest.supports_projects=true
tenant_products tenant ↔ product matrix + JSONB config
tenant_idp_config enterprise SSO (OIDC/SAML metadata)
api_keys argon2 hash + prefix + scopes + revoked_at
audit_log Retraced-compatible; indexed for cross-
product filtering per §8.4
triggers: updated_at auto-bump on every mutable table
fks: ON DELETE CASCADE for owned rows; SET NULL for audit_log
cmd/migrate (new binary): golang-migrate as a library with migrations
embedded via migrations/embed.go; subcommands up/down/version/force.
Ships as a self-contained Orca init container in prod.
Tests (require Docker; gated by -short):
TestMigrate_upDownRoundTrip schema → 6 tables + 4 enums; down→
empty; up-after-down clean
TestSeed_canInsertAndQuery insert across every table; FK cascade;
audit_log SET-NULL keeps the row
TestSlugConstraint regex rejects too-short / leading dash /
trailing dash / uppercase / underscore
Makefile: migrate-up/down/down-all/version/create NAME=...; test-short
to skip integration when Docker isn't around; build-migrate for just
the migrator.
CI: pin golangci-lint to v2.12.2 (Go 1.25-compatible) + bump
golangci-lint-action to v7 (v6 rejects v2.x).
The handler-layer in-memory store is unchanged; M4.2 swaps it for the
pgx-backed implementation against this schema.
Refs: M4.1
This commit is contained in:
@@ -64,7 +64,39 @@ The skeleton's store is in-memory and pre-seeded with one tenant:
|
||||
|
||||
So `curl http://localhost:8090/v1/tenants/by-slug/acme` works the moment `make dev` is up.
|
||||
|
||||
The full schema (tenants, tenant_products, audit_log) is committed at `migrations/0001_init.up.sql` for review, but unapplied until the M4.1 follow-up PR swaps the in-memory store for pgx-backed Postgres.
|
||||
The full schema (6 tables: `tenants`, `tenant_projects`, `tenant_products`, `tenant_idp_config`, `api_keys`, `audit_log` — per `PLATFORM_ARCHITECTURE.md §5c`) lives at `migrations/0001_init.up.sql`. The handler-layer in-memory store is still wired in by default; the pgx-backed store + the full REST surface lands in **M4.2**.
|
||||
|
||||
## Schema migrations (M4.1)
|
||||
|
||||
```bash
|
||||
# Apply all pending migrations against the dev Postgres (assumes
|
||||
# `make dev-up` in platform/orca-platform is running):
|
||||
make migrate-up
|
||||
|
||||
# Inspect current version:
|
||||
make migrate-version
|
||||
|
||||
# Roll back the most recent migration:
|
||||
make migrate-down
|
||||
|
||||
# Wipe everything (DESTRUCTIVE — only safe against a dev DB):
|
||||
make migrate-down-all
|
||||
|
||||
# Create the next pair of empty migration files:
|
||||
make migrate-create NAME=add_team_table
|
||||
```
|
||||
|
||||
Migrations are embedded into both `cmd/server` and `cmd/migrate` via `migrations/embed.go`. In production, `cmd/migrate` ships as an Orca init container so the schema is applied before the API server starts (`IMPLEMENTATION_PLAN.md §1.7`: migrations are forward-only and run as an init container before the service).
|
||||
|
||||
The migrations package ships three integration tests (require Docker):
|
||||
|
||||
| Test | What it asserts |
|
||||
|---|---|
|
||||
| `TestMigrate_upDownRoundTrip` | up → all 6 tables + 4 enums exist; down → schema empty; up again succeeds |
|
||||
| `TestSeed_canInsertAndQuery` | end-to-end insert across all 6 tables, FK cascade behaviour, `audit_log` SET-NULL on tenant delete |
|
||||
| `TestSlugConstraint` | tenant slug regex enforced (rejects too-short / leading dash / uppercase / underscore) |
|
||||
|
||||
Run them with `make test`. Use `make test-short` in environments without Docker.
|
||||
|
||||
## Deployment
|
||||
|
||||
|
||||
Reference in New Issue
Block a user