Skip to content

fix(spec,rest,runtime): request bodies are checked against the schemas the catalog declares (#3899) - #4322

Merged
os-zhuang merged 10 commits into
mainfrom
claude/request-body-schema-validation-o9ltjz
Jul 31, 2026
Merged

fix(spec,rest,runtime): request bodies are checked against the schemas the catalog declares (#3899)#4322
os-zhuang merged 10 commits into
mainfrom
claude/request-body-schema-validation-o9ltjz

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Closes #3899(建议 ①②④;建议 ③ 的 filter-normalizer 已由 #4128 一轮修完,$or/$not 现为树节点、未知操作符直接 throw,本 PR 无需改动)。

范围核对(issue 核对于 93f267f,此后已落地的部分)

Issue 表中 7 个 schema,有 4 个已被单独 issue 接线:DeleteManyDataRequestSchema(#3897)、UpdateManyDataRequestSchema(#3933)、批量上限与单一 Zod 源(#3939/#3944)、SharingRuleSchema(#3896);AnalyticsQueryRequestSchema 也已在 #3878/#3891 之后接上(domains/analytics.tsassertAnalyticsQueryBody,信封形状已退役、schema 现为 .strict() + retiredKey 墓碑)。本 PR 收掉剩余的一半,并补上把"声明=生效"钉死的门。

① 目录停止承诺没做的事(plugin-rest-api.zod.ts)

② 声明的 schema 接到真实入口

rest-server(沿用 #3933/#3944 的"路径参数最后合并 + zodIssuesToFields"范式,400 信封与 updateMany/deleteMany 完全一致):

路由 之前 现在
POST /data/:object/query query: req.body || {} 原样透传,畸形 body 静默变全量读 FindDataRequestSchema 校验;路径 object 最后写入并随查询下传(body object 不能再与路径矛盾);校验后转发合并后的原始 body,不注入 parse 产物
POST /data/:object data: req.body 裸传 CreateDataRequestSchema(非 record body → 400)
PATCH /data/:object/:id 裸传 UpdateDataRequestSchema
POST /data/:object/batch 注释自述"未校验" BatchUpdateRequestSchema;上限检查移到形状检查之后(#3944 同序)
POST /data/:object/createMany records: req.body || [] CreateManyDataRequestSchema(裸数组 wire 不变;发 {records:[...]} 信封会拿到带指引的 400)

runtime dispatcher(analytics 入口的 throw-duck-shape 范式,两个错误出口都映射为 400,#3918 已钉):

  • POST /notifications/read:接 MarkNotificationsReadRequestSchema。旧读法 Array.isArray(body?.ids) ? … : []{"notificationIds":[...]}/{"ids":"n1"} 静默变成 markRead(userId, [])——200、readCount: 0、角标永不清零(issue ③ 原例)。
  • POST /automation(registerFlow):name 必须为非空字符串——拼错 name 曾把流程注册到 undefined 键下并回显 200。
  • POST /automation/:name/toggle:严格 { enabled?: boolean }——{"enable": false}(少个 d)曾启用流程并返回 200 {enabled: true};现在 400 并点名错键。空 body = enable 的既有语义保留。
  • PUT /automation/:name:定义必须是对象(definition 信封是既有双方言,原样保留、未新增)。
  • validationFailure/fieldsFromZodIssues 从 analytics 内联提升到 validation-failure.ts(与识别器同文件,构造与识别不可能漂移),analytics/notifications/automation 三处共用。

④ 门

门当场抓到的两处真实漂移(本 PR 顺带修掉)

这两处都不是我改出来的,是新门第一次运行就照出来的既有"声明 ≠ 实际",与本 issue 是同一种病:

  1. QuerySchema 的 search 契约与 ADR-0061 服务的形状不符。schema 只声明了结构化的 FullTextSearchSchema,而 ADR-0061 D1 的规范拼写是裸字符串(客户端只说搜什么,服务端决定搜哪些字段),顶层 searchFields 窄化更是完全没声明——可执行器、conformance ledger、dogfood HTTP 证明用的都是后者。入口一开始校验 body,dogfood 的 showcase-search 立刻红。按 contract-first 修在 spec 侧(search: string | FullTextSearch、正式声明 searchFields),并在 rest 门里钉了该 wire 形状的阳性用例。连带:QUERY_AST_KEYS(Record<keyof QueryAST, true>,存在意义就是"spec 加键、REST 边界没跟上就编译不过")如设计般把构建拦红,补键后顺手清掉 RESERVED_LIST_QUERY_PARAMS 里那份手写的 'searchFields' 副本。
  2. 两份手写查询文档只教了对象形,query-syntax.mdx 的类型签名 search?: FullTextSearch 已是字面错误,searchFields 一字未提。同一种病上移一层,一并校正。

一处 CI 稳定性修复(354caba,与请求体校验无关,但本 PR 被它挡住)

Test Core 在本分支连续两次停摆在完全相同的位置,被杀任务都是 @objectstack/driver-mongodb#test。取证后根因明确:该包三个套件在模块加载期从 fastdl.mongodb.org 抓 ~123MB 的 mongod 二进制,代码只防了"下载失败"(try/catch → skip,文件头注释写明意图正是"别让它拖垮整个 Test Core"),没防"下载卡住"——挂起时 promise 永不 settle,套件既不跑也不跳,就地停住。instance.launchTimeout 不覆盖这一段(它约束的是二进制就位后 spawn mongod)。

不是本 PR 的 diff 引起:同一任务在 main(40 分钟前)是 cache miss 真跑的,日志有完整的 Downloading MongoDB "8.2.6": 0% → 100% 并通过;是网络侧在变而等待没有上界。但任何改动 @objectstack/spec 的 PR 都会让全仓缓存失效、让这个任务真跑,于是必然撞上,重跑绕不过去。

修法是给等待加 120s 截止时间,让"卡住"落进套件本来就有的 skip 分支——降级结果与可见性不变(warn + 跳过),只是从"永不发生"变成"有界发生"。取证与讨论记在 #4250(该 issue 已记录的三次机制不同,是另一条线索,未受影响)。

行为变更

违反已声明契约的 body 从"静默换一种语义执行"变为 400 VALIDATION_FAILED + fields[]。合规调用方(SDK 全部方法已逐一核对发送形状)不受影响;曾依赖畸形 body 被静默接受的调用按 fields[] 指引改正即可。细节见 changeset。

验证

  • 新增门测试先行验证会红:catalog 旧状态下 spec 门直接失败(端点数、幽灵路由),rest/runtime 门在未接线的路由上拿到 2xx 而非 400。
  • 全量回归:spec 7145 / rest 536 / runtime 977 / objectql 1373 / metadata-protocol 122 / driver-mongodb 160 全绿;全量构建 71/71;check:generated 8/8;check:liveness 绿(新声明的 query/searchFields 与转为 union 叶子的 query/search 均已登记台账)。
  • 改动文件 ESLint 干净。
  • 既有调用方核对:client.data.query/create/update/batch/createManyclient.notifications.markReadclient.automation.toggle/execute 发送形状全部合规;既有集成用例发送的都是合规 body,全数通过。

🤖 Generated with Claude Code

https://claude.ai/code/session_01EynH7cngDczRGMkGMudJpC

…s the catalog declares (#3899)

The API catalog (plugin-rest-api.zod.ts) declared requestSchema on 16
routes while almost no mounted entry point validated its body — a
malformed request did not 400, it executed different semantics (an
unfiltered full read on /query, markRead(userId, []) on a misnamed key,
a flow registered under the key `undefined`, a one-letter-off toggle
body ENABLING the flow it meant to disable).

Wire the declared schemas at the real entry points, make the catalog
stop promising what nothing performs, and gate both directions:

- rest: POST /data/:object/query, POST /data/:object,
  PATCH /data/:object/:id, POST /data/:object/batch and
  POST /data/:object/createMany now safeParse the declared contract and
  answer 400 VALIDATION_FAILED + fields[] (the #3933/#3944 pattern);
  the query route also pins the PATH object into the forwarded query.
- runtime: POST /notifications/read validates
  MarkNotificationsReadRequestSchema; the automation registerFlow /
  updateFlow / toggle bodies get strict hand-written guards (keys.ts
  pattern); the analytics-entry validationFailure helper is hoisted to
  validation-failure.ts and shared.
- spec: the catalog drops the four ghost notification endpoints
  (#3612 removed the routes), fixes the automation trigger path to
  /trigger/:name and drops its never-true request schema, adds the
  POST /:object/query entry, repoints create/update at the schemas the
  routes actually validate, and drops requestSchema from bodyless
  GET/DELETE entries.
- gates: schema-name references must resolve to real exports and sit on
  body-carrying methods (spec); every declared requestSchema on a
  mounted route has a violating-body -> 400 conformance case with a
  completeness ratchet (rest + runtime request-schema-gate suites).

Suites: spec 7132, rest 536, runtime 977 all green; check:generated 8/8.

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

vercel Bot commented Jul 31, 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 Jul 31, 2026 7:49am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Jul 31, 2026
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 5 package(s): @objectstack/metadata-protocol, @objectstack/driver-mongodb, @objectstack/rest, @objectstack/runtime, @objectstack/spec.

116 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/connect-mcp.mdx (via @objectstack/rest)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via packages/runtime, @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/rest, @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/rest, @objectstack/runtime, @objectstack/spec)
  • content/docs/api/wire-format.mdx (via @objectstack/runtime)
  • 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 @objectstack/runtime, 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 @objectstack/metadata-protocol, @objectstack/runtime, packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/runtime, packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/driver-mongodb, @objectstack/runtime, @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/index.mdx (via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/deployment/vercel.mdx (via @objectstack/runtime)
  • 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/glossary.mdx (via @objectstack/driver-mongodb)
  • 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/runtime, @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/runtime, @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/metadata-protocol, @objectstack/driver-mongodb, @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authentication.mdx (via @objectstack/rest, @objectstack/runtime)
  • content/docs/permissions/authorization.mdx (via packages/runtime, @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/rest, @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/driver-mongodb, @objectstack/rest, @objectstack/runtime, @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/runtime)
  • content/docs/protocol/kernel/i18n-standard.mdx (via packages/rest, @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/runtime, @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/driver-mongodb, @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/driver-mongodb, @objectstack/rest, @objectstack/runtime, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/rest, @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/metadata-protocol, @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.

claude added 2 commits July 31, 2026 05:58
… serves

The first CI run of the #3899 request-schema gate rejected the dogfood
search proof's own wire shape: `{ search: 'retail', searchFields:
['industry'] }` answered 400. The schema was the wrong half — QuerySchema
declared only the structured FullTextSearchSchema form while ADR-0061 D1
("the client sends only the query text"), the engine executor
(search-filter.ts), and the search-conformance ledger all serve the bare
string plus the validated `searchFields` narrowing.

- `search` becomes `string | FullTextSearch` (string is the canonical
  Tier-1 spelling; the object form keeps the declared Tier-2 knobs)
- `searchFields` is formally declared (the ADR's own P1 item), noted as
  server-intersected — can only narrow, never widen
- rest request-schema gate pins the ADR-0061 wire shape as a positive
  case so entry validation can never 400 it again
- regenerated: references docs + authorable-surface (adds
  `data/Query:searchFields`); all 8 artifact gates green

spec suite 7145 green; both previously-failing dogfood files pass
locally (showcase-search 4/4, two-factor-lockout 5/5 — the 2FA pair does
not reproduce here and is green on main @ 5d21a48's identical job).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EynH7cngDczRGMkGMudJpC
claude added 5 commits July 31, 2026 06:17
…hFields in the liveness ledger

The search-contract repair turned `search` into a union the liveness
walker does not descend, and declared `searchFields` — both landed
UNCLASSIFIED on the freshly-seeded query ledger (#4286). `search`
becomes a leaf entry (the object form's experimental flags stay audited
by their own describe markers inside FullTextSearchSchema);
`searchFields` gets its live entry pointing at the resolveSearchFields
intersection and the ADR-0061 dogfood proof.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EynH7cngDczRGMkGMudJpC
…e demands

`QUERY_AST_KEYS` is typed `Record<keyof QueryAST, true>` precisely so a key
added to the spec is a compile error here rather than silent drift at the
REST boundary — and it did its job: declaring `searchFields` on QuerySchema
turned the whole build red until the key was listed.

The hand-maintained `'searchFields'` entry in RESERVED_LIST_QUERY_PARAMS goes
with it. It was there as a "transport-only extra the AST does not name"; the
AST names it now, so it arrives through the `QUERY_AST_KEYS` spread and the
type-level pin covers it. Keeping both would have been the second source that
list exists to avoid.

No behavior change on either path: the GET normalizer already accepted
`?searchFields` / `$searchFields` and the engine already read `ast.searchFields`
(ADR-0061). metadata-protocol 122, objectql 1373, full build 71/71 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EynH7cngDczRGMkGMudJpC
…hand-written docs

Both hand-written query pages taught only the structured `search: {query,
fields}` form — `query-syntax.mdx` even typed it `search?: FullTextSearch`,
which is now literally wrong. The bare string is the canonical ADR-0061
spelling (D1: the client says what to search for, the server decides which
fields), it is what every surface sends, and it is what the dogfood proof
asserts; the top-level `searchFields` narrowing was undocumented entirely.

Same gap this PR exists to close, one layer up: a reader following these
pages learned half the contract. Both forms are now shown, with the
structured one named as equivalent for the two members that drive the
expansion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EynH7cngDczRGMkGMudJpC
…instead of stopping Test Core

These three suites start a real mongod via mongodb-memory-server, which
fetches a ~123 MB binary from fastdl.mongodb.org at module load. Each already
anticipated that fetch FAILING — try/catch, warn, skip — precisely so a
blocked download costs a skipped suite rather than the monorepo test job.

A catch cannot express the other half. When the fetch HANGS, the top-level
await never settles: the suite neither runs nor skips, it stops. Observed
twice on this branch (Test Core attempts 1 and 2 of run 30610017310), both
frozen at the identical point with zero output from this package and no skip
warning, both force-killed 10 minutes later by the #4250 stall guard with
`@objectstack/driver-mongodb#test` as the surviving task. `instance
.launchTimeout` does not cover it — that bounds spawning mongod once the
binary is on disk, a later phase than the fetch.

`createTestMongod` puts a 120s deadline on the wait so a hang lands in the
skip branch the suites already had. Not a workaround for this PR's diff: the
same task on main 40 minutes earlier logged `Downloading MongoDB "8.2.6": 0%
… 100%` and passed on a cache miss, so this is the network changing under an
unbounded wait. Any PR touching @objectstack/spec invalidates the cache and
runs straight into it.

Verified: 160/160 still pass locally on the success path (binary cached), and
a mocked never-settling create() resolves to undefined at the deadline rather
than hanging. The helper stays out of dist — tsup entry is src/index.ts only,
which does not reference it (mongodb-memory-server is a devDependency).

Refs #4250.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EynH7cngDczRGMkGMudJpC
claude added 2 commits July 31, 2026 07:35
…checked source

`src/test-mongod.ts` uses setTimeout / clearTimeout / console and turned the
package's `tsc --noEmit` red. The `.test.ts` files that call it have always
used the same globals, but tsconfig excludes `**/*.test.ts`, so this package
never needed `types: ["node"]` until a shared helper became typechecked
source — and it cannot be named `*.test.ts`, or vitest would collect it as a
suite with no tests.

Same one-line declaration a dozen sibling packages already carry (client,
core, lint, cli, metadata-protocol, …); @types/node is already a devDep here.

I missed this locally by verifying with build + eslint + vitest: tsup's dts
step only covers the `src/index.ts` entry graph, which this helper is
deliberately outside of, so nothing I ran typechecked it. Re-verified with the
command CI actually uses — `turbo run build --filter='./packages/*'`, 57/57 —
plus `tsc --noEmit` in this package and its 160 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EynH7cngDczRGMkGMudJpC
…chema-validation-o9ltjz

# Conflicts:
#	content/docs/protocol/objectql/query-syntax.mdx
@os-zhuang
os-zhuang marked this pull request as ready for review July 31, 2026 08:02
@os-zhuang
os-zhuang merged commit a1b61e0 into main Jul 31, 2026
26 of 27 checks passed
@os-zhuang
os-zhuang deleted the claude/request-body-schema-validation-o9ltjz branch July 31, 2026 08:07
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 protocol:data size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

请求体从不与声明它的 schema 对照(#3877 的请求侧对偶):7 个 schema 定义了从未启用,而 API 目录已宣称生效

2 participants