Commit Graph
11 Commits
Author SHA1 Message Date
Sharang ParnerkarandClaude Fable 5 576d733eae feat(tenants): provision the product tenant with the registry UUID on create
ci / shared (pull_request) Successful in 14s
ci / test (pull_request) Failing after 16m9s
ci / image (pull_request) Skipped
Closes the tenant-anchor divergence that blocked the Auth-5 sdk/backend flips.

The registry is the authority for tenant identity (model B2), but nothing ever
told the product about a new tenant. The anchors drifted: the registry held
acme/matrix-acme while the product database held only the legacy seed tenant
9282a473. With the SDK gate enabled its TenantResolver does GetTenantBySlug and
would 403 EVERY authenticated request, because no real user's org slug existed
locally.

New internal/product port, mirroring keycloak.Adapter: handlers depend on the
interface, main wires HTTPProvisioner when PRODUCT_API_URL is set and
NoopProvisioner otherwise, so an unconfigured deployment still creates tenants.
Tenant creation now also provisions the product tenant with OUR uuid, using the
same best-effort contract as Keycloak provisioning: a failure does not roll the
tenant back, it emits a product.provision_failed audit event so the divergence
is traceable. Success emits product.tenant_provisioned.

A 409 from the product counts as success — onboarding may retry and the
product's insert is idempotent on the primary key (compliance#217).

Server.productProvisioner() guarantees the documented never-nil invariant;
tests construct Server directly and would otherwise panic mid-tenant-creation.

5 tests incl. the point of the whole port (the registry UUID is what gets sent).
Full suite green with -race, coverage 71.4% (gate 70).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CNdLL9BdsWm7MCyui5ffPD
2026-09-01 23:16:33 +02:00
sharang 80565fdbf2 fix(keycloak): org create must send a domain (KC 26 rejects domainless) (#20)
ci / shared (push) Successful in 12s
ci / test (push) Successful in 21m24s
ci / image (push) Successful in 17s
2026-09-01 09:18:15 +00:00
sharang 84516e9b4f feat(keycloak): organizations become the membership authority source (#19)
ci / shared (push) Successful in 11s
ci / test (push) Successful in 21m22s
ci / image (push) Successful in 19s
2026-09-01 09:03:23 +00:00
sharangandSharang Parnerkar ce75ed04c2 RBAC Phase 1: membership authority endpoint + fail-closed API auth (#14)
ci / shared (push) Failing after 14s
ci / test (push) Successful in 21m13s
ci / image (push) Skipped
Implements the model-B2 membership authority (ratified compliance auth design) and inbound token verification.

- GET /v1/users/{id}/memberships: Keycloak supplies user->tenant links + org_roles (attribute projection until the realm migrates to Organizations); registered tenants override status/plan/products from registry tables (source: registry|keycloak). Closes the M5.2-deferred org_roles stub.
- New internal/authn: OIDC discovery + JWKS verification (go-oidc/v3), audience tenant-registry. /healthz + /readyz stay PUBLIC_EXPLICIT; all other routes INTERNAL_SERVICE_ONLY. AUTH_ENABLED=true refuses to start on incomplete config (fail-closed); false (dev default) keeps current behavior.
- Full suite green incl. postgres testcontainers; openapi.yaml updated (contract test passes).

Activation is a separate step (Auth-5): requires the orca-infra env merge and a portal service token (portal currently calls with no auth).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com>
Reviewed-on: #14
2026-08-24 18:21:46 +00:00
sharang 8fa1a1bffd feat(store): set trial_ends_at on tenant create
ci / shared (push) Successful in 6s
ci / test (push) Successful in 1m42s
ci / image (push) Has been skipped
trial_ends_at = NOW()+14d for customer kind; demo kind gets status=demo and no end. Unblocks M12.1 portal banner.

Refs: M4.1 + M12.1 prep
2026-05-19 16:27:09 +00:00
sharang a37ae1d121 fix(audit): strip IPv6 brackets before INET insert
ci / shared (push) Successful in 7s
ci / test (push) Successful in 1m46s
ci / image (push) Has been skipped
Caught during live local-smoke run.

Refs: M4.2/M5.3
2026-05-19 15:09:00 +00:00
sharang 9138731eea feat(keycloak): M4.3 — Admin API adapter + claim resolver
ci / shared (push) Successful in 5s
ci / test (push) Successful in 1m32s
ci / image (push) Has been skipped
internal/keycloak Adapter (HTTPAdapter + Mock). POST /v1/tenants now provisions a KC organization + IT_ADMIN invite when admin_email is set; KC failures emit keycloak.provision_failed but don't roll back. POST /v1/internal/keycloak/claims resolves the current claim bundle for any (tenant_id|tenant_slug|user_attrs.*) lookup. Mock used in tests + when KEYCLOAK_ADMIN_URL is empty. HTTPAdapter tested against an in-process stub KC (httptest.Server).

Refs: M4.3
2026-05-19 11:51:09 +00:00
sharang ffab866c87 feat(api): M4.2 — REST surface + pgx Postgres store + OpenAPI 3.1
ci / shared (push) Successful in 6s
ci / test (push) Successful in 1m15s
ci / image (push) Has been skipped
Full M4.2 deliverable: 16 endpoints (tenants CRUD + lifecycle, catalog, entitlements, API keys with argon2 hashing, audit append + filter), Store interface with pgx-backed Postgres + in-memory parallel implementations exercised by the same eachStore harness, openapi.yaml at 3.1 with kin-openapi contract test. M4.3 adds auth.

Refs: M4.2
2026-05-19 10:51:59 +00:00
sharang d66760b246 feat(schema): M4.1 — tenant_registry schema + migrate binary
ci / shared (push) Successful in 5s
ci / test (push) Successful in 20s
ci / image (push) Has been skipped
PLATFORM_ARCHITECTURE.md §5c schema as one initial migration: 6 tables + 4 enums + updated_at triggers. cmd/migrate binary (golang-migrate library, embedded SQL). testcontainers round-trip + seed + slug-constraint tests.

Refs: M4.1
2026-05-19 10:10:14 +00:00
sharang e70ed771ca fix(dev): default port :8080 → :8090
ci / shared (push) Successful in 4s
ci / test (push) Successful in 9s
ci / image (push) Has been skipped
Unblock local dev: Keycloak owns :8080, so tenant-registry shifts to :8090. Prod is functionally unchanged.

Refs: M5.1
2026-05-19 09:47:36 +00:00
sharang af9f331781 feat(server): tenant-registry skeleton boots against dev stack
ci / shared (push) Successful in 4s
ci / test (push) Successful in 11s
ci / image (push) Has been skipped
Minimal Go service: /healthz + /v1/tenants/by-slug/:slug + /v1/tenants/:id with an in-memory store seeded with the acme tenant. Stdlib-only; pgx + JWT validation land in M4.1 follow-up.
2026-05-19 09:35:04 +00:00