Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/adr-0024-sso-list-visibility.md
Original file line number Diff line number Diff line change
@@ -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.)
16 changes: 16 additions & 0 deletions packages/platform-objects/src/identity/sys-sso-provider.object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down