Skip to content

Commit d082139

Browse files
committed
chore: add changeset for #13439
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mciyv38maJ6HYVMiaM26T1
1 parent 3c531b6 commit d082139

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
"@objectstack/spec": minor
3+
"@objectstack/plugin-auth": minor
4+
---
5+
6+
feat(spec,plugin-auth): declare `plugins.scim` / `plugins.sso` / `plugins.ssoDomainVerification`, and let an explicit config value win over the env var (#13439)
7+
8+
**Behavior change** (maintainer ruling 2026-08-31 on #13439).
9+
10+
Two halves of one contract gap:
11+
12+
- **Declaration.** `AuthPluginConfigSchema` now declares `scim`, `sso` and
13+
`ssoDomainVerification` as tri-state `z.boolean().optional()`, following the
14+
`dynamicClientRegistration` template. Previously the keys were read by
15+
`plugin-auth` through an `as any` cast while no schema declared them — a key
16+
an author could write, that typechecked only via the cast, that no
17+
publish-time validation would ever reject or confirm.
18+
- **Precedence flip.** For these three keys an EXPLICIT config value now wins
19+
over the corresponding env var (`OS_SCIM_ENABLED` / `OS_SSO_ENABLED` /
20+
`OS_SSO_DOMAIN_VERIFICATION`); the env var decides only where the config
21+
leaves the key UNSET (absent env ⇒ off). Previously the env var always won,
22+
so `plugins: { scim: false }` had no effect at all whenever
23+
`OS_SCIM_ENABLED` was set — a line that read as a security control, passed
24+
review and typecheck, and did nothing. The operator per-environment override
25+
is preserved for every deployment that leaves the keys unset. The other
26+
env-paired keys (`oidcProvider`, `dynamicClientRegistration`, `twoFactor`,
27+
`passwordRejectBreached`) deliberately keep their documented env-wins order.
28+
29+
The ADR-0071 forced-admin coupling is unchanged in shape
30+
(`admin: pluginConfig.admin ?? scimEffective`): effective SCIM still forces
31+
the better-auth `admin` plugin on when `admin` is unset — but the flipped
32+
resolution flows through it, so an explicit `plugins.scim: false` now also
33+
declines the admin plugin it would have dragged in. The admin coupling itself
34+
is out of this change's scope (#13816 tracks it).
35+
36+
**Known risk, named:** a deployment that writes BOTH an explicit value and the
37+
env var and depends on the env winning will flip. The only known explicit
38+
writer is the cloud control plane, which requires the new order (its
39+
plan-derived `plugins.scim` must be authoritative; cloud#1265's refuse-to-build
40+
workaround can retire once this lands).
41+
42+
<!-- adr-0087: not-required (no-migration-prescription) Additive declaration of three previously-undeclared optional keys plus a documented precedence flip: no key is removed, renamed or re-shaped, no tombstone exists, and nothing mechanical for `objectstack migrate meta` to rewrite. The affected quadrant (explicit value AND env var set, relying on env winning) has a measured population of one writer — the cloud control plane — which requires the new order. -->

0 commit comments

Comments
 (0)