From b5448038b14f55e84ddec11ae0fbe02a7d143b53 Mon Sep 17 00:00:00 2001 From: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Date: Sun, 28 Jun 2026 01:16:20 +0800 Subject: [PATCH] fix(auth): make the SSO Providers list visible to admins (ADR-0024 / cloud#551) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sys_sso_provider Setup list rendered empty even after an admin registered a provider — member_default's wildcard tenant_isolation RLS denied every row (better-auth writes via its adapter with no tenantId → organization_id never stamped; the platform-admin viewAllRecords bypass is gated to private/non-tenant objects). sys_sso_provider is env-global admin-only identity config, so it now declares tenancy.enabled:false (admin viewAllRecords sees all env providers) + requiredPermissions:['manage_platform_settings'] (object-level gate so members are 403'd; without it tenancy-disabled + member_default '*' allowRead would leak). Verified E2E: admin sees all providers in the list, non-admin → 403. Env-only object (no control-plane risk). Co-Authored-By: Claude Opus 4.8 --- .changeset/adr-0024-sso-list-visibility.md | 13 +++++++++++++ .../src/identity/sys-sso-provider.object.ts | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 .changeset/adr-0024-sso-list-visibility.md diff --git a/.changeset/adr-0024-sso-list-visibility.md b/.changeset/adr-0024-sso-list-visibility.md new file mode 100644 index 0000000000..d7f2a52649 --- /dev/null +++ b/.changeset/adr-0024-sso-list-visibility.md @@ -0,0 +1,13 @@ +--- +'@objectstack/platform-objects': patch +--- + +Auth: make the SSO Providers list visible to admins (ADR-0024 / cloud#551) + +The `sys_sso_provider` Setup list rendered empty even after an admin registered a provider: `member_default`'s wildcard `tenant_isolation` RLS (`organization_id == current_user.organization_id`) denied every row, because better-auth writes these via its adapter with no tenantId context so `organization_id` is never stamped, and the platform-admin `viewAllRecords` superuser bypass is gated to private/non-tenant objects. + +`sys_sso_provider` is env-global, admin-only identity config, so it now declares: +- `tenancy: { enabled: false }` — opts out of multi-tenancy (the env IS the tenant; providers are env-wide), letting a platform admin's `viewAllRecords` bypass see every provider. +- `requiredPermissions: ['manage_platform_settings']` — object-level capability gate so ordinary members are denied (without it, tenancy-disabled + `member_default`'s `'*': allowRead` would expose providers to every authenticated user). + +Verified E2E: an admin sees all env providers in the Setup → Access Control → SSO Providers list; a non-admin gets 403. (Env-only object — no control-plane cross-tenant impact. The sibling `sys_oauth_application` / `sys_account` nav entries share the same empty-list symptom but span the control plane and need separate per-object analysis.) diff --git a/packages/platform-objects/src/identity/sys-sso-provider.object.ts b/packages/platform-objects/src/identity/sys-sso-provider.object.ts index f2297605d2..3fec44f952 100644 --- a/packages/platform-objects/src/identity/sys-sso-provider.object.ts +++ b/packages/platform-objects/src/identity/sys-sso-provider.object.ts @@ -31,6 +31,22 @@ export const SysSsoProvider = ObjectSchema.create({ icon: 'shield-check', isSystem: true, managedBy: 'better-auth', + // ADR-0024 — env-global, ADMIN-ONLY identity config. Two orthogonal controls: + // • `tenancy.enabled: false` — the env IS the tenant; providers are env-wide, + // not org-partitioned. Opting out of multi-tenancy lets a platform admin's + // `viewAllRecords` superuser bypass see every provider (without it, the + // `member_default` wildcard `tenant_isolation` RLS denies every row, since + // better-auth writes via its adapter with no tenantId → `organization_id` + // is never stamped). + // • `requiredPermissions: ['manage_platform_settings']` — object-level + // capability gate (ADR-0066 D3) so ordinary members are denied entirely + // (without it, tenancy-disabled + `member_default`'s `'*': allowRead` would + // leak providers to every authenticated user). + // Together: admins see all env providers; non-admins get 403. better-auth's + // own endpoints already read via a system context. (Env-only object — no + // control-plane cross-tenant risk.) + tenancy: { enabled: false, strategy: 'shared' }, + requiredPermissions: ['manage_platform_settings'], // ADR-0010 §3.7 — managed by better-auth; tenants may not edit schema. protection: { lock: 'full',