Skip to content

showcase 端点注释把 cacheTtl 的响应头写成 public, max-age=30 —— 运行时发的是 private,而 private 是安全规则 #5244

Description

@os-zhuang

发现于 #5238(#5040 E9 文档追平)。纯注释修真,零行为变更;与本 issue 的父单 #5231 同一类纪律(注释必须与实际一致),故挂为其子单。

事实

examples/app-showcase/src/system/apis/index.ts:80,TaskFeedEndpoint.cacheTtl 上方的注释:

// Seconds. Emitted as `Cache-Control: public, max-age=30` on a SUCCESSFUL
// answer only — never on a 401/429/5xx, ...

运行时发的不是 public。packages/runtime/src/endpoint-policy.ts 的 computeCacheControl:

if (!Number.isFinite(ttl) || ttl <= 0) return 'no-store';
return `private, max-age=${Math.floor(ttl)}`;

PR #5230 自己的真实 boot 探针 P1 也打印了实测值:

########## P1  GET /api/v1/apps/showcase/tasks  (authed)
HTTP/1.1 200 OK
cache-control: private, max-age=30

注释的后半句(只随成功答案上线、不随 401/429/5xx)是对的,错的只有 public 这一个词。

为什么值得单独记一笔

private 在这条链上不是调优选择而是安全规则,endpoint-policy.ts 的文档块把理由写清楚了:任何一条响应都可能是按调用者 RLS 裁剪过的,所以共享缓存绝不能存下来再发给别人(#5040 §3.3 的 per-principal cache key 在没有服务端缓存时就落在这个 header 上)。

而这条注释所在的位置是 showcase —— 声明式端点唯一的一手示例,是 AI 作者最可能整段抄走的那份文件。抄走 public 的作者会顺理成章地推断「共享缓存可以存这条响应」,而这正好是该规则要挡住的推断。

修法

把 public 改成 private,并把「private 是安全规则不是调优」这半句带上(与 endpoint-policy.ts 的措辞对齐,不复述第二套规则)。顺带可核一下 cacheTtl: 0 的语义(no-store)是否也需要在示例里点一句。

边界

不动运行时,不动声明本身(cacheTtl: 30 是对的),不动 content/docs/releases/。

Activity

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions