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

This commit was merged in pull request #20.
This commit is contained in:
2026-09-01 09:18:15 +00:00
parent 84516e9b4f
commit 80565fdbf2
2 changed files with 25 additions and 0 deletions
+15
View File
@@ -13,6 +13,11 @@ import (
// ─── organizations API ───────────────────────────────────────────────────
// orgDomainSuffix namespaces the synthetic org domain. The slug is unique in
// the registry, so "<slug>.tenant.breakpilot.com" is unique per organization
// and never a real deliverable mail domain we might clash with.
const orgDomainSuffix = ".tenant.breakpilot.com"
type orgCreate struct {
Name string `json:"name"`
Alias string `json:"alias"`
@@ -50,6 +55,16 @@ func (a *HTTPAdapter) CreateOrgAndInvite(ctx context.Context, in InviteInput) (*
Name: in.Name,
Alias: in.Slug,
Description: fmt.Sprintf("Auto-provisioned from tenant-registry %s", in.TenantID),
// Keycloak 26 rejects an organization with no domain ("You must
// provide at least one domain"). Membership is registry-authoritative
// (model B2), so we do NOT use Keycloak's email-domain auto-join; a
// synthetic per-tenant domain derived from the unique slug satisfies
// the constraint without depending on the customer's real mail domain
// (which may be a shared public domain and would collide across
// tenants). Unverified is fine — verification only gates auto-join.
Domains: []map[string]any{
{"name": in.Slug + orgDomainSuffix, "verified": false},
},
Attributes: map[string][]string{
"tenant_id": {in.TenantID},
},