Skip to content

test(qa): dogfood 真实 boot 把 cacheTtl 的 private 一并钉住,不只钉 max-age (#5396) - #5411

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-5396-dogfood-pin-private
Aug 5, 2026
Merged

test(qa): dogfood 真实 boot 把 cacheTtl 的 private 一并钉住,不只钉 max-age (#5396)#5411
baozhoutao merged 1 commit into
mainfrom
claude/issue-5396-dogfood-pin-private

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes #5396

修了什么

packages/qa/dogfood/test/showcase-declarative-endpoints.dogfood.test.ts 是整条 cacheTtl 链上唯一观测真实 wire 的一层,而它此前只钉半个头:

expect(res.headers.get('cache-control'), 'cacheTtl: 30 must reach the wire').toMatch(/max-age=30/);

漏掉的 private 恰好是这条链上唯一有安全含义的那一位:任何一条 endpoint 响应都可能已按调用者被 RLS 裁剪,共享缓存绝不能存下来再发给别人(computeCacheControl 的文档块成文,packages/runtime/src/endpoint-policy.ts:270)。

改为整行钉住:

).toMatch(/^private, max-age=30$/);

前提复核(Prime Directive「issue 是线索不是规格」)

在从 origin/main(4b61cf3be)新切的 worktree 上核对,issue 正文所述完全成立:

  • 该文件 :202 就是那条只钉 max-age=30 的断言,行号未漂移;
  • 下层三处 private 钉死点也都在(endpoint-policy.test.ts:312/327api-endpoint-step.test.ts:351/524dispatcher-plugin.endpoint-fallback.integration.test.ts:502),所以这确实是「唯一观测真实 wire 的那层比它下面几层松」,而不是一个没人守的洞 —— 观察类的定性也成立。

实测的真实 wire 值(PM 口径:先测再选钉法)

PM 要求先确认真实 boot 的实际输出,若含合法附加指令导致整行钉法脆断则退回 toContain('private')实测不需要退回:整行钉法直接绿,而一条带 ^...$ 锚的正则跑绿,本身就等价于「wire 上的值恰好是 private, max-age=30 这一整串」—— 无附加指令,无重排,policy 层到 socket 之间没有任何一层改写过它。故取 PM 首选的整行钉法。

反向验证(方向事先声明,两条方向都测了)

预测:把 producer 的 private 临时翻成 public 并重建 @objectstack/runtime 后,新断言翻红、旧断言保持绿 —— 后者正是这张单要消灭的那个盲区。实测与预测逐条一致:

producer 断言 结果
public(临时篡改) /max-age=30/ 绿 —— 盲区实锤:运行时真把 private 翻成 public,这条唯一看得见 wire 的断言也不会响
public(临时篡改) /^private, max-age=30$/
private(已还原) /^private, max-age=30$/ 绿

翻红时的实际报文,顺带把 wire 值第二次印了出来:

AssertionError: cacheTtl: 30 must reach the wire, and reach it as `private`:
  expected 'public, max-age=30' to match /^private, max-age=30$/
- Expected: /^private, max-age=30$/
+ Received: "public, max-age=30"

篡改仅存在于本地验证期间,packages/runtime/src/endpoint-policy.tsgit checkout 还原并重建 dist,最终 diff 只有测试文件一个(git status 干净,grep 确认 dist 回到 private, max-age=)。

边界(未越界)

  • 只动这一条断言所在的 it():断言本身 + 一段说明「为什么钉的是 private 这一位」的注释 + 用例名。
  • 动运行时,动 showcase 声明,动同文件 :213(现 :236)那条「错误答案不得带缓存指令」的断言。
  • it() 补了显式 }, 60_000)(车道 TEST DISCIPLINE)。核对过:本文件此前只有 beforeAll120_000,各 it() 均无显式超时,故是补而非重复。本用例实测 26–67ms,超时纯属合并队列满载分片下的保险。同文件其余用例仍吃 vitest 默认超时 —— 属既有状况,不在本单文件面内,未顺手改。

测试

均在容器共享 verify 锁下、NODE_OPTIONS=--max-old-space-size=4096--maxWorkers=2:

vitest run test/showcase-declarative-endpoints.dogfood.test.ts   → Test Files 1 passed / Tests 14 passed
pnpm --filter @objectstack/dogfood test(全量 dogfood)             → Test Files 85 passed | 1 skipped / Tests 506 passed | 3 skipped
pnpm --filter @objectstack/dogfood typecheck                     → tsc --noEmit,无输出(通过)
node scripts/check-nul-bytes.mjs                                 → OK (5423 files)
grep -naP 控制字符自查 改动文件                                     → 无匹配

changeset

纯测试改动,无用户可见行为变化 —— 按仓规走豁免路径,加 skip-changeset 标签(与近日同类 test-only PR #5380 一致)。


Generated by Claude Code

)

showcase-declarative-endpoints.dogfood.test.ts 是整条 cacheTtl 链上唯一
观测真实 wire 的一层,而它此前只钉 /max-age=30/,漏掉了 `private` ——
链上唯一有安全含义的那一位。实测:把 computeCacheControl 临时改成
public 后,旧断言依然全绿。

改为整行钉 /^private, max-age=30$/(实测真实 wire 值就是这一整串,
无附加指令,故整行钉法不脆断)。仅此一条断言;运行时、showcase 声明、
以及 :213 那条「错误答案不得带缓存指令」的断言均未改动。

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

vercel Bot commented Aug 5, 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 5, 2026 9:06am

Request Review

@github-actions github-actions Bot added the size/s label Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

No hand-written docs reference the 0 changed package(s). ✅

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

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants