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
23 changes: 23 additions & 0 deletions .changeset/retire-sys-scim-provider-object.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'@objectstack/platform-objects': minor
'@objectstack/spec': minor
'@objectstack/plugin-auth': minor
'@objectstack/plugin-security': minor
---

**BREAKING (platform object removed):** the `sys_scim_provider` platform object is retired (#11757, ruled on #11693 — leg 1a of the #11632 SCIM epic).

FROM → TO, per surface:

- `SysScimProvider` (export of `@objectstack/platform-objects` / `.../identity`) → removed, no replacement export. Fix: delete the import. Stable SCIM state lives on the seven `sys_scim_*` stable-model objects (#3653), and connection credentials on `sys_scim_connection_credential`.
- `sys_scim_provider` in `PLATFORM_PROVIDED_OBJECT_NAMES` (`@objectstack/spec/system`) → removed. `isPlatformProvidedObjectName('sys_scim_provider')` is now `false`, so a stack referencing the name is flagged as a probable typo instead of resolving.
- plugin-auth: the object is no longer provisioned, and `AUTH_MODEL_TO_PROTOCOL` carries no `scimProvider` entry — the installed stable `@better-auth/scim@1.7.1` derives no such model, so the entry bridged nothing.
- plugin-security: the `BETTER_AUTH_MANAGED_OBJECTS` write-deny entry for it is gone with the object (the list is pinned bidirectionally against `managedBy: 'better-auth'` declarations).

The rc.1-era row was written only by the retired `/scim/generate-token` endpoint; after the stable-1.7.1 migration (PR #12726) nothing could write to it. Per the maintainer's ruling (2026-08-24, 「不需要考虑历史数据」; reaffirmed 2026-08-25 — SCIM has no real customers), **no data migration ships**: existing `sys_scim_provider` tables in deployed databases are left untouched — no backfill, no reaper, no migrate command. SCIM-enabled deployments re-register connections on the stable surface; the IdP token reissue is a migration-day operator action regardless of this change.

The ADR-0066 D3 capability-gate pin moves from the retired object to its surviving sibling `sys_sso_provider`, so the gate posture stays test-pinned.

Breaking ships as `minor` per the launch-window convention (`scripts/check-changeset-no-major.mjs`) and the #12726 precedent on the same ruling.

<!-- adr-0087: registered scim-provider-object-retired -->
4 changes: 2 additions & 2 deletions content/docs/permissions/authorization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,8 @@ The complete, prioritized gap map lives in issue **#2561** (the production
`sys_verification`, `sys_oauth_access_token`, `sys_oauth_refresh_token`,
`sys_device_code`) declare `access: { default: 'private' }` — no wildcard
grant reaches them; platform admins retain access via the posture-gated
superuser bypass. `sys_scim_provider` is capability-gated like
`sys_sso_provider`. Member self-service objects (`sys_session`,
superuser bypass. `sys_sso_provider` is capability-gated
(`manage_platform_settings`). Member self-service objects (`sys_session`,
`sys_api_key`, `sys_oauth_application`, `sys_two_factor`) deliberately stay
public-posture (the Account app reads them as the member; row scoping is
their guard). Still open: Studio posture surfacing (objectui).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,7 @@ describe('[#8608] the tenant index follows the wall’s derivation', () => {
// being dialect-dependent). It is the ONE shipped platform object whose
// answer this card changes; every other table that would qualify already
// declares its own single-column tenant index (`sys_invitation`,
// `sys_team`, `sys_scim_provider`) or is tenancy-disabled
// (`sys_sso_provider`).
// `sys_team`) or is tenancy-disabled (`sys_sso_provider`).
const out: any = applySystemFields(leadWith({ managedBy: 'better-auth' }), {
multiTenant: true,
});
Expand Down
2 changes: 1 addition & 1 deletion packages/objectql/src/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ function provisionTenantScopeIndex(
* (`sys_member`) is walled on that column and is now indexed on it. Re-adding
* an exclusion the wall does not have is precisely the drift this rebinding
* closes — and `declaresTenantIndex` already covers the tables that declare
* their own tenant index (`sys_invitation`, `sys_team`, `sys_scim_provider`).
* their own tenant index (`sys_invitation`, `sys_team`).
*
* ⚠️ The clause-1 rows are NOT a leftover of the condition #8459 lifted: an
* object that declares itself non-tenant-scoped is one the wall composes NO
Expand Down
5 changes: 2 additions & 3 deletions packages/platform-objects/scripts/i18n-extract.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ import {
SysOauthClientAssertion,
SysJwks,
SysSsoProvider,
SysScimProvider,
SysScimConnectionBinding,
SysScimConnectionCredential,
SysScimGroup,
Expand Down Expand Up @@ -248,9 +247,9 @@ const config: ObjectStackDefinition = defineStack({
SysOauthClientAssertion,
SysJwks,
SysSsoProvider,
SysScimProvider,
// Stable @better-auth/scim 1.7.x model set + the ObjectStack-owned
// credential store (#3653). SysScimProvider above retires under #11757.
// credential store (#3653). The rc.1-era SysScimProvider retired under
// #11757.
SysScimConnectionBinding,
SysScimConnectionCredential,
SysScimGroup,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ const OWNED_OBJECTS = new Set([
'sys_user_preference', 'sys_oauth_application', 'sys_oauth_access_token',
'sys_oauth_refresh_token', 'sys_oauth_consent', 'sys_oauth_resource',
'sys_oauth_client_resource', 'sys_oauth_client_assertion', 'sys_jwks',
// identity — external SSO / SCIM providers (admin-facing, better-auth-managed)
'sys_sso_provider', 'sys_scim_provider',
// identity — external SSO provider (admin-facing, better-auth-managed)
'sys_sso_provider',
// identity — stable @better-auth/scim 1.7.x model set + the ObjectStack-owned
// credential store (#3653; sys_scim_provider above retires under #11757)
// credential store (#3653; the rc.1-era sys_scim_provider retired under #11757)
'sys_scim_connection_binding', 'sys_scim_connection_credential', 'sys_scim_group',
'sys_scim_group_member', 'sys_scim_identity_tombstone', 'sys_scim_projection_grant',
'sys_scim_subject', 'sys_scim_user',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1894,47 +1894,6 @@ export const enObjects: NonNullable<TranslationData['objects']> = {
}
}
},
sys_scim_provider: {
label: "SCIM Provider",
pluralLabel: "SCIM Providers",
description: "SCIM 2.0 connections (bearer tokens) external IdPs use to provision/deprovision this environment's users",
fields: {
id: {
label: "ID"
},
provider_id: {
label: "Provider ID",
help: "Stable SCIM provider identifier (e.g. \"okta-scim\")"
},
provider_key: {
label: "Provider Key",
help: "Derived <organization>:<provider_id> uniqueness key maintained by @better-auth/scim; do not write directly."
},
scim_token: {
label: "SCIM Token (hash)",
help: "Hashed bearer credential for this SCIM connection — the plaintext is shown once at generate-token. Sensitive; do not expose."
},
organization_id: {
label: "Organization",
help: "Organization scope of this token (org-scoped tokens restrict provisioning to that org)"
},
user_id: {
label: "Owned By",
help: "User who generated this token (when provider-ownership is enabled)"
},
created_at: {
label: "Created At"
},
updated_at: {
label: "Updated At"
}
},
_views: {
all: {
label: "All"
}
}
},
sys_scim_connection_binding: {
label: "SCIM Connection Binding",
pluralLabel: "SCIM Connection Bindings",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1894,47 +1894,6 @@ export const esESObjects: NonNullable<TranslationData['objects']> = {
}
}
},
sys_scim_provider: {
label: "Proveedor SCIM",
pluralLabel: "Proveedores SCIM",
description: "Conexiones SCIM 2.0 (tokens bearer) que los IdP externos usan para aprovisionar/desaprovisionar los usuarios de este entorno",
fields: {
id: {
label: "ID"
},
provider_id: {
label: "ID de proveedor",
help: "Identificador de proveedor SCIM estable (p. ej. «okta-scim»)"
},
provider_key: {
label: "Provider Key",
help: "Derived <organization>:<provider_id> uniqueness key maintained by @better-auth/scim; do not write directly."
},
scim_token: {
label: "Token SCIM (hash)",
help: "Credencial bearer con hash de esta conexión SCIM: el texto plano se muestra una sola vez al generar el token. Sensible; no lo exponga."
},
organization_id: {
label: "Organización",
help: "Ámbito de organización de este token (los tokens por organización limitan el aprovisionamiento a esa organización)"
},
user_id: {
label: "Propiedad de",
help: "Usuario que generó este token (cuando la propiedad de proveedor está habilitada)"
},
created_at: {
label: "Creado el"
},
updated_at: {
label: "Actualizado el"
}
},
_views: {
all: {
label: "Todos"
}
}
},
sys_scim_connection_binding: {
label: "SCIM Connection Binding",
pluralLabel: "SCIM Connection Bindings",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -499,9 +499,6 @@ export const esESGeneratedSourceHashes: Readonly<Record<string, string>> = {
"objects.sys_scim_projection_grant.fields.user_id.label": "6c0d22a931e235bd",
"objects.sys_scim_projection_grant.label": "fbf273320dc0e8cb",
"objects.sys_scim_projection_grant.pluralLabel": "b8bb5769deedfbe3",
"objects.sys_scim_provider.fields.id.label": "00b0385c9c152888",
"objects.sys_scim_provider.fields.provider_key.help": "6eba9e41bfb954ab",
"objects.sys_scim_provider.fields.provider_key.label": "fbc96a8b3ed4709d",
"objects.sys_scim_subject._views.all.label": "6d6f653f8264ab17",
"objects.sys_scim_subject.description": "8fc839e493ef3e75",
"objects.sys_scim_subject.fields.created_at.label": "1f02d416befb595b",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1894,47 +1894,6 @@ export const jaJPObjects: NonNullable<TranslationData['objects']> = {
}
}
},
sys_scim_provider: {
label: "SCIM プロバイダー",
pluralLabel: "SCIM プロバイダー",
description: "外部 IdP がこの環境のユーザーをプロビジョニング/デプロビジョニングするために使用する SCIM 2.0 接続(ベアラートークン)",
fields: {
id: {
label: "ID"
},
provider_id: {
label: "プロバイダー ID",
help: "安定した SCIM プロバイダー識別子(例: 「okta-scim」)"
},
provider_key: {
label: "Provider Key",
help: "Derived <organization>:<provider_id> uniqueness key maintained by @better-auth/scim; do not write directly."
},
scim_token: {
label: "SCIM トークン(ハッシュ)",
help: "この SCIM 接続のハッシュ化されたベアラー資格情報——平文はトークン生成時に一度だけ表示されます。機密情報のため、公開しないでください。"
},
organization_id: {
label: "組織",
help: "このトークンの組織スコープ(組織スコープのトークンはプロビジョニングをその組織に限定します)"
},
user_id: {
label: "所有者",
help: "このトークンを生成したユーザー(プロバイダー所有権が有効な場合)"
},
created_at: {
label: "作成日時"
},
updated_at: {
label: "更新日時"
}
},
_views: {
all: {
label: "すべて"
}
}
},
sys_scim_connection_binding: {
label: "SCIM Connection Binding",
pluralLabel: "SCIM Connection Bindings",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,9 +492,6 @@ export const jaJPGeneratedSourceHashes: Readonly<Record<string, string>> = {
"objects.sys_scim_projection_grant.fields.user_id.label": "6c0d22a931e235bd",
"objects.sys_scim_projection_grant.label": "fbf273320dc0e8cb",
"objects.sys_scim_projection_grant.pluralLabel": "b8bb5769deedfbe3",
"objects.sys_scim_provider.fields.id.label": "00b0385c9c152888",
"objects.sys_scim_provider.fields.provider_key.help": "6eba9e41bfb954ab",
"objects.sys_scim_provider.fields.provider_key.label": "fbc96a8b3ed4709d",
"objects.sys_scim_subject._views.all.label": "6d6f653f8264ab17",
"objects.sys_scim_subject.description": "8fc839e493ef3e75",
"objects.sys_scim_subject.fields.created_at.label": "1f02d416befb595b",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1894,47 +1894,6 @@ export const zhCNObjects: NonNullable<TranslationData['objects']> = {
}
}
},
sys_scim_provider: {
label: "SCIM 提供方",
pluralLabel: "SCIM 提供方",
description: "外部 IdP 用于开通/停用本环境用户的 SCIM 2.0 连接(Bearer 令牌)",
fields: {
id: {
label: "ID"
},
provider_id: {
label: "提供方 ID",
help: "稳定的 SCIM 提供方标识符(如 “okta-scim”)"
},
provider_key: {
label: "Provider Key",
help: "Derived <organization>:<provider_id> uniqueness key maintained by @better-auth/scim; do not write directly."
},
scim_token: {
label: "SCIM 令牌(哈希)",
help: "该 SCIM 连接的哈希 Bearer 凭据——明文仅在生成令牌时显示一次。敏感信息,请勿泄露。"
},
organization_id: {
label: "组织",
help: "该令牌的组织范围(组织级令牌将开通限制在该组织内)"
},
user_id: {
label: "所有者",
help: "生成该令牌的用户(启用提供方归属时)"
},
created_at: {
label: "创建时间"
},
updated_at: {
label: "更新时间"
}
},
_views: {
all: {
label: "全部"
}
}
},
sys_scim_connection_binding: {
label: "SCIM Connection Binding",
pluralLabel: "SCIM Connection Bindings",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 +439,6 @@ export const zhCNGeneratedSourceHashes: Readonly<Record<string, string>> = {
"objects.sys_scim_projection_grant.fields.user_id.label": "6c0d22a931e235bd",
"objects.sys_scim_projection_grant.label": "fbf273320dc0e8cb",
"objects.sys_scim_projection_grant.pluralLabel": "b8bb5769deedfbe3",
"objects.sys_scim_provider.fields.id.label": "00b0385c9c152888",
"objects.sys_scim_provider.fields.provider_key.help": "6eba9e41bfb954ab",
"objects.sys_scim_provider.fields.provider_key.label": "fbc96a8b3ed4709d",
"objects.sys_scim_subject._views.all.label": "6d6f653f8264ab17",
"objects.sys_scim_subject.description": "8fc839e493ef3e75",
"objects.sys_scim_subject.fields.created_at.label": "1f02d416befb595b",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ import { SysTeam } from './sys-team.object.js';
import { SysTeamMember } from './sys-team-member.object.js';
import { SysApiKey } from './sys-api-key.object.js';
import { SysSsoProvider } from './sys-sso-provider.object.js';
import { SysScimProvider } from './sys-scim-provider.object.js';
import { SysTwoFactor } from './sys-two-factor.object.js';
import { SysAccount } from './sys-account.object.js';
import { SysSession } from './sys-session.object.js';
Expand Down Expand Up @@ -142,7 +141,6 @@ const OBJECTS: Array<[string, { actions?: unknown }]> = [
['sys_team_member', SysTeamMember],
['sys_api_key', SysApiKey],
['sys_sso_provider', SysSsoProvider],
['sys_scim_provider', SysScimProvider],
['sys_two_factor', SysTwoFactor],
['sys_account', SysAccount],
['sys_session', SysSession],
Expand Down
3 changes: 1 addition & 2 deletions packages/platform-objects/src/identity/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,9 @@ export { SysJwks } from './sys-jwks.object.js';
export { SysSsoProvider } from './sys-sso-provider.object.js';

// ── SCIM 2.0 provisioning (@better-auth/scim) ──────────────────────
// `SysScimProvider` is the rc.1-era connection row; it retires under #11757.
export { SysScimProvider } from './sys-scim-provider.object.js';
// The stable 1.7.x model set (#3653) — seven library-managed tables plus the
// ObjectStack-owned credential store the app-owned verifyBearerToken uses.
// (The rc.1-era `SysScimProvider` connection row retired under #11757.)
export { SysScimConnectionBinding } from './sys-scim-connection-binding.object.js';
export { SysScimConnectionCredential } from './sys-scim-connection-credential.object.js';
export { SysScimGroup } from './sys-scim-group.object.js';
Expand Down
Loading
Loading