Skip to content

docs(spec): ApiEndpointSchema.path.describe() 换成 ADR-0121 carve-out 形状的示例 (#5310) - #6064

Merged
qq9340100 merged 3 commits into
mainfrom
claude/issue-5310-endpoint-path-describe-carveout
Aug 7, 2026
Merged

docs(spec): ApiEndpointSchema.path.describe() 换成 ADR-0121 carve-out 形状的示例 (#5310)#6064
qq9340100 merged 3 commits into
mainfrom
claude/issue-5310-endpoint-path-describe-carveout

Conversation

@qq9340100

Copy link
Copy Markdown
Collaborator

Fixes #5310

正文里的路径占位符统一写成方括号([manifest.namespace]),避开 GitHub 正文清洗把 < 加字母当成 HTML 标签吞掉。源码 .describe() 里用的是尖括号。

前提复核(先证再改)

origin/main(efedd28)上逐条核对,问题描述的两个事实都成立:

  • packages/spec/src/api/endpoint.zod.ts:59 仍然一字未改:
    path: z.string().regex(/^\//).describe('URL Path (e.g. /api/v1/customers)')
  • packages/spec/src/api/endpoint-publish-gate.ts:87appEndpointMountPrefix(namespace) 返回
    `${DEFAULT_RUNTIME_PREFIX}/${APP_ENDPOINT_SEGMENT}/${namespace}/`,即 /api/v1/apps/[namespace]/

/api/v1/customers 不以该挂载前缀开头,namespaceGate 走的是拒绝分支 —— 词表自己举的例子,publish 会当场拒

为什么现在才要紧

#5271 之前 api 没有注册 schema,/meta/types 不为它出 JSON Schema,Studio 只能给一个 raw-JSON 文本框,这段 .describe() 没有渲染面。#5271 之后它成为 metadata-admin 端点表单里 path 字段的说明文字,并进入生成的 JSON Schema —— 于是一段会被拒绝的示例,变成了作者(按 ADR-0033,常常是 AI 作者)照抄的第一手提示。

改了什么

ApiEndpointSchema.path.describe() 换成 carve-out 形状:

  • 给出形状 /api/v1/apps/[manifest.namespace]/[subpath],并点明子路径必须非空(ADR-0121 D1);
  • 给出一个具体示例 /api/v1/apps/crm/leads,并说明它对应 manifest.namespacecrm 的栈;
  • 说明命名空间段派生自 manifest.namespace(ADR-0121 D2),不是作者的自由字段;
  • 说明 carve-out 之外的路径会在 publish 被拒、且运行期匹配不到任何东西。

措辞直接复用 endpoint-publish-gate.tsnamespaceGate 的拒绝文案(must be ... with a non-empty subpathOnly the subpath is yours to namewould parse today and match NOTHING at runtime),没有新发明判据 —— 作者在表单里读到的规则,和被拒时读到的规则,是同一条。

只动文案。 schema 结构、/^\// 正则、门逻辑一律未动,endpoint-publish-gate.ts 一个字节没改。path 仍然只是一个以斜杠开头的字符串,carve-out 仍然只由 publish 门(和运行期匹配器)判定,所以这不是破坏性变更:今天能发布的声明明天照样能发布。

ApiMappingSchema.describe() — 逐条复核结果

问题里点名要一并复核,复核完的处置是三条都保持原样,理由逐条不同:

字段 现文案 判定
source Source field/path 不举例,也没说错 —— 门对路径形状的额外要求(空段、原型键)是门的判据,不是文案的失实。不改
target Target field/path 同上。不改
transform Transformation function name 这个键确实会被 mappingGate 整键拒绝。但它不是「举例失实」,而是「冻结词表里的被拒键,该不该在表单里自陈」——另一类问题,且这段文案被 packages/runtime/src/api-mapping.ts 的词表小节逐字引用为规范来源(改它要连带动 packages/runtime)。按 Prime Directive #10 另行归档,不在本 PR 修

inputMapping / outputMapping 的两条(Map Request Body to Internal Params / Map Internal Result to Response Body)与运行期实现一致,也不改。

测试

新增的断言不复述文案,而是把 .describe() 的文本从 schema 里读回来再喂给门 —— 这样断言不可能和作者真正看到的字符串漂移:

const description = ApiEndpointSchema.shape.path.description ?? '';
const concreteExamples = (description.match(/\/[A-Za-z0-9_<>./-]+/g) ?? [])
  .filter((candidate) => !candidate.includes('<'));   // 占位符不是示例

三条:

  1. 文案里必须至少有一个具体示例路径(反空转);
  2. 每个具体示例都必须是 /api/v1/apps/[namespace]/[subpath] 形状,并在它自己命名的那个命名空间下通过 validateApiEndpointDeclarations(carve-out 由 D2 派生,示例只有配上能声明它的 manifest 才算诚实);
  3. 旧示例 /api/v1/customers 仍然被拒 —— 把缺陷本身钉住。

反向验证(方向在跑之前就先定好:)

预测:把旧文案换回去,新断言应当因为「示例不是 carve-out 形状」而失败。实测正是这个方向、这个原因:

59:  path: z.string().regex(/^\//).describe('URL Path (e.g. /api/v1/customers)'),
     × every concrete example it shows PASSES the gate that judges authored paths
AssertionError: example '/api/v1/customers' is not `/api/v1/apps/[namespace]/[subpath]`
               — the shape ADR-0121 D1 requires: expected null not to be null
 Test Files  1 failed (1)
      Tests  1 failed | 45 passed (46)

恢复改动后:

 ✓ [#5310] the `path` vocabulary text is itself publishable > shows the author at least one CONCRETE example path
 ✓ [#5310] the `path` vocabulary text is itself publishable > every concrete example it shows PASSES the gate that judges authored paths
 ✓ [#5310] the `path` vocabulary text is itself publishable > the example it USED to show is still rejected — the defect itself, pinned
 Test Files  1 passed (1)   Tests  46 passed (46)

既有的 5 条拒绝例(carve-out 外、别人的命名空间、空子路径、showcasex 近似前缀、无 manifest.namespace)全部保留且仍然拒。

全量

pnpm --filter @objectstack/spec test        → Test Files 325 passed (325) | Tests 8312 passed (8312)
pnpm --filter @objectstack/spec typecheck   → TYPECHECK_EXIT=0(tsc --noEmit + check:test-typecheck OK)

生成物

按 os-regen 纪律,不手改、不整包扫射:check:generated 先判定失效面,只有 content/docs/references/** 一项失效,--fix 只重生成这一项,随后补跑 gen:openapi(#5371,该生成器无门)。复跑后 ✓ All 10 generated artifacts are up to date.

问题描述里预计会动 authorable-surface.json / json-schema.manifest.json,实测没有动:前者不收录 .describe() 文本,后者只是 schema 名字的棘轮清单。实际落点只有 content/docs/references/api/endpoint.mdx 一行表格。

变更集

.changeset/endpoint-path-describe-carveout.md,@objectstack/spec: patch —— .describe() 是发布面文案(进 JSON Schema、进参考文档、进 Studio 表单),不是代码注释。


Generated by Claude Code

claude added 2 commits August 6, 2026 16:12
…e-out 形状的示例 (#5310)

这段文案原本是 `URL Path (e.g. /api/v1/customers)`。ADR-0121 D1 把声明路径收紧为
`<运行前缀>/apps/<命名空间>/<子路径>`,publish 门 `namespaceGate` 对 carve-out 之外的
路径直接拒绝 —— 词表自己举的例子,publish 会当场拒。

#5271 让 `api` 成为注册元数据类型之后,这段 `.describe()` 成为 metadata-admin 端点表单
里 `path` 字段的说明文字,并进入生成的 JSON Schema,是作者(常为 AI 作者,ADR-0033)
照抄的第一手提示。

新文案给出 carve-out 形状、一个具体示例 `/api/v1/apps/crm/leads`,并说明命名空间段派生
自 `manifest.namespace`(ADR-0121 D2)。措辞复用 `endpoint-publish-gate.ts` 中
`namespaceGate` 的拒绝文案,未新发明判据。

只改文案:schema 结构、`/^\//` 正则、门逻辑一律未动。

新增断言把 `.describe()` 的文本读回来再喂给门:文案里的每个具体示例路径都必须在它自己
命名的命名空间下通过 `validateApiEndpointDeclarations`。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011M7UwH25Unfi73UHim7ajY
`.describe()` 文案变化会落到生成的参考文档表格里。按 os-regen 纪律用
`check:generated` 判定失效面(仅 `content/docs/references/**` 一项),再用
`--fix` 只重生成被证实失效的那一项,随后补跑 `gen:openapi`(#5371,无门)。
未手改任何生成物。

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

vercel Bot commented Aug 6, 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 6, 2026 11:50pm

Request Review

@github-actions

github-actions Bot commented Aug 6, 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.

@qq9340100
qq9340100 marked this pull request as ready for review August 7, 2026 00:17
@qq9340100
qq9340100 added this pull request to the merge queue Aug 7, 2026
Merged via the queue into main with commit 1eb13a0 Aug 7, 2026
25 checks passed
@qq9340100
qq9340100 deleted the claude/issue-5310-endpoint-path-describe-carveout branch August 7, 2026 00:41
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