Skip to content

SCIM: 停在 @better-auth/scim rc.1,等正式版再整体迁移 —— rc.2 换掉了整套模型 #3653

Description

@os-zhuang

重写。 原帖(以及第一次更新)问的是"要不要补齐 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(当前) scimProviderscimGroupscimGroupMemberscimGroupRolescimGroupRoleGrant
rc.2 scimConnectionBindingscimIdentityTombstonescimSubjectscimUserscimProjectionGrantscimGroupscimGroupMember

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)。到那时一并处理,作为一个独立的迁移任务:

  1. 按正式版的模型集补齐平台对象(届时以正式版为准,不是 rc.2);
  2. 决定 sys_scim_provider 的去向 —— 迁移还是废弃;
  3. 重做连接配置模型(静态 connections vs 现有的 generate-token + Setup UI);
  4. auth-manager.tsscim({...}) 调用补上必需参数。

一处独立的遗留张力(与版本无关)

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。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions