6.2 KiB
任务书 · 普通用户报告公开内容分层与导出投影(2026-09-22)
0. 基线与先决条件
- 基线 commit:
1bc6a954c597e2817fe72bfedad93119ab19a527;开工前 fetch 并以最新origin/staging重核。 - 执行分支:
codex/report-public-content-20260922;工作树:.worktrees/report-public-content-20260922。 - 业务已拍板:普通用户导出的报告隐藏内部技法和工作流字段;只保留用户可读正文、结论和必要限制说明。专业参考若保留,另立明确入口和规则。
- 本单与人物 other 资料无关;不得把报告接入人物切换任务。
- 本单不与人物选择器共享实现文件;如同批执行,先完成服务端 subject binding,再由报告单独接入其 canonical projection,禁止把两种资料真值边界混在同一 helper 中。
1. 事故实证
会议反馈:网站生成的报告夹带不该展示的内容,具体字段会上未列清。代码调查确认存在公开合同分裂:
- 普通聊天消息已经按 BUG-011 移除内部证据徽章、Technique Audit、单条回答下载控件。
frontend/src/lib/consultation-report-export.ts的consultationReportMarkdown()仍可能序列化technique_truth、workflow_route、workflow_status、precise_timing、missing_layers、Claim boundary 等内部字段;现有导出测试仍将其作为预期结果。frontend/src/lib/personal-report-longform-download.ts优先使用已有 Markdown,下载前主要去除图盘 fence,没有统一公开内容投影。frontend/src/app/api/reports/[reportId]/professional-reference/route.ts会返回已存储的完整 Markdown;接口名是 professional reference,但用户入口可能只是笼统“导出报告”。frontend/src/components/personal-report/personal-report-markdown-view.tsx的 HTML/URL/XSS 过滤是结构安全措施,不等于内部字段分类。
相关历史:BUG-011、BUG-058、BUG-086~094、BUG-188。它们已明确内部路由、未执行技法、评分、原始响应和用户敏感内容不得进入普通用户可见层。
2. 根因
报告阅读、咨询导出、个人报告下载和 professional-reference 返回的是不同边界:聊天层隐藏了内部字段,但 canonical Markdown/导出/API 没有统一普通用户 allowlist。因此不能只在 React 下载按钮前用正则删除,也不能凭感觉删除会上未定义的内容。
3. 决策记录(产品已拍板)
- 普通用户报告只展示:用户可读正文、结论、行动建议(若业务允许)和必要的限制说明。
- 普通报告禁止:
technique_truth、workflow_route、workflow_status、precise_timing、missing_layers、内部评分/权重/执行账本、内部 URL、secret、模型调试字段、raw tool response、job/attempt/provider 元数据。 - 若专业参考仍需展示部分方法证据,必须单独命名、单独入口、单独权限/标识和单独合同;本单不把它混入普通导出。
- 旧报告不能因缓存或已存 Markdown 绕过新公开规则;优先在服务端 canonical 投影边界统一处理。
4. 硬红线
- 不得把普通报告变成内部调试报告;不得把“更专业”当作公开内部执行轨迹的理由。
- 不得只在客户端用脆弱字符串正则作唯一隐私防线。
- 不得破坏 Markdown 的既有 XSS、危险 URL、HTML 和
jyotish-chartfence 安全合同。 - 不新增 PDF/Canvas/jsPDF/Playwright/Puppeteer 导出链路,不升级依赖。
- 不修改星盘计算、报告生成算法或人物绑定;只治理公开投影边界。
- 不在 fixture、日志、任务书、BUG 历史中写真实姓名、出生资料、会话原文、凭据、secret。
5. 任务分解与验收标准
T1 · 建立字段级公开投影
- 在服务端/共享 canonical 层新增明确的普通报告投影 helper;字段白名单优先于黑名单。
- 区分聊天导出、个人报告详情、普通 Markdown 下载和专业参考文档类型,不用接口名字猜用户可见级别。
- 内部限制字段若需要保留其产品含义,转成自然语言限制说明,不透出内部 key/value。
验收:每个字段有公开/内部归类;普通报告在同一 synthetic fixture 下只含允许内容;没有字段时不虚构;图盘 fence 规则继续有效。
T2 · 接入所有普通输出边界
consultation-report-export.ts、personal-report-longform-download.ts、报告详情/阅读路径和 API 返回统一使用投影。/professional-reference若继续存在,必须显式区分专业参考与普通报告;若本轮不改专业参考,至少阻止它被普通下载路径当作普通报告 fallback。- 处理旧缓存 Markdown/已存文档:下载和 API 返回不能绕过投影。
验收:页面阅读、下载文件、直接 API 响应与普通公开合同一致;禁止字段不会因缓存命中、旧报告或备用路径复现;专业参考不会被误标为普通报告。
T3 · 回归与安全测试
覆盖:字段存在/缺失、旧缓存、专业参考路径、图盘 fence、Markdown HTML/script/iframe/object/embed/img、危险 URL、内部 URL/secret/模型字段扫描。保留现有 consultation-report-export、personal-report-longform-md、报告归属/ready 检查测试名;断言变化写原值/新值/原因。
6. 让步顺序
T1 字段合同 > T2 canonical 接入 > T3 回归测试。若专业参考产品边界尚未实现,普通下载必须 fail-safe 使用普通投影,不能以“接口叫 professional-reference”为由透出内部字段。
7. 开工前置命令
git status -sb
git fetch origin --prune
git worktree add -b codex/report-public-content-20260922 .worktrees/report-public-content-20260922 origin/staging
cd .worktrees/report-public-content-20260922/frontend
./node_modules/.bin/tsc --noEmit
npm run lint
npm test
npm run build
8. 交付记录
同轮写 docs/tasks/PROGRESS-report-public-content-20260922.md,更新 docs/BUG_HISTORY.md(关联 BUG-011/058/188;若确认新用户可见回归,按开工时最大号连续编号)和必要的 CHANGELOG.md。视觉/文案变化同步 frontend/DESIGN.md / frontend/docs/VOICE.md。没有登录态的浏览器级导出验收写入 docs/testing/,不得写成通过。