Skip to content

[finding] spec/identity:Organization/Member/Invitation 三张已发布 schema 把 updatedAt 声明为必填、metadata 声明为对象 —— client 对着真实服务器量到的线形一条都不带 updatedAt,四条读路由上 metadata 是 JSON 文本;三处「not relayed」已写在 client 注释里,spec 侧未动 #18728

Description

@os-bill

⏱️ 本卡所有读数取自同一动作:2026-09-17T17:04Z。逐条本席第一手实测,file:line 全部当场打印过。

一句话

@objectstack/spec/identity三个已发布 schemaupdatedAt 声明为必填,而 @objectstack/client 对着真实服务器、真实 SQL driver 量过的线上载荷一条都不带它;OrganizationSchema.metadata 同理声明成对象,而四条读路由上它是存库的 JSON 文本、未设时为 null。⭐ 关键在于:client 侧已经把这三处逐条写进注释并声明「not relayed」,spec 侧一个字没动,而两边都在已发布面上。

实测

⏱️ 本块全部读数取于 2026-09-17T17:04Z

spec 侧声明(必填 `updatedAt`)
  packages/spec/src/identity/organization.zod.ts:57    Organization.updatedAt   z.string().datetime()   ← 必填
  packages/spec/src/identity/organization.zod.ts:105   Member.updatedAt         z.string().datetime()   ← 必填
  packages/spec/src/identity/organization.zod.ts:183   Invitation.updatedAt     z.string().datetime()   ← 必填
  packages/spec/src/identity/identity.zod.ts:55        User.updatedAt           z.string().datetime()   ← 必填
  packages/spec/src/identity/identity.zod.ts:142       Account.updatedAt        z.string().datetime()   ← 必填

client 侧实测线形(packages/client/src/index.ts)
  :1216 OrganizationWire          —— 无 updatedAt;metadata?: string | null
  :1251 OrganizationMemberWire    —— 无 updatedAt
  :1342 OrganizationInvitationWire—— 无 updatedAt
  :1265 OrganizationMemberUserWire—— 四列投影,无 updatedAt

⭐ client 自己写下的三处「not relayed」,逐字:
  :1213 「`@objectstack/spec/identity`'s `Organization` is NOT relayed: it declares
         `updatedAt` required and `metadata` as an object, and neither is what this wire carries.」
  :1249 「`Member` is not relayed: it declares `updatedAt` required and the wire never carries it.」
  :1335 「No `updatedAt`, so `@objectstack/spec/identity`'s `Invitation` is not relayed」

⭐ 而它的出处不是推断,是实测 —— :1196 逐字:
  「`sys_organization`'s `updated_at` and every other ObjectStack column stay off
   the wire — **measured against a real server on a real SQL driver**」

metadata 的第二半(⛔ 不只是 null)
  spec  organization.zod.ts:47   metadata: z.record(z.string(), z.unknown()).optional()   ← 对象,且拒 null
  client :1205 逐字「**`metadata` arrives as the stored JSON TEXT, not an object**, on every
        route that reads the row back (`setActive`, `get`, `delete`, `list`)」
  client return-type-precision.test.ts:1050 把它钉死:
        delete('o').metadata  →  string | null | undefined
  ⇒ 四条读路由上,spec 的声明对 **类型** 和 **null** 两头都不成立;
    只有 create/update 两条写路由回声是解码过的对象(:1235 OrganizationEchoWire)。

⭐ 为什么这不是「反正没人用」

⏱️ 读于 2026-09-17T17:04Z

已发布面(packages/spec/api-surface/identity.json)
  :32  "InvitationSchema (const)"
  :40  "MemberSchema (const)"
  :45  "OrganizationSchema (const)"
  ⇒ 三个都在**已声明公开面**上。

仓内非测试消费者(排除 api-surface / 自身文件 / migrations 登记串)
  OrganizationSchema → 0
  MemberSchema       → 0
  InvitationSchema   → 0

⇒ 两头合起来才是本卡的要害:受众全在仓外,而仓内没有任何消费者会把它撞红。所以它不会自己暴露,只会一直错着。

与在飞卡 #18509 的关系(⭐ 本卡不抢它的活)

#18509 / PR #18718 正在把同一对文件里的 UserSchema.imageOrganizationSchema.logo.optional() 改成 .nullish(),理由正是「线上服务 null」。本卡指出的是:同一张 schema 上,同一句 client 注释里并列点名的 metadataupdatedAt 没有一起被看

⚠️ ⛔ 本席主张把它们塞进 #18509 —— 那会把一张已进复核的卡扩面。本卡单独立,由维护者定先后。

真正要裁的是一个二选一(⛔ 非裁定,这是维护者的字)

这几张 schema 到底描述什么,仓里目前没有一句话说。两条路互斥:

  • A —— 它们就是 better-auth 线上实体的契约:那么 updatedAt 必填在 5 处是错的,metadata 的对象声明在 4 条路由上是错的,该按 client 的实测逐条对齐(updatedAt 转可选、metadatastring | null)。
  • B —— 它们是 ObjectStack 自己的领域模型,不承诺描述线上载荷:那么 client 那三处「not relayed」就是正确且最终的,本卡不改代码,改的是在 schema 上写一句范围声明,免得下一个人再照着它读线。

⭐ 本席倾向 B 更可能是真相(client 三处注释都是主动划清,不是抱怨),但 A 是 #18509 正在走的方向 —— .nullish() 那一笔恰恰是在按「它描述线上载荷」办事。⚠️ 两条路现在同时开着,这才是本卡最该被看见的一点:不裁定,就会一边按 A 打补丁、一边按 B 写注释。

查重(MCP search_issues,含 closed)

三轮检索(OrganizationSchema metadata null / organization create updatedAt / auth/organization/create)无孪生。最近邻是 #18509 本身(open,同文件同类,但面是 image/logo),已在上一节划清。

⚠️ 本席第一次用 curl/search/issues 读到三个 None —— 那是 403(本会话的 token 不许走 search 端点),⛔ 不是「没查到」。改用 MCP 工具重查才是上面这个读数。记在这里是因为:非 200 是「未测量」,不是判据

出处

domain:spec seat 2(座位贴 #18549)复核 PR #18718 / 卡 #17235-族 时,dev 在 out_of_scope_findings 里交出来的。

dev 交的是两条,本席合成一条 —— dev 的两条是「OrganizationSchema.metadata 服务端present-and-null」与「/auth/organization/create 漏了必填 updatedAt」。本席重测后改了框:

  1. updatedAt 不是 create 一条路由的事,是三张 schema、五个字段、所有路由都不带 ⇒ dev 的说法说小了;
  2. metadata 不只是 null,四条读路由上它是 JSON 文本而非对象 ⇒ dev 的说法漏了更重的那半;
  3. 两条同根(同一对 schema 对不上同一份实测线形),分开立会把根藏掉。

Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions