Files
tenant-registry/go.mod
T
sharang 4c46d673fb
ci / shared (pull_request) Successful in 5s
ci / test (pull_request) Failing after 1m30s
ci / image (pull_request) Has been skipped
feat(api): M4.2 — full REST surface + pgx-backed Postgres store
Replaces the M5.1-skeleton handler set with the M4.2 spec from
IMPLEMENTATION_PLAN.md:

Endpoints (authoritative shape in openapi.yaml):
  POST   /v1/tenants
  GET    /v1/tenants/{id}
  GET    /v1/tenants/by-slug/{slug}
  POST   /v1/tenants/{id}/activate
  POST   /v1/tenants/{id}/cancel
  GET    /v1/entitlements?tenant_id=...
  GET    /v1/catalog
  POST   /v1/catalog/request
  POST   /v1/catalog/trial-request
  POST   /v1/api-keys                       returns plaintext ONCE
  GET    /v1/api-keys?tenant_id=...
  DELETE /v1/api-keys/{id}
  POST   /v1/internal/api-keys/verify       always 200; valid: bool
  POST   /v1/audit
  GET    /v1/audit?{tenant_id,product,actor_id,action,since,until,limit,cursor}

Architecture:
  internal/store/store.go        Store interface (CRUD + audit + ping)
  internal/store/memory.go       in-process impl, used when DATABASE_URL
                                 is empty (seed acme tenant, no migrations)
  internal/store/postgres.go     pgxpool impl against the M4.1 schema
  internal/server/server.go      router + healthz/readyz
  internal/server/{tenants,catalog,apikeys,audit}.go
                                 per-concern handlers (≤250 LoC each)
  internal/server/helpers.go     writeJSON/writeError/error mapping/log mw
  openapi.yaml                   3.1 spec; openapi_test.go is the contract gate

API keys:
  Plaintext format 'bp_<22-char base64>'. Prefix bp_<8> stored for UI.
  Hash is argon2id(salt, time=1, mem=64MB, threads=4, len=32) encoded as
  'argon2id|<salt-b64>|<hash-b64>'. Format-tagged so we can rotate
  parameters without re-keying. Verify is constant-time.

Store selection:
  cmd/server picks Postgres when DATABASE_URL is set, otherwise Memory.
  Both implementations are exercised by the same eachStore test harness —
  parity is enforced.

Audit:
  Every state-changing endpoint emits via s.emitAudit() (fire-and-forget).
  audit_log uses ON DELETE SET NULL on tenant_id so forensic history
  outlives tenant deletes (per M4.1 schema).

Routing constraint:
  Go 1.22 ServeMux can't disambiguate /v1/tenants/{id}/products from
  /v1/tenants/by-slug/{slug=products}. Per-tenant subresources moved to
  query-param top-level paths: /v1/entitlements?tenant_id=… and
  /v1/api-keys?tenant_id=….

Tests:
  Every endpoint exercised against both Memory and Postgres via the
  eachStore harness. Includes happy paths, validation errors, conflicts,
  404s, auto-audit-emit assertion. testcontainers-go for the postgres
  harness; gated by -short.

  TestOpenAPISpec is the contract gate: every documented operation must
  resolve against the router. (kin-openapi v0.138.0.)

Refs: M4.2
2026-05-19 12:44:43 +02:00

83 lines
3.8 KiB
Modula-2

module gitea.meghsakha.com/platform/tenant-registry
go 1.25.0
require (
github.com/getkin/kin-openapi v0.138.0
github.com/golang-migrate/migrate/v4 v4.19.1
github.com/google/uuid v1.6.0
github.com/jackc/pgerrcode v0.0.0-20250907135507-afb5586c32a6
github.com/jackc/pgx/v5 v5.9.2
github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0
golang.org/x/crypto v0.51.0
)
require (
dario.cat/mergo v1.0.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/ebitengine/purego v0.10.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.18.5 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.10 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/go-archive v0.2.0 // indirect
github.com/moby/moby/api v1.54.1 // indirect
github.com/moby/moby/client v0.4.0 // indirect
github.com/moby/patternmatcher v0.6.1 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/oasdiff/yaml v0.0.9 // indirect
github.com/oasdiff/yaml3 v0.0.12 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
github.com/shirou/gopsutil/v4 v4.26.3 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/testcontainers/testcontainers-go v0.42.0 // indirect
github.com/tklauser/go-sysconf v0.3.16 // indirect
github.com/tklauser/numcpus v0.11.0 // indirect
github.com/woodsbury/decimal128 v1.3.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.41.0 // indirect
go.opentelemetry.io/otel/metric v1.41.0 // indirect
go.opentelemetry.io/otel/trace v1.41.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.44.0 // indirect
golang.org/x/text v0.37.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)