重写。 原帖(以及第一次更新)问的是"要不要补齐 SCIM group 的四张平台对象表"。去调研 rc.2 之后,这个问题的前提没有了 —— rc.2 把 SCIM 整个重设计了,rc.1 的那四张表在上游已经不存在。所以本 issue 现在记录的是一个决定和它的理由,不是一个待办。
决定
停在 @better-auth/scim@1.7.0-rc.1,不补 group 表,不升 rc.2。等 SCIM 出正式版之后,作为一次独立的架构迁移一起做。
为什么不补 rc.1 的四张表
照 rc.1 实现,等于照着上游已经废弃的 schema 建四张表:
scimGroupRole / scimGroupRoleGrant 在 rc.2 里已经没了;
scimGroup / scimGroupMember 名字还在,但列完全不同(rc.2 的 scimGroup 多了 connection_id / revision / display_name_key / order_key)。
写出来就是即刻过时的迁移债,而且是带数据的那种。
为什么不升 rc.2
rc.2 不是一次版本升级,是一次架构迁移。三点,按严重程度排:
1. scimProvider 整个消失了
rc.2 里全文 0 处引用。而 sys_scim_provider 是 ObjectStack 唯一有的 SCIM 平台对象 —— 也就是 #3688 刚给它补上 provider_key 的那张表。它在 rc.2 下没有对应的上游模型。
2. 模型换了一套
|
模型 |
| rc.1(当前) |
scimProvider、scimGroup、scimGroupMember、scimGroupRole、scimGroupRoleGrant |
| rc.2 |
scimConnectionBinding、scimIdentityTombstone、scimSubject、scimUser、scimProjectionGrant、scimGroup、scimGroupMember |
5 个换 7 个,只有两个名字重合,而这两个的列也不一样。
3. 连接从"运行时数据行"变成了"启动时配置"
rc.2 的 scim() 在构造时强制要求静态声明 connections:
BetterAuthError: The scim plugin requires at least one provisioning connection.
而 auth-manager.ts 现在传的是 scim({ storeSCIMToken: 'hashed' }) —— 没有 connections,rc.2 下直接抛错。
这一条比 schema 变更严重得多:它把 SCIM 连接从「数据库行 + /scim/generate-token 端点 + Setup UI 管理」搬到了「进程启动配置」。token 由谁产生、存在哪、怎么轮换,全都变了,连带影响 Setup UI 和 generate-token 那一整条链路。
现在是什么状态(不是"坏的",是"有边界的")
所以开启 SCIM 的部署,今天不要让 IdP 推送 group。 这是接受这个决定的代价,写在这里而不是让人踩。
parity gate 怎么守住这段时间
gate(better-auth-schema-parity.test.ts)没有假装覆盖到了。四个无对象的 model 在一个 KNOWN_UNMAPPED_MODELS 精确集合里,并且集合本身被断言:
- 出现新的无对象 model → 构建失败;
- 某个 model 不再在集合里(说明已经 provision 了)→ 也失败,提示把它挪进列检查。
也就是说:真去升 rc.2 的那一刻,gate 会立刻把这七个模型的差异全部报出来,不会有第二个"悄悄长出来的洞"。这正是它该起的作用。
重启这件事的触发条件
@better-auth/scim 发布正式版(非 rc)。到那时一并处理,作为一个独立的迁移任务:
- 按正式版的模型集补齐平台对象(届时以正式版为准,不是 rc.2);
- 决定
sys_scim_provider 的去向 —— 迁移还是废弃;
- 重做连接配置模型(静态
connections vs 现有的 generate-token + Setup UI);
auth-manager.ts 的 scim({...}) 调用补上必需参数。
一处独立的遗留张力(与版本无关)
sys_scim_provider 上有 { fields: ['provider_id'], unique: true },但 rc.1 上游的唯一性边界是 <organization>:<provider_id> —— 同一个 provider_id 在两个不同组织下,上游认为合法,而这个索引会拒绝。
比库假设的约束更严。#3688 里没有动它:放宽一个已经生效的唯一约束是独立的决定,而且要先确认当初是不是有意为之。记在这里,不随 SCIM 迁移绑定 —— 它今天就可以单独判断。
已经做完的部分(原帖的问题)
原帖最初问的是"parity gate 覆盖不到 sso/scim"。这一点已经修好并合并:两个 plugin 虽然不接受 schema option,但它们自己暴露 .schema,而 adapter 对 bridged model 的列名规则是机械的 camelCase → snake_case。gate 现在读前者、套后者,算出它们真正会写的列。
Refs #3624, #3647, #3688, ADR-0071。
重写。 原帖(以及第一次更新)问的是"要不要补齐 SCIM group 的四张平台对象表"。去调研 rc.2 之后,这个问题的前提没有了 —— rc.2 把 SCIM 整个重设计了,rc.1 的那四张表在上游已经不存在。所以本 issue 现在记录的是一个决定和它的理由,不是一个待办。
决定
停在
@better-auth/scim@1.7.0-rc.1,不补 group 表,不升 rc.2。等 SCIM 出正式版之后,作为一次独立的架构迁移一起做。为什么不补 rc.1 的四张表
照 rc.1 实现,等于照着上游已经废弃的 schema 建四张表:
scimGroupRole/scimGroupRoleGrant在 rc.2 里已经没了;scimGroup/scimGroupMember名字还在,但列完全不同(rc.2 的scimGroup多了connection_id/revision/display_name_key/order_key)。写出来就是即刻过时的迁移债,而且是带数据的那种。
为什么不升 rc.2
rc.2 不是一次版本升级,是一次架构迁移。三点,按严重程度排:
1.
scimProvider整个消失了rc.2 里全文 0 处引用。而
sys_scim_provider是 ObjectStack 唯一有的 SCIM 平台对象 —— 也就是 #3688 刚给它补上provider_key的那张表。它在 rc.2 下没有对应的上游模型。2. 模型换了一套
scimProvider、scimGroup、scimGroupMember、scimGroupRole、scimGroupRoleGrantscimConnectionBinding、scimIdentityTombstone、scimSubject、scimUser、scimProjectionGrant、scimGroup、scimGroupMember5 个换 7 个,只有两个名字重合,而这两个的列也不一样。
3. 连接从"运行时数据行"变成了"启动时配置"
rc.2 的
scim()在构造时强制要求静态声明connections:而
auth-manager.ts现在传的是scim({ storeSCIMToken: 'hashed' })—— 没有connections,rc.2 下直接抛错。这一条比 schema 变更严重得多:它把 SCIM 连接从「数据库行 +
/scim/generate-token端点 + Setup UI 管理」搬到了「进程启动配置」。token 由谁产生、存在哪、怎么轮换,全都变了,连带影响 Setup UI 和generate-token那一整条链路。现在是什么状态(不是"坏的",是"有边界的")
OS_SCIM_ENABLED),爆炸半径仅限显式开启的部署。provider_key,那是 SCIM 一打开就会撞上的第一个坑。/Groups推送会写四张不存在的表,和 org creation over HTTP 500s when teams are enabled: better-auth 1.7.0-rc.1 default team carries memberCount, sys_team lacks the column/mapping #3624 同一个失败形状。这四个 model 在 rc.1 的插件代码里是无条件使用的,没有开关能关掉它。所以开启 SCIM 的部署,今天不要让 IdP 推送 group。 这是接受这个决定的代价,写在这里而不是让人踩。
parity gate 怎么守住这段时间
gate(
better-auth-schema-parity.test.ts)没有假装覆盖到了。四个无对象的 model 在一个KNOWN_UNMAPPED_MODELS精确集合里,并且集合本身被断言:也就是说:真去升 rc.2 的那一刻,gate 会立刻把这七个模型的差异全部报出来,不会有第二个"悄悄长出来的洞"。这正是它该起的作用。
重启这件事的触发条件
@better-auth/scim发布正式版(非 rc)。到那时一并处理,作为一个独立的迁移任务:sys_scim_provider的去向 —— 迁移还是废弃;connectionsvs 现有的generate-token+ Setup UI);auth-manager.ts的scim({...})调用补上必需参数。一处独立的遗留张力(与版本无关)
sys_scim_provider上有{ fields: ['provider_id'], unique: true },但 rc.1 上游的唯一性边界是<organization>:<provider_id>—— 同一个provider_id在两个不同组织下,上游认为合法,而这个索引会拒绝。比库假设的约束更严。#3688 里没有动它:放宽一个已经生效的唯一约束是独立的决定,而且要先确认当初是不是有意为之。记在这里,不随 SCIM 迁移绑定 —— 它今天就可以单独判断。
已经做完的部分(原帖的问题)
原帖最初问的是"parity gate 覆盖不到 sso/scim"。这一点已经修好并合并:两个 plugin 虽然不接受
schemaoption,但它们自己暴露.schema,而 adapter 对 bridged model 的列名规则是机械的 camelCase → snake_case。gate 现在读前者、套后者,算出它们真正会写的列。@better-auth/sso完全干净 ✅sys_scim_provider缺provider_key→ 已补(fix(auth): close the sso/scim parity hole; provision sys_scim_provider.provider_key (#3653) #3688)Refs #3624, #3647, #3688, ADR-0071。