Skip to content

feat(spec)!: 跨形态同名三条收敛 — ShareRecipientType / TransformType / suggestFieldType (#4539) - #4571

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-4539-cross-form-dual-source
Aug 2, 2026
Merged

feat(spec)!: 跨形态同名三条收敛 — ShareRecipientType / TransformType / suggestFieldType (#4539)#4571
os-zhuang merged 1 commit into
mainfrom
claude/issue-4539-cross-form-dual-source

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes#4539

基线里最阴险的三条:同名但不同形态(type≠const,或两个不相干的 function),选错一侧连"形状重叠、编译通过"的掩护都没有。每条都按三仓 import 级扫描(framework、/workspace/cloud、objectui 浅克隆)单独判真源 —— cloud 与 objectui 对这三个名字的引用均为零,全部消费方都在本仓。

逐条判定

1. ShareRecipientType — 改名(两个活概念共用一名)

  • 真源(保名):security/sharing.zod.ts 的 zod enum(user | team | position | unit_and_subordinates | business_unit)—— 可授权的共享规则收件人词表,被 SharingRuleSchema.sharedWith.type 直接消费,与 contracts 的 SharingRuleRecipientType(多一个保留的 queue)本来就是刻意配对。
  • contracts 侧:描述的是另一个概念 —— sys_record_share 行的 recipient_type。它自称 "mirrors spec/security" 早已失真(security 侧 groupteamguest 已删),且成员 role 与存储侧 select(user | group | position | unit_and_subordinates | guest)不符 —— role 从来不是可持久化的值。改名 RecordShareRecipientType,成员对齐存储 select(roleposition,补完 ADR-0090 D3 leftovers in plugin-sharing: sys_record_share role recipient enum + "角色及下级" translations #2724 D3 改名在 changelog 里声称完成、实际漏掉的那一半),注释改为指向它真正镜像的存储侧 gate。plugin-sharing 的 re-export 同步改名;运行时仍只强制 user(grant() 拒绝其余值),行为零变化。测试里原本被迫的 as any 铸型随之删除 —— 类型现在能如实表达。

2. TransformType — 改名(shared 侧双名零消费者)

  • 真源(保名):data/mapping.zod.ts 的导入映射 enum(none | constant | lookup | split | join | javascript | map),被 ImportMapping 的 transform 字段活消费。
  • shared 侧:TransformTypeSchema(transform 配置对象的 discriminated union,形态完全不同)+ 推断类型别名 TransformType,两个名字在三仓都是零 importer。整对改名 FieldMappingTransformSchema / FieldMappingTransform(它就是 FieldMapping.transform 的取值)。为什么不是只删别名:build-docs 生成 import type { X } 示例时机械剥 Schema 后缀,别名不在了文档照样宣传一个不存在的导出 —— 该生成器缺陷已按第十条军规单独立案 build-docs.ts 用「剥掉 Schema 后缀」推导 import type 示例,类型别名不存在时生成的文档引用无法编译 #4570(unassigned)。json-schema.manifest.jsonshared/TransformType 键随之改为 shared/FieldMappingTransform(蓄意改名,非静默下架)。不引入过渡别名:零消费者,干净断,changeset 带 FROM → TO。

3. suggestFieldType先 diff 两份实现,行为判定如下

两份实现从来不是同一函数的分叉,是两个用途不相干的函数共用一名,签名、语义、返回类型全不同:

输入shared/suggestions.zod(. + ./shared,同一符号)data/type-compat(./data)
签名(input: string) => string[](rawType: string, dialect?: SqlDialect) => FieldType | undefined
用途作者拼错 FieldType 时的 "Did you mean?"(别名表 + Levenshtein),喂 zod error mapSQL 列类型 → ObjectStack 字段类型的确定性映射(ADR-0015 §4.6,外部数据源起草)
'varchar(255)'[](模糊匹配不到)'text'
'text_area'['textarea']undefined(不是 SQL 类型)
'int'['number'](数组)'number'(标量)

不是潜伏 bug:两个调用方(error map、service-datasource)各自 import 的都是自己要的那份,运行时行为无分歧。真正的危险在编写时选错:auto-import 按名挑错一侧后,标量位置来了个数组 —— 而 [] 是 truthy,if (suggested) 这类写法编译通过、静默走错分支。处置:./data 侧改名 suggestFieldTypeForSqlType(typo-suggester 保名保 root 导出);上表的行为分歧已固化为 type-compat.test.ts 里的交叉 pin,两函数若日后被人为归并,pin 会逼着显式删除。

基线

dual-source-exports.baseline.json 恰好删除 3 行(gate 点名的即这 3 行,main 移动未产生额外 stale 行):

  • ShareRecipientType — [./contracts (type)] ≠ [./security (const)]
  • TransformType — [./data (const)] ≠ [./shared (type)]
  • suggestFieldType — [., ./shared (function)] ≠ [./data (function)]

验证

  • pnpm --filter @objectstack/spec build
  • check:generated8/8 up to date ✅(api-surface + reference docs 经 --fix 定向再生)
  • check:dual-source-exports ✅(self-test 通过;4306 名字 / 16 入口,基线 38 → 35)
  • spec test:287 文件 / 7271 用例全过 ✅;spec typecheck
  • 全仓 pnpm build 71/71 ✅、pnpm typecheck 122/122 ✅、pnpm test 132/132 ✅

Changeset

@objectstack/spec: major@objectstack/plugin-sharing: major,三条 FROM → TO 迁移各带一行修法(升级 agent grep 得到)。

范围外发现

🤖 Generated with Claude Code

https://claude.ai/code/session_01M9uWvoEp9CoLzYjNExj9sL


Generated by Claude Code

The three baseline rows where the two declarations sharing a name did not
even share a FORM (type vs const, or two unrelated functions), so a wrong
import-path pick had no shape overlap to hide behind. Each judged against a
three-repo import-level scan (framework, cloud, objectui — the latter two
contain zero references to all three names).
- ShareRecipientType: the security zod enum (authorable sharing-RULE
recipients) keeps the name; the contracts type is a DIFFERENT concept —
the recipient_type a sys_record_share ROW may carry — renamed
RecordShareRecipientType, member set aligned to the storage select it
actually mirrors ('role', never persistable, -> 'position', completing
the #2724 D3 rename its changelog already claimed). plugin-sharing
re-export renamed in lockstep; only 'user' is enforced today, unchanged.
- TransformType: the data import-mapping enum keeps the name; shared's
differently-shaped config-union pair (zero importers for either name in
all three repos) renamed FieldMappingTransformSchema /
FieldMappingTransform. Renamed rather than alias-deleted because
build-docs derives `import type` examples by stripping 'Schema' (filed
unassigned as #4570). json-schema.manifest key moved with it.
- suggestFieldType: diffed the two implementations FIRST — they were never
forks of one function: shared/suggestions.zod is the typo-suggester
(string -> string[] candidates, feeds the zod error map, keeps the name
on . and ./shared); data/type-compat is the deterministic SQL-column ->
FieldType mapper (ADR-0015), renamed suggestFieldTypeForSqlType.
Divergence pinned in type-compat.test.ts: ('varchar(255)') -> [] vs
'text'; ('text_area') -> ['textarea'] vs undefined; ('int') ->
['number'] vs 'number'. Not a live bug: each caller imports the one it
means; the hazard was authoring-time wrong-pick, where `[]` is truthy.
All 3 dual-source-exports.baseline.json rows deleted; api-surface and
reference docs regenerated via check:generated --fix (8/8 green);
check:dual-source-exports green at 35 baseline rows.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M9uWvoEp9CoLzYjNExj9sL
@vercel

vercelBot commented Aug 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 2, 2026 7:19am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation protocol:data tests tooling size/m labels Aug 2, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/plugin-sharing, @objectstack/service-datasource, @objectstack/spec.

107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/spec)
  • content/docs/api/environment-routing.mdx(via @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via @objectstack/spec)
  • content/docs/automation/connectors.mdx(via @objectstack/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via packages/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/cli.mdx(via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via packages/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via packages/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/plugin-sharing, @objectstack/spec)
  • content/docs/kernel/services.mdx(via @objectstack/spec)
  • content/docs/permissions/authorization.mdx(via packages/plugins/plugin-sharing, @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via packages/plugins/plugin-sharing, @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/rls.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @objectstack/plugin-sharing, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/plugins/plugin-sharing, packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx(via @objectstack/plugin-sharing, @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v16.mdx(via @objectstack/spec)
  • content/docs/releases/v17.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/spec)
  • content/docs/ui/actions.mdx(via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/spec)
  • content/docs/ui/translations.mdx(via @objectstack/spec)
  • content/docs/ui/views.mdx(via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

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

Labels

documentationImprovements or additions to documentationprotocol:datasize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[#4535·B] 跨形态同名三条:ShareRecipientType(type≠const)、TransformType(const≠type)、suggestFieldType(双实现 function)

2 participants

@os-zhuang@claude