Skip to content

Commit 89448a5

Browse files
Elon Muskclaude
andauthored
refactor(plugin-auth): remove the inert AUTH_SSO_PROVIDER_SCHEMA export (#13413)
AUTH_SSO_PROVIDER_SCHEMA was a publicly exported ssoProvider column mapping with zero code consumers -- four repo-wide hits: its own declaration, two frozen CHANGELOG lines and one comment, measured with a positive control on a live sibling symbol in the same file. Unlike the scim sibling (#11777), it was not inert by construction: @better-auth/sso@1.7.1 accepts SSOOptions.schema.ssoProvider and the runtime honours it -- the mapping was unused BY CHOICE (#10074 ruling A: the bridge stays at the adapter layer). Removed under ADR-0049 enforce-or-remove: it was a second source of truth for column names owned by the adapter layer (AUTH_MODEL_TO_PROTOCOL + mechanical camelCase-to-snake_case in objectql-adapter.ts) over the sys_sso_provider platform object, pinned by the sso/scim parity block. A NOTE in its place keeps the domainVerified / ADR-0024 (2) knowledge and records that the sso() schema option exists and is deliberately unused, so the absence reads as a choice rather than a limitation. The one comment in auth-manager.ts that pointed at the constant is retargeted to that NOTE (surface amendment declared on the card before editing). Claude-Session: https://claude.ai/code/session_012WkdHQwHr2KQmaX7P1BHzi Co-authored-by: Claude <noreply@anthropic.com>
1 parent 240aad5 commit 89448a5

3 files changed

Lines changed: 55 additions & 69 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@objectstack/plugin-auth': minor
3+
---
4+
5+
**BREAKING (public export removed):** `AUTH_SSO_PROVIDER_SCHEMA` no longer exists. It was an `ssoProvider` column mapping exported from `@objectstack/plugin-auth` (via `export * from './auth-schema-config.js'`) that nothing ever read — four repo-wide hits: its own declaration, two frozen CHANGELOG lines and one comment, measured against a positive control on a live sibling symbol in the same file, and corroborated by an org-wide code search that returned only this repo's own two files.
6+
7+
Unlike its scim sibling (removed the same way), this one was not inert by construction: `@better-auth/sso@1.7.1` genuinely accepts a schema option (`SSOOptions.schema.ssoProvider.{modelName,fields,additionalFields}`, honoured at runtime), and the mapping was still never handed to it — unused by choice (#10074, ruling A: the bridge stays at the adapter layer). Removed under ADR-0049 enforce-or-remove because it was a **second source of truth** for the same column names. The load-bearing one is the adapter layer — `AUTH_MODEL_TO_PROTOCOL` plus the mechanical camelCase-to-snake_case field resolution in `objectql-adapter.ts`, over the `sys_sso_provider` platform object that declares the columns — pinned by the dedicated sso/scim block in `better-auth-schema-parity.test.ts`. A dead copy is worse than none: nothing fails when it drifts from the live names, and the next reader cannot tell which of the two is authoritative.
8+
9+
A NOTE in its place keeps what outlives the constant: the `domainVerified` / ADR-0024 ② knowledge (the eighth field domain verification adds, its `domain_verified` column, and that the one-time `domainVerificationToken` is not a provider column), and the fact that the `sso()` schema option exists and is deliberately unused — so the absence reads as a choice, not as "sso accepts no schema option" (the stale claim #8224 swept).
10+
11+
Behaviour is unchanged. No SSO column name, platform object, adapter mapping or wire shape moves.
12+
13+
Breaking ships as `minor` per the launch-window convention (`scripts/check-changeset-no-major.mjs`).
14+
15+
<!-- adr-0087: not-required (no-migration-prescription) A dead public constant is deleted; nothing consumed it in this repo (measured on origin/main at 090f2302e with a positive control on a live symbol in the same file) or anywhere in the org (code search returned only this repo's own declaration and a comment), so no caller has code to rewrite. It is not a metadata surface: no Zod schema, no packages/spec declaration, no authorable key and no stored representation, so objectstack migrate meta has nothing to visit and there is no tombstone to mint. The column names it duplicated are unchanged and keep their real declaration on the sys_sso_provider platform object under the adapter's mechanical field rule; an external importer, if one exists, is told by the compiler at the import line, which is more precise than a ledger entry. Nothing to migrate, so no migration is prescribed. -->

packages/plugins/plugin-auth/src/auth-manager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3118,8 +3118,8 @@ export class AuthManager {
31183118
await this.addOptionalPlugin(plugins, 'sso', async () => {
31193119
const { sso } = await import('@better-auth/sso');
31203120
// NOTE: the `ssoProvider` model is bridged to `sys_sso_provider` by the
3121-
// better-auth adapter / a global model map, not per-plugin here (see
3122-
// AUTH_SSO_PROVIDER_SCHEMA).
3121+
// better-auth adapter / a global model map, not per-plugin here (see the
3122+
// `ssoProvider` NOTE in auth-schema-config.ts).
31233123
//
31243124
// That bridge dates from 1.6.20, where @better-auth/sso hardcoded the
31253125
// model and read no `schema` option. Re-measured against the installed

packages/plugins/plugin-auth/src/auth-schema-config.ts

Lines changed: 38 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -908,73 +908,44 @@ export const buildOidcProviderPluginSchema = buildOauthProviderPluginSchema;
908908
// SSO plugin – ssoProvider table (@better-auth/sso)
909909
// ---------------------------------------------------------------------------
910910

911-
/**
912-
* `@better-auth/sso` plugin `ssoProvider` model mapping.
913-
*
914-
* Each row is an external OIDC/SAML IdP this environment federates login to
915-
* (the relying-party side — ADR-0024's OPEN per-env SSO mechanism). The
916-
* protocol detail lives in JSON blobs (`oidcConfig` / `samlConfig`); the model
917-
* itself is thin.
918-
*
919-
* | camelCase (better-auth) | snake_case (ObjectStack) |
920-
* |:------------------------|:-------------------------|
921-
* | providerId | provider_id |
922-
* | oidcConfig | oidc_config |
923-
* | samlConfig | saml_config |
924-
* | userId | user_id |
925-
* | organizationId | organization_id |
926-
* | issuer / domain | (same name — no remap) |
927-
* | domainVerified | domain_verified |
928-
*
929-
* ## Coverage, measured 2026-08-20 against `@better-auth/sso@1.7.1`
930-
*
931-
* The previous note here said only "Mirrors `@better-auth/sso@1.6.20`'s
932-
* `BaseSSOProvider`" — a field-surface claim about a version two minors behind
933-
* the installed one, which nobody had re-checked. Re-measured by resolving the
934-
* plugin's real model the way the adapter does (`field.fieldName ?? key`) over
935-
* `getAuthTables({ plugins: [sso()] }).ssoProvider.fields`:
936-
*
937-
* - `sso()` declares 7 fields — `issuer`, `oidcConfig`, `samlConfig`,
938-
* `userId`, `providerId`, `organizationId`, `domain` — exactly the members
939-
* of the shipped `BaseSSOProvider` type
940-
* (`dist/index-CZytzKv6.d.mts:189-197`).
941-
* - `sso({ domainVerification: { enabled: true } })` — the shape
942-
* `OS_SSO_DOMAIN_VERIFICATION` turns on — adds an 8th, `domainVerified`.
943-
* - Every one of those 8 resolves to a column `sys_sso_provider` declares.
944-
* Nothing in the map is orphaned, and nothing in the model is unmapped.
945-
*
946-
* ⚠️ Unlike the core models, this mapping has **no parity gate**:
947-
* `better-auth-schema-parity.test.ts` deliberately passes `getAuthTables()` no
948-
* `sso` plugin, so an upstream field added to `ssoProvider` would land here
949-
* silently. Until that changes, re-run the resolution above by hand when the
950-
* `@better-auth/sso` pin moves — the check is one `getAuthTables` call.
951-
*/
952-
export const AUTH_SSO_PROVIDER_SCHEMA = {
953-
modelName: 'sys_sso_provider',
954-
fields: {
955-
providerId: 'provider_id',
956-
oidcConfig: 'oidc_config',
957-
samlConfig: 'saml_config',
958-
userId: 'user_id',
959-
organizationId: 'organization_id',
960-
// DNS domain-ownership proof (ADR-0024 ②). @better-auth/sso writes
961-
// `domainVerified` on its `ssoProvider` model when domain verification is
962-
// enabled; map it so the env can surface a verified/unverified badge. The
963-
// one-time `domainVerificationToken` is NOT a provider column — it lives in
964-
// the verification table and is returned only from request-domain-verification.
965-
domainVerified: 'domain_verified',
966-
},
967-
} as const;
968-
969-
// NOTE: there is intentionally no `buildSsoPluginSchema()`. The original reason
970-
// was that the plugin exposed NO `schema` option (true of 1.6.20) — that is no
971-
// longer why. Measured 2026-08-19 against the installed `@better-auth/sso@1.7.1`:
972-
// `SSOOptions.schema.ssoProvider.{modelName,fields,additionalFields}` exists and
973-
// the runtime honours it, so the mapping above COULD be handed to the plugin.
974-
// It is still consumed at the ADAPTER layer instead (AUTH_MODEL_TO_PROTOCOL +
975-
// field resolution in objectql-adapter.ts), which is now a deliberate choice
976-
// about where the bridge lives rather than a limitation of the dependency;
977-
// revisiting it is the open architecture question on #8224. See ADR-0024.
911+
// NOTE: there is intentionally no `ssoProvider` mapping constant here, and no
912+
// `buildSsoPluginSchema()`. Each `sys_sso_provider` row is an external
913+
// OIDC/SAML IdP this environment federates login to (the relying-party side —
914+
// ADR-0024's OPEN per-env SSO mechanism); protocol detail lives in JSON blobs
915+
// (`oidc_config` / `saml_config`), so the model itself is thin. Unlike scim
916+
// below, the absence of a mapping is a CHOICE, not a limitation of the
917+
// dependency: `@better-auth/sso@1.7.1` DOES accept a schema option —
918+
// `SSOOptions.schema.ssoProvider.{modelName,fields,additionalFields}` exists
919+
// and the runtime honours it (measured 2026-08-19, #8224) — so a mapping COULD
920+
// be handed to `sso({ schema })`. It deliberately is not (#10074, ruling A —
921+
// do not rewire the seam): the bridge lives at the ADAPTER layer, where
922+
// AUTH_MODEL_TO_PROTOCOL maps `ssoProvider` → `sys_sso_provider` and the
923+
// adapter's mechanical camelCase → snake_case field resolution
924+
// (objectql-adapter.ts) owns every column name — a rule total by
925+
// construction, where a hand-maintained per-field list is covered only if
926+
// someone remembers to update it. That layer is pinned by the dedicated
927+
// sso/scim block in better-auth-schema-parity.test.ts.
928+
//
929+
// `domainVerified` (ADR-0024 ②): with `sso({ domainVerification: { enabled:
930+
// true } })` — the shape `OS_SSO_DOMAIN_VERIFICATION` turns on — the plugin
931+
// writes an eighth `ssoProvider` field, `domainVerified` (DNS
932+
// domain-ownership proof), which the adapter rule resolves to
933+
// `domain_verified`, declared on the `sys_sso_provider` platform object so
934+
// the env can surface a verified/unverified badge. The one-time
935+
// `domainVerificationToken` is NOT a provider column — it lives in the
936+
// verification table and is returned only from request-domain-verification.
937+
// (The parity block constructs bare `sso()`, whose 7 declared fields exclude
938+
// `domainVerified`, so this eighth column rests on the platform-object
939+
// declaration plus the mechanical rule.)
940+
//
941+
// A mapping constant here would be a SECOND declaration of adapter-owned
942+
// column names that nothing reads and nothing enforces — it could drift from
943+
// the live ones with every gate green, and the next reader could not tell
944+
// which was authoritative (ADR-0049 enforce-or-remove); one was removed for
945+
// exactly that reason, mirroring the scim sibling below. Do not re-add one
946+
// unless it is actually handed to `sso({ schema })` — the one trigger #10074
947+
// named that would justify that rewiring is sso needing `additionalFields`,
948+
// which has no adapter-layer equivalent.
978949

979950
// ---------------------------------------------------------------------------
980951
// SCIM plugin – scim* tables (@better-auth/scim)

0 commit comments

Comments
 (0)