Files
Neo-ZQYY/docs/_overview/wave1-findings/01-W1-findings-response.md
Neo 8952ca2969 docs(audit): Wave 1 findings 反馈响应 + F2-1 OpenAPI 同步历史调研
01-W1-findings-response.md 主线整合 12 项 Neo 反馈:
- 直接同意 7 项 (F1-1/1-5 + F2-1 + F3-1/3/5 等)
- 修正 2 项: F1-2 降级 P1 UX (admin-web 无 site_admin 登录),
  F1-4 撤销 (前提错误)
- 评估 1 项: F1-3 改良为 Hot DB + Cold Parquet 按月分区
- 简化 1 项: F2-2 基于 Neo 前提 5 分钟方案 (删 .gitignore + 入仓)
- 联网搜 1 项: F3-2 DashScope Qwen3-Max-Preview $1.20/$6.00 per 1M
  + Qwen3 切词 1000 字符 ≈ 500 tokens + SCD2 配置表方案
- 答疑 1 项: F3-4 沙箱越界 422 拒绝

F2-1-openapi-history.md (234 行) 真相:
- 抓取脚本 scripts/ops/_export_openapi.py 12 行曾存在
- 2026-04-06 00:39 commit 779b2f6 批量清理 1155 个废弃文件时
  被 Claude Opus 4.6 误归档到 _DEL/_DEL/scripts/ops/
- 36 分钟前同一天还跑过最后一次抓取
- 28 天内无人发现, 9/10 缺失端点是工具消失后新加 router
- 脚本本身无 bug, 推荐恢复 + 加 hook 防御
2026-05-05 00:03:57 +08:00

14 KiB
Raw Blame History

Wave 1 发现 — Neo 反馈响应(主线整合)

日期:2026-05-04 / 触发:Neo 在 00-W1-findings-stories.md 12 项业务故事卡上写斜体反馈 用途:对每条反馈给出主线处理路径 + 修正前期判断错误 + 答疑 + 评估新方案


一、12 项处理总览(更新版)

# Neo 反馈类型 处理 Wave
F1-1 同意 Wave 2 选 A 直接排程 Wave 2
F1-2 🟡 质疑前提"问题在哪" 降级为 P1 UX(非安全),修正描述 Wave 4
F1-3 🟡 提出新方案 JSON+MD 评估并推荐改良版 Wave 4
F1-4 🟡 质疑前提"site_admin 不能登 admin-web" 撤销 — 不是问题
F1-5 同意 Wave 1 选 A 直接排程 Wave 1
F2-1 🟡 要历史原因调研 真相:抓取脚本被 Claude Opus 4.6 大批量清理时误归档(2026-04-06)→ A 恢复脚本 + B 加 hook Wave 2 前(立即)
F2-2 🟡 给出前提要更优方案 简化方案(不脱敏 + 不启 CI) Wave 5
F3-1 选 B(显式 ?scope=) 直接排程 Wave 2
F3-2 🟡 让我联网搜 DashScope 实证 + 推荐方案 Wave 2
F3-3 选 A(audit + 二次确认) 直接排程 Wave 2
F3-4 选 A + 新提问 答疑"沙箱 4-1 申请 4-5 数据" Wave 5 文档
F3-5 选 A,先彻底修完再后续 直接排程 Wave 4

二、修正项详细分析

F1-2 修正:不是"跨租户 PII 泄露",是"切 site UX 不一致"

Neo 的质疑(完全正确):

admin-web 是系统管理后台,看到租户的一些信息,问题在哪里?我同意加店铺过滤,也可以查看所有店铺。

主线核实代码(权限模型实证):

admin-web 登录: auth.admin_users (super_admin / admin),JWT aud="admin"
tenant-admin 登录: auth.tenant_admins (tenant_admin / site_admin),JWT aud="tenant-admin"

两套用户表 + 两套 aud 完全分离,admin-web 没有 site_admin 登录场景。所以原 F1-2 描述里的"site_admin 越权看到 PII"前提错误 — site_admin 根本进不来 admin-web。

修正后真正的问题:

  • admin-web super_admin 切 site 时,run-logs 列表应该按所选 site 过滤(否则切 site 没意义)
  • 但 super_admin 依然有权看所有 site(只是默认按当前选择的 site 显示,可显式切"全部")
  • 这是 UX 一致性问题,不是安全/PII 问题

修正后的方案:

  1. A 切 site 即过滤,提供"全部 site"切换选项(推荐):默认按当前 site 过滤,super_admin 可显式切"全部" → UX 一致
  2. B 维持现状(全表,前端筛选):零改 → super_admin 习惯
  3. C 维持现状 + 列表加 "site_id" 列:可读性提升,无过滤 → 简单

修正后判定:[P1 UX] Wave 4(数据正确性 Wave,顺手),选 A — 与切 site 行为一致。法律风险表述删除(super_admin 有合法授权)。


F1-4 撤销:admin-web 没有 site_admin 登录场景,问题不存在

Neo 的质疑(完全正确):

admin-web 是系统级管理后台,site_admin 本就没有权限登录啊,何来此问题?

主线核实:确认 admin-web 路由全部 Depends(get_current_user) 来自 admin_users 表,site_admin 通过 tenant-admin 登录,JWT aud="tenant-admin",根本无法通过 admin-web 登录(aud 不匹配会被拒绝)。

结论:F1-4 撤销(P1-7 PRD 撰写时假设了多角色 admin-web 场景,与实际不符)。

关联调整:批 1 PRD 里 F1-4 评估发现需要回滚标注。让我在批 1 PRD 加注脚,声明这条评估错误已撤销。

结论:[B 现状对] 撤销,无需 Wave 排期


三、评估 Neo 新方案

F1-3 评估:JSON 索引 + MD 文件 / 或 JSON 也放硬盘

Neo 提出:

基于 B 选项再做优化,数据库只记录索引(每月一行的 JSON 数据索引),通过 JSON 解读出要找的 MD 文件,真正内容记录在 MD 文件中,以文件形式记录在指定硬盘目录中。或者更激进 — JSON 也放硬盘?

主线评估:

优势

  • 数据库压力大幅降低:90 天 hot 数据保留 DB,90+ 天冷数据归档到文件 → 列表查询不卡
  • 可读性强:MD 文件运维可直接 cat / grep,不依赖客户端
  • 备份成本低:文件系统增量备份比 DB 增量备份便宜
  • 符合"冷数据归档"通用模式

风险

  • 跨月查询不便:JSON 索引按月组织,用户查"最近 7 天 token 使用"需要跨 1-2 个月文件聚合
  • 全文检索弱:MD 不支持索引 → grep 慢(尤其文件大时)
  • 并发写:多个 AI 调用同时写同一个 MD 文件 → 需要文件锁或单 worker 串行写
  • 激进版"JSON 也放硬盘"问题更大:列表查询需要扫所有月份 JSON,启动慢

推荐改良版

hot/cold + 工业标准格式:

  • Hot(0-30 天):DB biz.ai_run_logs(列表 / 筛选 / 分页友好)
  • Cold(30-365 天):Parquet 文件按月分区(/data/cold/ai_run_logs/2026-04.parquet),DuckDB 可直接 SQL 查询,列存压缩比 MD/JSON 高 10x
  • Frozen(>1 年):对象存储(可选,Wave 5 之后)
  • Index:DB 保留 biz.ai_run_logs_archive_index 表(每月一行,记 partition 路径 + row_count + 占用空间)

比 Neo 的 JSON+MD 方案优:

  • Parquet 比 MD 体积小,解压快
  • DuckDB 直接对 Parquet 跑 SQL,跨月聚合不需要写 Python 代码
  • 工程上久经考验(数据湖标准格式)

比 Neo 的"JSON 也放硬盘"激进版优:

  • 启动快(DB index 表毫秒级返回月份列表)
  • 工程友好(Parquet 主流工具链都支持)

修正后判定:[P1] Wave 4,选改良版 D(Hot DB 30 天 + Cold Parquet 按月分区)。如果你坚持 MD 友好(运维 cat / grep),可以双写:Parquet 主存储 + MD 摘要文件(每行 1 句关键字段)用于人眼浏览。


四、简化方案

F2-2 改良:基于 Neo 给的前提,最简方案

Neo 给的前提:

仅当前开发环境进行测试;支持同步测试脚本到 GIT;敏感信息可以上传 GIT 我允许

最简方案(对齐 Neo 前提):

步骤 动作 工时
1 .gitignore:71 tests/ → 删除该行(或改为更精细 **/__pycache__/ **/.pytest_cache/) 5 分钟
2 git add -A apps/*/tests/ 入仓现有所有测试 1 分钟
3 不脱敏(Neo 允许敏感) 0
4 不启 CI(Neo 仅本地测试) 0
5 写审计:tests 入仓 + 备注"Neo 决定本地跑测试" 5 分钟

好处:

  • 测试代码可见 → 跨设备协作不破坏
  • 测试可信度提升(Wave 1 W1-T4 audience 7 单测可入仓)
  • 后续若决定启 CI,只需添 GitHub Actions 即可,无需先做脱敏扫描

修正后判定:Wave 5 处理(主线 5 分钟级动作,跟其他文档收尾合并 1 个 PR)。


五、F3-2 实证 — DashScope Qwen3-Max-Preview 计费

5.1 官方计价(2026-05 实测)

DashScope 官方价 OpenRouter 第三方
Input $1.20 / 1M tokens ≈ ¥8.64 / 1M $0.78 / 1M
Output $6.00 / 1M tokens ≈ ¥43.20 / 1M $3.90 / 1M
上下文窗口 258K tokens
最大输出 66K tokens

(USD→RMB 按 1:7.2 估算,实际按结算汇率为准)

5.2 Qwen3 Tokenizer 切词特性(用于精确估算)

Qwen3 系列基于 BPE tokenizer,中英文切词比例:

文本类型 字符 / token 比 1000 字符约耗 token
纯英文 3.8-4.2 ~250
纯中文 1.6-1.9 ~600
中英混合 2.0-2.5 ~450
JSON 结构 2.5-3.0(标点占 token) ~370

NeoZQYY 场景多为中文 prompt + JSON output,估算系数:1000 字符 ≈ 500 tokens

5.3 SDK 计费返回(关键)

DashScope SDK 调用返回中包含实际 token usage:

response = dashscope.Generation.call(...)
# response.usage.input_tokens
# response.usage.output_tokens
# response.usage.total_tokens

重要发现:DashScope 不返回直接的 RMB cost 字段,需要后端按"input × 单价 + output × 单价"自己算。

5.4 推荐方案(基于实证)

修正后选项:

  1. A SDK token + 配置表单价(SCD2):cfg_ai_token_price 表按 (model, effective_from) 切片,每次调用记 input_tokens / output_tokens,后端实时算 RMB → 优:符合 SCD2 规范,DashScope 调价时只需 INSERT 新行 劣:对账依赖配置表与官方价格同步
  2. B 硬编码 $1.20 / $6.00 + 月度对账:简单,DashScope 调价后手工更新代码 → 优:5 分钟落地 劣:依赖人
  3. C 调用 DashScope 计费 API(若有):查询账户实际消费 → 优:最准 劣:大概率没有此 API

修正后判定:选 A(SCD2 配置表),Wave 2 实施。表 schema 建议:

CREATE TABLE biz.cfg_ai_token_price (
    model_name TEXT NOT NULL,           -- 'qwen3-max-preview'
    input_price_per_million NUMERIC(8,4),  -- 8.64 RMB
    output_price_per_million NUMERIC(8,4), -- 43.20 RMB
    currency TEXT DEFAULT 'CNY',
    effective_from DATE NOT NULL,
    effective_to DATE,                  -- NULL 表示至今
    note TEXT,
    PRIMARY KEY (model_name, effective_from)
);

写入策略:Wave 2 第一次种子写入当前价格,后续 DashScope 调价时人工 INSERT 新行(effective_from = 调价日,前一行 effective_to = 调价前一日)。


六、F3-4 答疑 — "沙箱 4-1 申请 4-5 数据"

Neo 提问:

比如沙箱设定了 4 月 1 日,我申请了 4 月 5 日的数据,如何处理?返回空?

主线分析(基于 P20 SPEC §3.5 业务日上界视图):

6.1 当前实现(2026-05-02 已落地)

P20 SPEC §3.5 的 39 个业务日上界视图,在沙箱模式下:

WHERE <date_column> <= app.business_date_now()  -- = sandbox_date

意味着:

  • 沙箱设 2026-04-01,小程序/admin-web 访问任何业务数据视图
  • 视图自动 WHERE 上界 ≤ 2026-04-01
  • 如果用户显式过滤 >=2026-04-05(申请 4-5 数据)→ 返回空(因为 4-5 这天的数据已被视图层过滤掉)

6.2 推荐处理(更友好)

选项 行为
A 显式 422 拒绝(我推荐) 后端校验:若用户 query 含 date_param > sandbox_date → 返回 422 + "沙箱日期 2026-04-01,无法查询晚于此日期的数据" UX 明确,用户知道为什么空 后端 query 校验逻辑增加
B 静默返空 当前实现:返回 [] 简单 用户不知道是真没数据还是被沙箱挡了
C 悄悄裁剪查询范围 后端把 >=4-5 自动改为 <=4-1 看起来"有数据" 误导用户,数据语义错位

强烈推荐 A:沙箱演示场景下,用户切了 sandbox_date 应该明确知道"不能查未来",422 是清晰的反馈。

实施位置:

  • 小程序 + admin-web 的 board / records 端点,在 query 解析后加校验
  • 校验函数放 apps/backend/app/services/runtime_context.py,统一逻辑

修正后判定:Wave 5 文档收尾时统一加 + 在 P20 SPEC §3.5 加这条 AC(验收标准)。可在 Wave 1-4 内任何模块改动时顺手加。


七、F2-1 OpenAPI 历史调研(完成)

详细 234 行报告 → F2-1-openapi-history.md

惊人真相(印证 Neo 直觉"有历史原因被忽略"):

  • OpenAPI 抓取脚本 scripts/ops/_export_openapi.py 曾经存在,12 行(2026-03-09 创建,逻辑极简 from app.main import app; app.openapi())
  • 2026-04-06 00:03:同一天先跑脚本抓最后一次 OpenAPI(commit 6f8f123,backend-api.json 末次更新)
  • 2026-04-06 00:39:36 分钟后,Claude Opus 4.6 协助"清理 1155 个废弃文件"(commit 779b2f6),把活的工具与一堆 v4-v8 废报告脚本一起误归档到 _DEL/_DEL/scripts/ops/_export_openapi.py — 大批量整理时工具识别不足
  • 28 天内无人发现(因为 spec-close.md 第 45 行虽写"手工同步 backend-api.json"但没指脚本路径,无 hook 强制)
  • 9/10 缺失端点都是工具消失新加的 router(都在 caf179a / 2026-05-04 02:30 加入)
  • 1/10(/api/admin/triggers/unified)在 6f8f123 同 commit 内,属"抓取与合并并行竞态"

真相判定:AI 大批量整理时的误判,把活的工具当废文件归档。脚本本身无 bug,只是消失了。

推荐方案 A+B 组合:

  • A 从 _DEL/ 恢复脚本(5 分钟,12 行无需改)+ 重抓 + 入仓 → Wave 2 撰写前完成
  • B 加 PostToolUse hook 匹配 apps/backend/app/routers/*.py,提醒重抓,并在 spec-close.md 第 45 行补脚本调用命令(防 OpenAPI 再 stale)
  • C(改运行时拉 /openapi.json)留 Wave 5 远期治理

修正后判定:Wave 2 前主线立即执行 A 恢复 + 重抓(零风险),Wave 2-3 加 B 防御。


八、本次响应后 Wave 重新分配

Wave 新增 / 调整
Wave 1(进行中) + F1-5 沙箱 batch-run 接入 runtime_context(沙箱主线必修)
Wave 2 + F1-1 长事务幂等(批 2 admin-ai 改造时一并)+ F2-1 修 OpenAPI 抓取 + F3-1 cache 粒度 + F3-2 配置表单价 + F3-3 audit_log + 二次确认
Wave 4 + F1-2 降级 UX(切 site 过滤) + F1-3 hot/cold + Parquet + F3-5 unified 分页
Wave 5 + F2-2 tests/ 入仓(简化 5 分钟版) + F3-4 沙箱越界 422(P20 SPEC AC + 各 service 校验)
撤销 F1-4(admin-web 无 site_admin 场景)

九、需 Neo 进一步确认的 3 项

# 问题 主线建议
F1-3 hot/cold + Parquet 改良版 vs Neo 原 JSON+MD 方案 改良版(运维"cat 友好"可加双写 MD)
F1-2 修正后选 A(切 site 过滤 + 显式"全部")vs 维持现状 A
F3-2 SCD2 配置表单价 vs 硬编码 SCD2

回答这 3 项后,所有 Wave 1 findings 进入实施轨道。F2-1 子代理调研完成后,主线整合最终路径。


来源