Skip to content

feat(spec): share-link enforcement 路径改收完整 ExecutionContext,窄类型只服务路由 401 (#6430) - #6511

Merged
qq9340100 merged 1 commit into
mainfrom
claude/issue-6430-sharelink-execution-context
Aug 8, 2026
Merged

feat(spec): share-link enforcement 路径改收完整 ExecutionContext,窄类型只服务路由 401 (#6430)#6511
qq9340100 merged 1 commit into
mainfrom
claude/issue-6430-sharelink-execution-context

Conversation

@qq9340100

Copy link
Copy Markdown
Collaborator

Fixes #6430

#6206 维护者 2026-08-07 裁决 A 案(comment 5219847367)的契约半边。只动 packages/spec 契约面,plugin-sharing 消费半边一行未碰。

改了什么

packages/spec/src/contracts/share-link-service.ts:

  1. 三个 enforcement 方法改收完整 ExecutionContext —— createLink / revokeLink / listLinks 的 context 参数从五字段的 ShareLinkExecutionContext 换成 ExecutionContext(z.input,即 caller 侧信封形状)。三个方法都在裁定访问:

    • createLink —— [Finding-2] 的可见性重读(只能为自己看得见的记录建链接);
    • revokeLink —— ADR-0111 D8 的 record share-manager 探针吃 context;
    • listLinks —— 列表本身在 context 下读,行可见性由它决定。

    所以三处都需要整份 resolveAuthzContext 结果:accessible_org_idsorg_user_idssystemPermissionsposturetabPermissionsresolveToken 不收 context,未动。

  2. 窄类型保留、形状不变,但 TSDoc 把边界写死:ShareLinkExecutionContext 明确降级为路由自身 401 的词汇(userId 在 ⇒ 放行,不在 ⇒ 401 —— 这个判断不读任何授权维度,所以不需要授权信封),并写明 ⛔ 不得进入任何 enforcement 路径,附上失效实据(group 姿态下 accessible_org_ids 就是 Layer 0 墙,ADR-0105 D2,缺席即拒 ⇒ 建链全量 403)与治理理由(ADR-0095 D2:posture 解析一次、随上下文流动、永不在 enforcement 处重推;本例是同族第三处组装,前两处 HookContext 契约表把 before*input.options 记成 DriverOptions —— 实测那里仍是调用方的 engine options(含 where),两个 break-glass 守卫正读它 #5997 / 两处手写的 ExecutionContext 组装已漂移:REST 传输不带 principalKind / onBehalfOf,而 explain / security 会读它 #6071)。

  3. pin 测试 packages/spec/src/contracts/share-link-service.test.ts(3 cases + 7 条类型级断言)。

⚠️ 一个必须说清的事实:本次契约收紧不会让消费方编译红

分诊评论预期「今天能编译的 caller 之后编译不过」。实测不成立,方向要反过来读:

  • TypeScript 的结构化子类型让 ShareLinkExecutionContext 可以赋给 ExecutionContext(五个字段在宽类型里都存在且类型兼容,而宽类型没有任何必填字段);方法参数又是双变的,所以 ShareLinkService implements IShareLinkService 也照样成立。
  • 实测:pnpm --filter @objectstack/plugin-sharing typecheck 在本分支上绿

也就是说,没有编译器在等着推消费半边一把 —— 那半边必须被有意识地做掉,不能指望 CI 变红来提醒。这条我已写进窄类型的 TSDoc 与 pin 测试的头注释,免得下一个读者把「没有 @ts-expect-error」误读成疏漏。

契约能做的、也是本 PR 做到的,是把 enforcement 参数类型声明成完整信封,于是裁剪动作在调用点可见(调用点写着 ExecutionContext,评审能看见一个五字段对象被塞进去),而不再藏在一个「看起来就是为这活儿设计的」类型后面。

反向验证(方向在跑之前先定,结果与预测一致)

预测:把三处签名改回 ShareLinkExecutionContext,测试层应当变红 —— 身份断言 TS2344 + 整信封字面量的 TS2353 excess-property。实测(tsc --noEmit -p tsconfig.test.json)恰好 7 条新错误(274 vs. debt 基线 267):

share-link-service.test.ts(66,52): error TS2344: Type 'false' does not satisfy the constraint 'true'.
share-link-service.test.ts(67,52): error TS2344: Type 'false' does not satisfy the constraint 'true'.
share-link-service.test.ts(68,52): error TS2344: Type 'false' does not satisfy the constraint 'true'.
share-link-service.test.ts(71,46): error TS2344: Type 'true' does not satisfy the constraint 'false'.
share-link-service.test.ts(72,46): error TS2344: Type 'true' does not satisfy the constraint 'false'.
share-link-service.test.ts(73,46): error TS2344: Type 'true' does not satisfy the constraint 'false'.
share-link-service.test.ts(134,9): error TS2353: Object literal may only specify known properties,
  and 'accessible_org_ids' does not exist in type 'ShareLinkExecutionContext'.

前 6 条是三个方法的类型身份 pin(参数类型 ExecutionContext不是窄类型);第 7 条是本文件真正的 before-red:整份信封写成对象字面量,excess-property 检查因此生效 —— 旧签名下 accessible_org_ids 等五个键每一个都是 TS2353,这正是当初路由宁可手工拼一个子集也不肯把已解析好的信封原样传下去的原因。

三个运行时 case 不是空跑:fake service 记录收到的 context,断言 accessible_org_ids / posture / org_user_ids / systemPermissions / tabPermissions 确实整份抵达。

下游半边的解锁点

本卡落地后,identity 车道的消费半边(Blocked-by: #6430)可以开工,落点两处:

  1. packages/plugins/plugin-sharing/src/sharing-plugin.tscontextFromRequest(:633-639)—— 不再裁剪,把 resolveAuthzContext 结果整份传下去;
  2. packages/plugins/plugin-sharing/src/share-link-service.ts —— 实现类三个方法的参数类型跟着契约改成 ExecutionContext(以及 ShareLinkServiceOptions.canManageShares 的 context 参数),engine.find 处因此吃到完整信封。

ShareLinkExecutionContext 保留导出,share-link-routes.tscontextFromRequest 类型位仍可用它 —— 但按裁决,它到路由 401 为止。

before-red 证据同时兑现分诊留下的 repro 义务(group 姿态建链 403 实测 → 修后 200);若 repro 不复现,按分诊 caveat 摘 target:v17 并回报。

测试与闸门(实跑输出)

  • pnpm --filter @objectstack/spec typecheck —— 绿(含 check:scripts-typecheckcheck:test-typecheck:OK — test layer compiles; 58 file(s) / 267 error(s) held in test-typecheck-debt.json,债务未增)。
  • pnpm --filter @objectstack/spec test —— Test Files 340 passed (340) / Tests 8702 passed (8702)
  • pnpm --filter @objectstack/spec check:generated —— ✓ All 10 generated artifacts are up to date.(未增删导出,api-surface/contracts.json 不动;contracts 无生成参考文档)。
  • pnpm --filter @objectstack/plugin-sharing typecheck —— 绿(见上文,这是「不会红」的实据)。
  • pnpm lint 全仓绿;family gates 逐个实跑绿:adr-anchors / authz-resolver / role-word / org-identifier / doc-authoring / error-code-casing / route-envelope / query-options-erasure / slot-lookup / spec-parsed-alias / engine-double-contract / wildcard-fallthrough / meta-type-normalized
  • node scripts/check-nul-bytes.mjs —— OK (scanned 6099 tracked text file(s));改动文件另做控制字节自扫,无命中。

ADR-0122 的 pin 计数陷阱(type-alias-convention.pin.test.ts:1491 硬编码 751)不受影响:本次未新增任何 zod schema 或裸别名,check:spec-parsed-alias 只扫 *.zod.ts,已实跑绿。


🤖 Generated with Claude Code

https://claude.ai/code/session_011M7UwH25Unfi73UHim7ajY


Generated by Claude Code

…6430)

`IShareLinkService.createLink` / `revokeLink` / `listLinks` now declare their
context parameter as the complete `ExecutionContext` envelope instead of the
five-field `ShareLinkExecutionContext`. All three adjudicate access, so each
needs the whole `resolveAuthzContext` result — `accessible_org_ids`,
`org_user_ids`, `systemPermissions`, `posture`, `tabPermissions` included.

`ShareLinkExecutionContext` is retained, unchanged in shape, as the route's own
401 vocabulary; its TSDoc now states the boundary and why tsc cannot enforce it
(structural subtyping accepts a narrow object wherever the wide type is
expected).

Implements the maintainer ruling on #6206 (option A, 2026-08-07). Contract half
only — the `@objectstack/plugin-sharing` consumer is the follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011M7UwH25Unfi73UHim7ajY
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 8, 2026 2:52am

Request Review

@github-actions github-actions Bot added the size/m label Aug 8, 2026
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

112 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 @objectstack/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/tenancy-modes.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 @objectstack/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/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 @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @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/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/http-protocol.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/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/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/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/apps.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/field-grouping-and-order.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.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Aug 8, 2026
@qq9340100
qq9340100 marked this pull request as ready for review August 8, 2026 03:11
@qq9340100
qq9340100 added this pull request to the merge queue Aug 8, 2026
Merged via the queue into main with commit d7e0b42 Aug 8, 2026
26 checks passed
@qq9340100
qq9340100 deleted the claude/issue-6430-sharelink-execution-context branch August 8, 2026 03:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants