- Introduced `convert_meta_api` endpoint to fetch the latest NAV date for conversion processes, restricted to users with the "risk_officer" role. - Updated `created_at` field in `AgentMessage` to use UTC timezone for consistency in timestamp handling. - Added `get_max_product_nav_date` method in `CoreReadOnlyRepository` to support the new API functionality. - Enhanced Milvus template loading in `MilvusTemplateVectorStore` to ensure collections are loaded when they exist. This update improves the API's capability to handle conversion metadata and ensures accurate timestamp management across the application.
28 KiB
28 KiB
企业级测试日志 · TEST-2026-09-12-FE-001
顾问前端 · 风控新功能(基金转换 T+1)· 风控前端 —— 真实浏览器 + 真实 HTTP 端到端验收(第三轮)
1. 文档元数据
| 字段 | 值 |
|---|---|
| 测试记录编号 | TEST-2026-09-12-FE-001 |
| 缺陷/变更标题 | 顾问前端四页 + 风控转换线 + 风控前端六页端到端:174 用例 · 161 PASS / 12 FAIL / 1 SKIP · 收敛 6 缺陷 |
| 文档版本 | v1.1 |
| 创建日期 | 2026-09-12 |
| 最后更新 | 2026-09-12(v1.1 · 结果明细入库 + D3 计数口径更正) |
| 关联分支 | merger |
| 被测版本 | merger @ c09b987(feat(web): 基金转换演示页与 agent 镜像表迁移; Core seed 修复) |
| 关联拍板 / TODO | docs/superpowers/specs/2026-09-12-advisor-agent-frontend-design.md · docs/memory/TODO.md「E2E 最小集进仓库」P0 |
| 风险等级 | MEDIUM(无 P1 阻断主流程;2 项降级 + 3 项前端缺陷 + 1 项纵深防御缺口) |
| 缺陷类型 | 前端默认值越界 ×1 · 前端字段名不匹配 ×1 · 路由守卫缺失 ×1 · 承接 D2/D3 ×2 · 测试资产腐化 ×1 |
| 发现阶段 | 真实浏览器 + 真实 HTTP 端到端验收(第三轮) |
| 修复阶段 | 未修复 —— 本轮定性「先报告、确认后再修」,app/ 与 web/src/ 零改动 |
2. 组织与责任
| 字段 | 值 |
|---|---|
| 所属系统 | JinRong 金融四 Agent 智能管家 |
| 所属模块 | 投资顾问 Agent 前端 · 风控 Agent(基金转换 T+1 新功能 + 前端) |
| 子模块 / 服务 | web/src/pages/advisor/*(4 页)· web/src/pages/risk/*(6 页)· /api/simulate/trade* · /api/admin/convert/confirm · /api/risk/* |
| 模块负责人 | (见 docs/项目框架设计/理财顾问Agent-合并说明.md) |
| 发现人 | Andrew |
| 修改人 | (未修改 · 待确认后再修) |
| 测试执行人 | Andrew |
| 评审人 | (待模块负责人确认) |
| 发布建议 | 不阻断主线:鉴权 / 合规 / 门闸 / 模板 / 台账 / 适当性 / AML 全绿;建议按下方优先级排修后再做演示 |
3. 环境与基线
| 字段 | 值 |
|---|---|
| 测试环境 | development · 本机 Windows 11 · Python 3.13 · Node(Playwright 1.63.0) |
| 被测版本 | merger @ c09b987 · git status 干净 |
| 后端 | python -m uvicorn app.main:app --host 127.0.0.1 --port 8000(真实进程 · 无 --reload) |
| 前端 | cd web && npm run dev → 必须 http://localhost:5173(app/ 无 CORS 中间件,浏览器只能走 Vite 的 /api 代理;且 WebCrypto 需安全上下文) |
| 浏览器 | 系统 Chrome(channel:'chrome'·headless)· 视口 1440×1000 |
| 数据库 | MySQL jinrong_agent + jinrong_core · NAV 最新 2026-09-11 · core_product_nav 覆盖 14 产品 |
| Redis / Milvus / Ollama | Docker 6380 · Milvus Lite(kb_script_templates 疑似空集,见 D3) · bge-m3 |
| DeepSeek | 有效 key · 异动解读实测 used_fallback=False latency≈1415ms(真实 LLM 路径) |
| 前置自检(关键) | 复跑前确认 :8000 上无 merge 前的旧进程:/openapi.json 必须含 /api/admin/convert/confirm 等转换路径。本轮开工时曾抓到旧进程(PID 27348 启动于 16:55:24,早于代码落地 17:52–17:59),若未重启,全部转换用例会假失败 |
| 基线对照 | 顾问 API 首轮(v1.0)为 53 PASS / 5 FAIL / 5 SKIP,本轮复跑已改写至 60 PASS / 3 FAIL / 0 SKIP,见 2026-09-12-advisor-agent-e2e/ |
4. 测试目标与方法
| 字段 | 值 |
|---|---|
| 目标 | 三块:A 顾问前端四页(真浏览器点按)· B 风控转换线 + RBAC(真 HTTP)· C 风控前端六页(真浏览器点按) |
| 方法 | 两条独立跑道:PyPlaywright→Chrome→Vite 代理→uvicorn / httpx→uvicorn。断言不看截图,逐用例判定 |
| 关键工具改进 | 新增 clearAuth(page)(切角色前清 localStorage,否则 #/login 会重定向回上个角色)与 waitRows(page)(轮询等真实行,取代固定 waitForTimeout 冒充空表判定) |
| 用例总数 | 174 = 顾问 API 63 + 风控 API 64 + 浏览器 47 |
| 账号 | 顾问 STAFF-10086 · 风控专员 STAFF-30001 · 风控经理 STAFF-31001 · 合规 STAFF-40001 · 客户 CUST-9527 |
| 未覆盖(明示) | 两个 SSE 对话页(/app/advisor/chat、/app/risk/chat,依赖实时 LLM 不确定)· agent_tools.py/agent_graph.py(无 HTTP 入口) |
5. 结果总览
| 跑道 | 用例 | PASS | FAIL | SKIP | 退出码 |
|---|---|---|---|---|---|
顾问 API advisor_e2e_smoke.py |
63 | 60 | 3 | 0 | 1 |
风控 API risk_e2e_smoke.py |
64 | 63 | 0 | 1 | 0 |
顾问前端 09-advisor-pages.mjs |
17 | 15 | 2 | 0 | — |
风控前端 10-risk-pages.mjs |
21 | 19 | 2 | 0 | — |
跨角色 11-cross-role.mjs |
9 | 4 | 5 | 0 | — |
| 合计 | 174 | 161 | 12 | 1 |
| 业务面 | 状态 |
|---|---|
| 顾问:鉴权 / 合规 / 复制门闸 / 模板 / 输入防护 / 跨线回归 | ✅ 全绿 |
| 顾问:市场异动(D1) | ✅ 本轮转绿(API 10/10 · 浏览器 4/4) |
| 顾问:KYC 采集(D2) | ❌ 500(API 2 FAIL · 浏览器 1 FAIL) |
| 顾问:话术语义检索(D3) | ⚠️ 静默降级(API 1 FAIL · 浏览器 1 FAIL) |
| 风控:台账 / 处置 / 适当性 / AML / 模拟交易 / 转换线 | ✅ 全绿(除下列前端渲染缺陷) |
| 前端:转换页一键预置(F1)· 模拟交易预警编号(F2)· 路由守卫(F3)· 确认日默认值(F4) | ❌ 见 §6 |
唯一 SKIP:风控 API R4 阻断文案 advice/notice —— 该客户/产品组合未触发阻断,非失败。
复现确认(报告定稿前实跑):两条 API 跑道按 §「复现三连」重放,逐字命中 ——
advisor_e2e_smoke.py → 60 PASS / 3 FAIL / 0 SKIP(退出码 1,失败项与 §7.5 完全一致)·
risk_e2e_smoke.py → 63 PASS / 0 FAIL / 1 SKIP(退出码 0)。
浏览器跑道(47 用例)为当时截图留档,未重放 —— 见 §3 复核提示。
6. 缺陷描述(6 条 · 均未修复)
归属分类:F1/F2/F4 = 实现缺陷(前端) · F3 = 纵深防御缺口 · D2/D3 = 承接顾问线未修项 · T1 = 测试资产腐化
F1 · 转换页「演示全转」一键预置是跨主体组合,必然失败(P2)
| 字段 | 内容 |
|---|---|
| 现象 | 风控前端「基金转换」受理 Tab 的唯一预置场景,点一下提交即 400 |
| 复现 | web 起后进 #/app/risk/convert → 受理 Tab → 直接点「提交受理」 |
| 期望 / 实际 | 演示预置应能一键走通 → 202 / HTTP 400 CROSS_ENTITY_NOT_SUPPORTED |
| 根因 | web/src/pages/risk/RiskConvertPage.tsx:16-27 的 ACCEPT_PRESETS[0].values 把 PROD-110022(华夏模拟基金 · TA-CN-001)配给 PROD-161725(易方模拟基金 · TA-CN-002)。业务规则要求同销售机构 + 同管理人 + 同 TA,违约即 400(app/service/convert/errors.py:75-78) |
| 实测 | 浏览器 B6.1/B6.2:预置文案 演示全转(CUST-1001 · 110022→161725 · 30000 份) → HTTP 400,页面报 CROSS_ENTITY_NOT_SUPPORTED;API 侧 R6 同步复现 |
| 影响 | 演示路径的唯一入口是不可用路径 —— 演示时必卡在第一步 |
| 修复方向(只写方向) | 把预置 to_product_id 换成与 PROD-110022 同管理人同 TA 的产品(实测 PROD-000001 可 202);不动手 |
| 佐证(改对后可通) | 同页手工改为 CUST-9527 / 110022→000001 / 4000 → 202 + convert_group_id=CNV-…,查询/撤单全链路通 |
F2 · 模拟交易页「预警编号」字段名不匹配,恒显示「—」(P2)
| 字段 | 内容 |
|---|---|
| 现象 | A-3 大额演示确实生成了预警,但页面「预警编号」永远是 — |
| 复现 | #/app/risk/simulate → 预置 A-3(50 万)→ 提交 |
| 期望 / 实际 | 显示刚生成的预警号 / — |
| 根因 | web/src/pages/risk/RiskSimulatePage.tsx:138 取 key: 'alert_id'(单数),而 POST /api/simulate/trade 返回的是 alert_ids(复数数组) |
| 实测取证 | 同一次请求:响应体 alert_ids=["ALT-20260912-A021D01E"]、triggered_rules=["RISK-001","RISK-002","RISK-003","RISK-004"],而页面渲染 预警编号 — |
| 影响 | 演示时「造预警」这一步看起来失败(实际成功),会误导演示者重复操作、堆重复预警 |
| 修复方向(只写方向) | 改取 alert_ids(数组,多命中时并列展示);不动手 |
| 注意 | 不是后端缺陷 —— 后端已正确返回;浏览器用例 B5.1 对后端断言 PASS,B5.2 对渲染断言 FAIL,二者分离记录 |
F3 · 无路由级角色守卫,菜单隔离仅「隐藏」不「拦截」(P2 · 纵深防御缺口)
| 字段 | 内容 |
|---|---|
| 现象 | 换角色后手输 URL 可打开另一条业务线的页面 |
| 复现 | 以风控 STAFF-30001 登录,地址栏直接输 #/app/advisor/compliance(或 kyc / templates / market-alerts);反向以顾问登录输 #/app/risk/convert |
| 期望 / 实际 | 应重定向回本角色首页 / 页面正常渲染 |
| 根因 | web/src/layouts/AppLayout.tsx:20 的 allowedPaths 只用于计算 Menu 的 selectedKey(:23),未参与任何路由守卫;web/src/routes/menus.ts 的 buildMenuGroups(roleLabel) 只做菜单隐藏 |
| 实测 | C1.2–C1.5(风控→顾问四页)、C2.2(顾问→转换页)全部 打开=true;菜单侧 C1.1/C2.1 隔离正常 |
| 定性:不是数据越权 | 后端 RBAC 仍然生效:C1.6 以风控身份在顾问页实际点「检测」→ HTTP 403 /api/advisor-agent/compliance/content-check;C2.3 顾问点开预警台账 → 页面级 AUTH_403_AGENT_MISMATCH。缺口只在 UI 可见性 |
| 为何仍要修 | ①演示时误入他人页面会看到空表/报错,观感像故障;②纵深防御应双端一致;③不做守卫时,未来若新增「前端隐式信任、后端未覆盖」的接口即成真越权 |
| 修复方向(只写方向) | 在 AppLayout 或路由层加基于 roleLabel 的 allowedPaths 守卫,越界重定向到本角色首页;不动手 |
F4 · 转换页确认批处理默认日期越界,默认即触发降级路径(P3)
| 字段 | 内容 |
|---|---|
| 现象 | 「确认批处理」Tab 的默认日期落在 NAV 区间之外 |
| 复现 | #/app/risk/convert → 确认批处理 Tab → 不改日期直接点「触发 confirm_batch」 |
| 期望 / 实际 | 默认值应落在可用区间(2026-09-11 及之前)/ 默认 2026-09-15,区间外 |
| 根因 | web/src/pages/risk/RiskConvertPage.tsx:37 硬编码 useState('2026-09-15');而 core_product_nav 最新 nav_date = 2026-09-11 |
| 实测对比 | 默认 2026-09-15(区间外)→ scanned=8 confirmed=0 nav_pending=8(全落 nav_pending,零确认);改 2026-09-11(区间内)→ scanned=0(因 accept_date 解析到下一交易日) |
| 口径提醒 | scanned / nav_pending 是当时存量(随每轮新增受理单增长,复跑时会变大,如 API 侧复现为 scanned=10)。判据看 confirmed 恒为 0,不看绝对数 |
| 定性 | 降级不是缺陷,默认值才是 —— scanned=8 confirmed=0 nav_pending=8 是 accept_date 解析为未来交易日所致(属已文档化行为);缺陷在于页面把不可用日期设为默认,使用者一进来就走到零确认路径 |
| 修复方向(只写方向) | 默认值改为由数据驱动(取 core_product_nav 最新 nav_date)或退化为 2026-09-11;不动手 |
D2(承接)· KYC 对话写 agent_message 时 created_at 显式 NULL(P1)
| 字段 | 内容 |
|---|---|
| 状态 | 未修复(顾问线首轮即报,本轮前端侧独立复现) |
| 现象 | KYC 页点「发送采集」→ 页面 INTERNAL_ERROR |
| 前端取证 | 09-advisor-pages.mjs A4.2:页面渲染 INTERNAL_ERROR internal server error trace_id: trc-6417ef20507a4d10;同页 A4.1「创建会话」成功(唯采集一步挂) |
| 根因 | app/model/entities.py:116 的 created_at 无 Python 侧 default,app/repository/kyc_session_repository.py 用 ORM 写且不传该字段 ⇒ 显式 NULL 覆盖 DDL 默认值 → IntegrityError 1048 |
| 完整定性 | 见 ../2026-09-12-advisor-agent-e2e/TEST-LOG-2026-09-12-ADV-001.md §6 D2 |
D3(承接)· Milvus 集合 released 未 load,语义检索静默降级(P2)
| 字段 | 内容 |
|---|---|
| 状态 | 未修复(根因已由服务端日志坐实,详见顾问线报告 v1.1) |
| 前端取证 | 09-advisor-pages.mjs A3.2:搜「亏损」返回 4 行,match_type 全为 keyword(["keyword","keyword","keyword","keyword"]) |
| 决定性证据 | uvicorn 日志 MilvusException (code=101, message=Collection 'kb_script_templates' is in state 'released'; call load() before search/get/query) —— 6 次独立异常(12 行提及 = 6 条 RPC-error + 6 条 traceback),全 session 无其它 Milvus 错误类型。原文摘录见 _raw/server-log-evidence.md §2 |
| 口径更正 | ADV-001 v1.1 与本文首版均写作「出现 10 次」—— 该数字实为日志行数(5 次异常 × 2 行),非异常次数。次数随每次语义检索查询累加(ADV-001 定稿时 5 次,本包 18:55 复现 +1)。结论不变,只是计数口径写错了 |
| 第二层 | 集合目录 5.0K/2 文件 vs 已灌集合 50K/5 文件 ⇒ 疑似空集,仅补 load() 未必恢复召回 |
| 完整定性 | 见顾问线报告 v1.1 §6 D3 |
T1 · 测试资产腐化(非产品缺陷 · 只上报)
| 资产 | 问题 | 建议方向(不动手) |
|---|---|---|
scripts/dev/sandbox_risk_test.py:325-326 |
仍断言 convert → 400 BAD_REQUEST;而 03fce88 之后合法 convert 受理为 202。该断言如今必然失败 |
把 expect(..., 400, "BAD_REQUEST") 改为断言 202 受理,或换成真正的非法组合(如本报告 F1 的跨主体对)以保留负例覆盖 |
scripts/demo/run_demo_smoke.ps1 |
仍调 /api/v1/* 并用 username/password 登录、断言 code=="00000";/api/v1 在 app/ 中已无任何路由,按当前代码必然 404 |
改到 canonical 路径 + POST /api/auth/login {"actor_id","token_type"} |
docs/演示文档/功能演示版启动手册.md 等 |
残留 alembic upgrade head 与 /api/v1 指引 |
与现状对齐 |
7. 测试执行记录(明细)
7.1 Part A · 顾问前端(09-advisor-pages.mjs · 15 PASS / 2 FAIL)
| 用例 | 结果 | 证据 |
|---|---|---|
| A1.1 首页渲染 + 名册表有行 | PASS | rows=10 canvas=2 |
| A1.2 首页无 HTTP≥400 | PASS | 0 条 |
| A2.1 合规检测「违规承诺」→ BLOCK | PASS | 命中 BLOCK |
| A2.2 复制门闸 Tab1 检测后自动回填(有序依赖) | PASS | summary="本产品保本保收益,绝对不会亏。" level=BLOCK |
| A2.3 复制门闸 BLOCK 内容 → 拒绝导出 | PASS | content cannot be copied or exported |
A2.4 复制门闸 INFO 内容 → 放行出 use_id |
PASS | 回执出现 |
A2.5 输入防护「注入样例」→ prompt_injection |
PASS | 命中 prompt injection |
| A3.1 话术模板搜「亏损」有行 | PASS | rows=4 |
A3.2 话术模板 match_type |
FAIL(D3) | 全为 keyword |
A3.3 话术模板引用 → use_id |
PASS | use_id=use_ab4e… |
| A4.1 KYC 创建会话 | PASS | 创建成功 |
| A4.2 KYC 发送采集 | FAIL(D2) | 页面 INTERNAL_ERROR + trace_id |
| A5.1 市场异动查净值 000001(D1 回归) | PASS | 净值快照渲染 |
| A5.2 市场异动扫描 + 列表 | PASS | rows=5 |
| A5.3 生成解读 → 四段式 | PASS | ["【异动概述】","【原因分析】","【当前建议】","【风险提示】"] len=403 |
| A5.4 采纳(adopt) | PASS | PUT …/feedback HTTP 200 |
A6.1 BUG-1 回归:点击登录(无 reload 兜底) |
PASS | 未出现 ErrorBoundary,直入 /app/advisor/home |
7.2 Part B/C · 风控前端(10-risk-pages.mjs · 19 PASS / 2 FAIL)
| 用例 | 结果 | 证据 |
|---|---|---|
| B1.1 首页 stats 渲染 | PASS | 待处理指标可见 |
| B2.1–B2.5 台账列表 / 筛选 / 处置 Modal / 提交 200 / 自动重载 | PASS | POST /api/risk/alerts/{id}/handle → 200 |
| B3.1 A-1 阻断 → 「阻断 · CODE」 | PASS | 阻断 · SUIT_RISK_MISMATCH 客户风险等级与产品最低等级不匹配 |
| B3.2 阻断解释文案 | PASS | 同上 |
| B4.1–B4.3 AML 扫描 / 计数 / 幂等 | PASS | 扫描客户 33 人 · 命中 1 人 · 新发预警 0 条 · 跳过已有 1 人 |
| B5.1 A-3 大额 → 后端触发预警 | PASS | alert_ids=["ALT-20260912-A021D01E"] |
| B5.2 页面「预警编号」渲染 | FAIL(F2) | 页面 预警编号 — |
| B6.1 预置可见 | PASS | 演示全转(CUST-1001 · 110022→161725 · 30000 份) |
| B6.2 内置预置一键受理 | FAIL(F1) | HTTP 400 CROSS_ENTITY_NOT_SUPPORTED |
| B6.3 改对后受理 → 202 | PASS | gid=CNV-20260912-602D8732 |
| B6.4 查询框自动回填 | PASS | 回填一致 |
| B6.5 查询 → 200 + 状态 | PASS | status accepted |
B6.6 撤单 → cancelled |
PASS | status cancelled |
B6.7 确认批处理默认 2026-09-15(区间外) |
PASS | scanned 8 confirmed 0 nav_pending 8 |
B6.8 确认批处理 2026-09-11(区间内) |
PASS | scanned 0 confirmed 0 nav_pending 0 |
7.3 Part C · 跨角色(11-cross-role.mjs · 4 PASS / 5 FAIL)
| 用例 | 结果 | 证据 |
|---|---|---|
| C1.1 风控菜单不含顾问项 | PASS | 菜单已隔离 |
| C1.2–C1.5 风控直达顾问四页 | FAIL ×4(F3) | 4 页全部 打开=true,无重定向 |
| C1.6 ★ 风控身份在顾问页实际提交 | PASS | HTTP 403 /api/advisor-agent/compliance/content-check |
| C2.1 顾问菜单不含风控项 | PASS | 菜单已隔离 |
C2.2 顾问直达 /app/risk/convert |
FAIL(F3) | 打开=true |
C2.3 顾问直达 /app/risk/alerts |
PASS | 页面级 AUTH_403_AGENT_MISMATCH |
7.4 Part B · 风控 API(risk_e2e_smoke.py · 63 PASS / 0 FAIL / 1 SKIP)
| 分组 | 覆盖 | 结果 |
|---|---|---|
| R1 鉴权负例 | 缺 X-Agent-Type → 401 · 域外值 → 400 · 跨域 → 403 |
全 PASS |
| R2 台账 RBAC | officer 全量 / manager 只读 / compliance 强制 aml / 越界 403 |
全 PASS |
| R3 处置状态机 | 200 迁移 · 重复 409 STATE_CONFLICT · 404 · 超长 422 |
全 PASS |
| R4 适当性 | owner 200 / 非归属 403 AUTH_403_SCOPE · 每次落 audit_log |
全 PASS(1 SKIP:未触发阻断) |
| R5 AML | 200 · skipped_existing 幂等 · 非 officer 403 |
全 PASS |
| R6 基金转换线 | 202 受理 · 幂等重放同 group_id · 未确认单不含 _CONFIRMED_ONLY_FIELDS · 撤单/重复撤单 409 · 确认批处理双日期 · 参数 422 · RBAC 403 |
全 PASS |
R6 关键口径(易误判,已固化)
- 合法受理 = HTTP 202 +
convert_group_id+status='accepted';幂等重放也是 202,且同group_id、idempotent=true(首跑false)。 - 适当性阻断 = HTTP 200 +
blocked=true,不是 202。 accept_date格式非法(2026/09/15)由 FastAPI 查询校验拦下 → 422REQUEST_VALIDATION_FAILED,不是 400。- 撤单必须在
confirm_batch之前:确认会把单推进到nav_pending,而nav_pending不可撤(409CANCEL_NOT_ALLOWED)。
7.5 Part A · 顾问 API(advisor_e2e_smoke.py · 60 PASS / 3 FAIL)
| 分组 | v1.1 | 备注 |
|---|---|---|
| G1 鉴权与封套(5) | 5 PASS | |
| G2 合规检测(14) | 14 PASS | |
| G3 复制门闸(5) | 5 PASS | |
| G4 话术模板(12) | 11 PASS / 1 FAIL | D3 |
| G5 市场异动(10) | 10 PASS | ✅ 由 D1 修复转绿(v1.0 为 3 PASS / 2 FAIL / 5 SKIP) |
| G6 KYC(10) | 8 PASS / 2 FAIL | D2 |
| G7 输入防护(3) | 3 PASS | |
| G8 桩路由(2) | 2 PASS | |
| G9 跨线回归(2) | 2 PASS |
8. 非缺陷澄清(易误判项 · 本轮实测踩过)
| 项 | 结论 |
|---|---|
复制门闸对 BLOCK 内容返回 content cannot be copied or exported |
非缺陷,正是门闸生效。初版用例误期「成功」,已改为断言「拒绝导出」,并另加 INFO 内容放行用例形成正反对照 |
「预警编号」页面显示 — |
是缺陷(F2),但不在后端。后端 alert_ids 正确返回;浏览器用例已把「后端 PASS」与「渲染 FAIL」拆成 B5.1/B5.2 两条,避免把渲染问题记成接口问题 |
确认批处理 scanned=8 confirmed=0 nav_pending=8 |
降级是已文档化行为,非缺陷。accept_date 解析到下一交易日(未来)故不能确认;缺陷在页面默认值越界(F4),不在批处理逻辑 |
| 风控身份能打开顾问页面 | 是缺陷(F3),但不是数据越权。后端 403 仍然拦住(C1.6 实证);缺口只在 UI 可见性 |
| 风控身份点「合规检测」返回 200 | 非缺陷。app/api/deps.py:48-58 的 AGENT_ACCESS_MATRIX["advisor"].roles 含 compliance,属设计内的跨线权限。初版用例误记为缺陷,已改为真正的负例(risk_officer 声明 advisor 域 → 403) |
台账 ?status=nope 返回 200 空集 |
低危观察,不列缺陷。未做枚举校验;前端用固定 Select,实际不可达 |
转换受理「失败」于 可用份额不足:申请 30000,可用 0(已扣除在途转换占用) |
非缺陷,是用例自污染。反复跑测把 CUST-1001 持有的 30000 份 PROD-110022 占满;改用仍有 80000 份余量的 CUST-9527 后即 202。本项曾是本轮 3 条假 FAIL 的根因之一 |
advisor JWT 通道够不到 NOT_ASSIGNED/NOT_OWNER 分支 |
渠道差异,非缺陷。advisor 不在 risk 域,矩阵层先行拦截(403 AUTH_403_AGENT_MISMATCH);sandbox 里那两条断言只能走 dev debug 通道(X-Debug-Role,不过矩阵)。已在报告中标注该渠道分叉 |
9. 变更清单
| 类型 | 路径 | 说明 |
|---|---|---|
| 脚本 | scripts/dev/risk_e2e_smoke.py |
新增 · 风控 API 真实 HTTP E2E(64 用例 · R1–R6 · --only / --report / 退出码 0·1·2) |
| 脚本 | C:/Users/Windows/e2e-jinrong/harness.mjs |
改(仓库外)· ROUTES.advisor 补 4 页、ROUTES.risk 补 /app/risk/convert;新增 clearAuth / waitRows / cjk;login() 加 reload:false 选项供 BUG-1 回归 |
| 脚本 | C:/Users/Windows/e2e-jinrong/09-advisor-pages.mjs |
新增(仓库外)· 顾问前端四页(17 用例) |
| 脚本 | C:/Users/Windows/e2e-jinrong/10-risk-pages.mjs |
新增(仓库外)· 风控前端六页(21 用例) |
| 脚本 | C:/Users/Windows/e2e-jinrong/11-cross-role.mjs |
新增(仓库外)· 跨角色隔离(9 用例) |
| 文档 | docs/memory/tests/2026-09-12-agent-frontend-e2e/ |
新增 · 本包(README + 本日志 + _raw/ 结果明细) |
| 数据 | …/2026-09-12-agent-frontend-e2e/_raw/ |
新增 · 逐用例原始记录:advisor-api.md(63) · risk-api.md(64) · browser-{advisor,risk,cross-role}.json(17/21/9) · shots/(12 张截图) · README.md(来源与口径说明) |
| 文档 | docs/memory/tests/2026-09-12-advisor-agent-e2e/TEST-LOG-2026-09-12-ADV-001.md |
改 · 升 v1.1,按 merger @ c09b987 重写结论、关闭 D1 |
| 文档 | docs/superpowers/specs/2026-09-12-agent-frontend-e2e-design.md · docs/superpowers/plans/2026-09-12-agent-frontend-e2e.md |
新增 · 履约 superpowers 约定 |
| 文档 | docs/memory/MEMORY.md · docs/memory/TODO.md |
改 · 同步本轮结论与未修项 |
| 业务代码 | app/ · web/src/ |
零改动 ✅ |
10. 数据准备与副作用
| 数据集 | 是否重灌 | 说明 |
|---|---|---|
jinrong_core |
否 | 保留取证数据;未执行 prepare_all.ps1 / reset.ps1(会 DROP DATABASE) |
| 脚本副作用 | —— | 每轮新增:core_trade · convert_request · risk_alert · audit_log · 模板使用日志 等行;全部保留 |
CUST-9527 持仓 |
被占用 | 转换用例按 CONVERT_QTY_* 消耗 PROD-110022 可用份额(在途占用),重跑前若份额耗尽需重灌 |
Milvus kb_script_templates |
未灌 | 本轮刻意不执行 sync_template_vectors.py(写操作,且会掩盖 D3 的待修状态) |
| 凭据 | —— | 本包不含任何明文密码;账号一律以 STAFF-* / CUST-* 标识 |
11. 结论与剩余风险
| 字段 | 结论 |
|---|---|
| 需求是否覆盖 | 顾问前端四页 + 风控前端六页(含新增 /app/risk/convert)+ 转换线四端点 + 风控四端点 RBAC 全部触达;SSE 两页与 agent_tools/agent_graph 明示排除 |
| 旧功能是否破坏 | 未破坏 —— 顾问 API 跨线回归(G9)双绿;风控台账/适当性/AML 全绿 |
| D1 状态 | 已关闭 —— app/repository/core_ro.py:839,851 补齐方法,实测市场异动 API 10/10 + 浏览器 4/4 转绿 |
| 剩余风险 | ① F1 转换页预置必失败 ⇒ 演示第一步即卡(建议优先修,一行数据改动);② F2 预警编号恒 — ⇒ 演示「造预警」观感失败(建议优先修);③ F3 无路由守卫 ⇒ 纵深防御单端;④ F4 确认日默认越界 ⇒ 默认零确认;⑤ D2 KYC 采集 500;⑥ D3 语义检索静默降级(且疑似空集);⑦ sandbox_risk_test.py:325-326 与 run_demo_smoke.ps1 已腐化,会持续报假红/假绿;⑧ 浏览器脚本在仓库外,他人不可复现 |
| 建议修复顺序 | F1 → F2(均为演示可见、改动面极小) → D2 → F4 → F3 → D3(需先确认向量是否已灌) |
| 建议人工再验 | 修完 F1/F2 后重跑 node 10-risk-pages.mjs,目标 21/21 PASS;修完 D2 后目标 advisor_e2e_smoke.py 0 FAIL |
| 是否阻断发布 | 不阻断主线(鉴权 / 合规 / 门闸 / 模板 / 台账 / 适当性 / AML 全绿);演示前建议先修 F1、F2 |
12. 修订历史
| 版本 | 日期 | 作者 | 说明 |
|---|---|---|---|
| v1.0 | 2026-09-12 | Andrew | 首版 · 174 用例 · 161 PASS / 12 FAIL / 1 SKIP · 收敛 6 缺陷 + 1 项测试资产腐化 · 业务代码零改动 |
| v1.1 | 2026-09-12 | Andrew | 结果明细入库 + 计数口径更正。 ①新增 _raw/ 逐用例原始记录:browser-*.json×3(脚本原产物原样搬运)· shots/×12 张截图 · README.md(来源与口径说明)②新增 _raw/server-log-evidence.md —— 把 D2/D3 赖以定性的 uvicorn 日志摘录入库(原件在临时目录会被清理),结论由「不可被第三方查阅」转为可查阅 ③D3 计数口径订正:原记「日志出现 10 次」实为日志行数(5 次异常 × 2 行),正确表述为 6 次独立异常;D3 结论未变 ④D2 由「推断」升级为「日志直证」:补 IntegrityError (1048, "Column 'created_at' cannot be null") 逐字报文,失败 SQL 明确列出 created_at 列且参数为 None ⑤新增交叉印证:全 session 8 次 500 全部出自 KYC 采集,市场异动线 0 次 —— D1 已修的独立佐证 |