docs(ops): close audit batch 4 report and park medium leftovers
Critical/high fixes are already on dev. Record the frontend test report, restore the audit note, and move remaining medium/low items into long-term so they are not treated as release blockers. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
---
|
||||
title: "系统深度体检审计(2026-09-19,dev@e8ed33b)"
|
||||
status: done
|
||||
created: 2026-09-19
|
||||
updated: 2026-09-19
|
||||
severity: high
|
||||
---
|
||||
|
||||
# 系统深度体检审计(2026-09-19)
|
||||
|
||||
> 只读审计,未修改业务代码。分支 `docs/system-deep-audit-2026-09-19`,基点 dev@e8ed33b。
|
||||
> 方法:go vet / go test -short 静态基线 + 五路并行深潜(后端 server/chat、docgov/events/工作流/迁移、前端 web、配置 flag/死代码、安全鉴权)。
|
||||
|
||||
## 一、总体结论
|
||||
|
||||
- **静态基线健康**:`go vet ./...` 零告警;`go test -short ./...` 55 包全 PASS;全仓 TODO/FIXME 仅 2 处非实质。
|
||||
- **四条已声明红线全部核实一致**:`MULTI_INTENT_PLAN_TIER=legacy`、`SEMANTIC_SUMMARY_REPLACE` 未接线、`FAV_DEGRADED_READ=false`、SWBOOT-10 fail-closed stub——代码与三环境 compose 均对齐,无漂移。
|
||||
- **IAM 主链路复核成立**:路由统一挂鉴权中间件、SQL 全参数化、token 哈希存储、错误出参有内部信息过滤。但存在 dev/test 兜底与端点级鉴权缺口(见 S1/S2)。
|
||||
- **本次新发现**:2 项 critical(后端数据竞态 + docgov 吞错)、10 项 high、若干 medium/low。其中 3 项被两路独立审查交叉命中(见 ★ 标记),可信度最高。
|
||||
- FEATURE-MATRIX 已声明的 partial/deferred(rdev、SWBOOT、FAV、D7、首载性能)不在本次重复申报范围;本次发现均为**新增**缺口。
|
||||
|
||||
## 二、Critical(发布前必须评估)
|
||||
|
||||
### C1 ★ docgov 持久化全链路 fire-and-forget 吞错;fencing token 未读回
|
||||
`internal/docgov/lease.go:460-467, 485-490`;`internal/docgov/engine.go:318, 392, 405, 470, 477, 650, 743, 750, 1081-1134`
|
||||
|
||||
租约获取/续约/回收、正文哈希、认领状态、提案决定及**全部审计日志**均为 `_, _ = e.pool.Exec(...)` 静默吞错:
|
||||
- 审计 INSERT 失败 → 合规事件永久丢失,无重试无告警;
|
||||
- 租约 UPDATE 失败 → 内存与 DB 分叉,重启后可并行编辑同一文档;
|
||||
- `lease.go:485` 用 `context.Background()` 脱离请求生命周期;
|
||||
- `loadDocumentFromDBLocked` 的 SELECT 列表**不含 `lease_fencing_token` 列**(00034 迁移已建列)→ 进程重启后 fencing 语义完全失效(合法持锁者被误判 stale,或 stale 写者被放行——两个方向都有缺口)。
|
||||
|
||||
**建议**:持久化失败必须返回 error 或 slog.Error+指标;审计写入失败进重试队列;lease SELECT 补 fencing 列;persistLeaseLocked 失败回滚内存状态。
|
||||
|
||||
### C2 ★ Session 全字段数据竞态 + 跨项目污染
|
||||
`internal/chat/session.go:275-277`;`internal/server/server.go:432-435`;`internal/server/handlers.go:196-198`
|
||||
|
||||
- `Messages`/`UserCtx`/`LastAccessedAt` 的读写锁粒度碎片化:SSE 路径持 `execMu`,而 `hydrateVisibleHistory`、`handleGetProject`、`cleanStaleSessionsLocked`、`server.go:435` 均不持锁。并发 SSE+REST 同会话时 `go test -race` 可复现 data race。
|
||||
- `handleChat` 无锁写 `sess.ProjectID = req.ProjectID`,同一 sessionID 被不同项目请求交错时跨项目串扰。
|
||||
|
||||
**建议**:Session 加 `sync.RWMutex` 统一保护;ProjectID 改为请求级参数不写回共享 sess。
|
||||
|
||||
### C3 SSE WriteTimeout=120s 硬杀长任务 + 心跳 goroutine 生命周期不一致
|
||||
`internal/server/server.go:352-355`;`internal/server/sse.go:252-271`
|
||||
|
||||
全局 `WriteTimeout: 120s`;SSE 靠 45s 续期+15s 心跳兜底,心跳被中间代理吞掉时长 LLM 回合(dialogueTimeout=3min)被强杀。非流式 `handleRunTask` 同步执行数十分钟任务,120s 必然截断响应(业务已执行、客户端收不到结果 → 幂等重试造成重复执行观感)。心跳 goroutine 模式与 `handleTaskRunEvents`(主循环 select,无此问题)不一致。
|
||||
|
||||
**建议**:长任务端点异步化(提交+轮询/SSE);心跳并入主 select 或 WaitGroup 收敛。
|
||||
|
||||
### C4 工作流计划保存跨语句竞态 + completed_by 错填
|
||||
`internal/projectinstance/service.go:185-190`;`internal/projectinstance/stage_store.go:132-138`
|
||||
|
||||
- `SaveWorkflowPlan`:upsert 与 bump revision 两条独立事务,并发下同版本号先互相覆盖 plan 再一方 bump 失败 → **版本号与 plan 内容错位落库**。`Activate` 的 token 前置校验与激活事务间存在 TOCTOU。
|
||||
- `completed_by = (SELECT activated_by ...)`:最终阶段完成的归属人被错填为激活人,审计归属错误。
|
||||
|
||||
**建议**:upsert+bump 同事务 + `FOR UPDATE` 锁 project 行;completed_by 显式传当前操作者。
|
||||
|
||||
## 三、High(建议进入 short-term 整改)
|
||||
|
||||
| # | 发现 | 位置 | 要点 |
|
||||
|---|------|------|------|
|
||||
| H1 ★ | dev/test 未认证静默兜底为 user id=1 | `internal/server/auth_middleware.go:48-51` | `Env=dev|test` + `AllowInMemory` + 无 ContextDB 时,无 token 请求静默识别为 id=1(管理员)。main 已被 `validateProductionSecrets` 兜住。建议:兜底路径加审计日志+启动告警;中期删除 legacy 兜底 |
|
||||
| H2 ★ | docgov 批注/审计端点无资源级鉴权且信任请求体身份 | `internal/server/handlers.go:858-940, 534-552` | 任意登录用户读任意文档批注/审计;`AddComment` 直接用 `req.UserID/UserName/UserRole` 可伪造他人身份;`Claim` 角色由客户端自选。两路审查交叉命中。建议:actor 一律取 principal;读类端点加项目成员校验 |
|
||||
| H3 ★ | 会话查询类端点水平越权 | `chat_turn_api.go:12-45`;`handlers.go:947-981, 429-451` | `handleGetChatTurn`/`handleListChatSessions`/`handleGetUserContext` 的 session_id/user_id 来自 query 不校验归属;userID<=0 时默认 1(种子 admin)。建议:改用 principal 或比对不一致 403 |
|
||||
| H4 | 登录/注册无速率限制 | `server.go:295-296` | 全仓无限流;bcrypt 高成本反而便于 CPU 耗尽 DoS。建议:IP+用户名滑动窗口限流 |
|
||||
| H5 | SSE 任务流缺幂等前置检查 | `internal/server/sse.go:398-424` | REST 路径有 `FindByIdempotencyKey`,SSE 路径没有;EventSource 断线重连产生重复任务执行 |
|
||||
| H6 | 事件 dispatcher stale-fencing 无限重放 | `internal/events/worker.go:206-275` | ErrStaleFencing 直接 cancel+return 不计 Failed;handler 半成功被回滚后事件无限重放,永不可达 dead,无告警 |
|
||||
| H7 | 迁移 00001–00009 缺 down;00012 seed 迁移破坏性 DELETE | `deploy/postgres/goose/` | 前 9 个迁移无 down;00012 无条件 DELETE 30 个 session 的真实消息再插种子;多个迁移事务内 CREATE INDEX(非 CONCURRENTLY)大表会锁表 |
|
||||
| H8 | compose 弱口令兜底 + main 注册默认开放 | `docker-compose.{dev,test}.yml:17,86,101`;`main.yml:101` | dev/test 的 DB/ADMIN 口令有弱默认值;main 已用 `:?required` 强制但 `AUTH_REGISTRATION_ENABLED` 默认 true。建议 test 对齐 main 必填,main 注册默认 false |
|
||||
| H9 | 前端 KaTeX 占位符 XSS | `web/src/engine/renderMarkdown.ts:44-64, 106-108` | 数学公式 catch 分支把未转义原文放入占位符数组,还原发生在 escapeHtml 之后 → XSS。建议:catch 分支 escapeHtml(math) + 占位符随机化 |
|
||||
| H10 | `context.Background()` 脱离请求生命周期 | `internal/chat/session.go:131-134`;`server.go:423,458,566` | LLM 摘要/DB 调用用 Background,客户端断开无法取消,慢库时 handler 挂死。建议:透传请求 ctx + WithTimeout |
|
||||
|
||||
## 四、Medium(选录,详见各专项)
|
||||
|
||||
| # | 发现 | 位置 |
|
||||
|---|------|------|
|
||||
| M1 | 全局缺安全响应头(CSP/nosniff/X-Frame-Options/Referrer-Policy) | `internal/server/server.go:624-636` |
|
||||
| M2 | 租约 TTL 无上限(可锁文档 1000 天)+ AcquireLease 无编辑权校验 | `handlers.go:1196-1203`;`docgov/lease.go:62-70` |
|
||||
| M3 | coordinator 关键词命中强制改写意图 + 模板硬编码"张工您好" | `internal/coordinator/engine.go:409-416, 485` |
|
||||
| M4 | `fmt.Sscanf` 解析 `u_sess_xxx` 必然失败 → UserID=0 审计落空 | `coordinator/engine.go:930-934, 1067-1071` |
|
||||
| M5 | `Runtime.Start` 被 main 与 Server.Start 双重调用且错误被吞 | `server.go:343-345`;`cmd/server/main.go:47` |
|
||||
| M6 | sessions map 无硬上限,惰性清理可被随机 session_id 放大 | `server.go:451-453` |
|
||||
| M7 | 修订三阶段写(账本→DocGov→freeform)无事务,靠客户端重试补偿 | `document_revision_handlers.go:274-318` |
|
||||
| M8 | 测试 flag 名笔误 `FAV_PUBLISHER_ENABLE`(少 D)门闩失效 | `internal/artifactvault/publisher_gate_test.go:16` |
|
||||
| M9 | dev compose 声明永不消费的 `SEMANTIC_SUMMARY_REPLACE`(诱导性配置);dev 与 test/main 默认模型不一致(M2.7-highspeed vs M3) | `docker-compose.dev.yml:119,44` |
|
||||
| M10 | OpsCutover 硬编码 `"dev"`,test/main 无合规 cutover 路径 | `internal/events/cutover.go:12-19` |
|
||||
| M11 | 前端乐观已读无失败回滚;MessageStream prevMsgCount 跨会话不重置;SSE 无 online 感知重连 | `web/src/hooks/useUnreadMarks.ts:176-233`;`MessageStream.tsx:148-154` |
|
||||
| M12 | ExcelViewer 无行数上限内存爆炸;React 19 下 30+ 处裸 setTimeout 无清理 | `ExcelViewer.tsx:42-55` |
|
||||
| M13 | `deploy/postgres/migrations/` 疑似死目录(14 个旧 SQL 无引用,与 goose 重复) | `deploy/postgres/migrations/` |
|
||||
| M14 | `Orchestrator.ResolveDocTask` 静默返回 0 值三权掩盖数据不一致 | `internal/workflow/runtime/orchestrator.go:69-83` |
|
||||
| M15 | PG 事件投递允许乱序而 MemoryBus 有 gap 语义——测试替身与生产行为分叉 | `internal/events/dispatcher.go:56-63` vs `bus.go:99-103` |
|
||||
|
||||
## 五、Low(选录)
|
||||
|
||||
- `handleHealth` 每请求同步两次 DB 往返无缓存无超时(`handlers.go:97-110`)
|
||||
- `writeStoredEvents` json.Marshal 错误被吞(`task_run_handlers.go:437`)
|
||||
- `ReplayPlan.Digest()` 不含 DryRun 字段(纵深防御,`internal/events/replay.go:24-38`)
|
||||
- 前端 localStorage 缓存无版本字段;`lucide-react@^1.16.0` 版本异常需确认来源;App.tsx 4600 行/30 个 useEffect 巨石组件
|
||||
- `handleRunTaskStream` 死参数 `includeDetails/requestID`(`sse.go:417-418`)
|
||||
|
||||
## 六、复核确认无问题的面(证据性记录)
|
||||
|
||||
- SQL 注入:全部 pgx 参数化;仅 4 处 fmt.Sprintf 涉 SQL 均为常量
|
||||
- CORS:白名单制、无 `*`+凭证;SSE 鉴权失败返回 JSON 而非污染流
|
||||
- 日志:密码 bcrypt、token SHA-256 摘要存储;`httpx.LooksInternal` 过滤内部错误串
|
||||
- os/exec:bridge 路径来自服务端配置,用户输入只进 stdin payload;无 text/template 引用
|
||||
- 事件系统:claim 幂等(SKIP LOCKED + fencing 复合判断)、ack+inbox+checkpoint 单事务、envelope 完整性校验、replay 审批人≠操作人——设计正确
|
||||
- 前端:Mermaid strict 模式、链接 noopener、ErrorBoundary 覆盖根组件、EventSource 卸载清理正确
|
||||
|
||||
## 七、优先级建议
|
||||
|
||||
1. **进 main 前必须处理**:C1–C4、H1–H5、H8、H9(H8 的 main 注册默认开放一项)
|
||||
2. **short-term 整改批**:H6、H7、H10、M1、M2、M8(一行修复恢复门闩)
|
||||
3. **backlog**:其余 medium/low
|
||||
|
||||
## 关联整改
|
||||
|
||||
- Remediation: 待立项(建议按第七节优先级拆 short-term 任务)
|
||||
|
||||
## 证据
|
||||
|
||||
- `go vet ./...` 零输出;`go test -short ./...` 55 包 ok(2026-09-19,dev@e8ed33b)
|
||||
- 五路只读深潜:后端 server/chat、docgov/events/工作流/迁移、前端 web、配置/flag/死代码、安全鉴权
|
||||
- 任务条目:[ops/short-term/2026-09-19-system-deep-audit.md](../ops/short-term/2026-09-19-system-deep-audit.md)
|
||||
|
||||
## 开放问题
|
||||
|
||||
- dev 与 test/main 默认模型不一致(M2.7-highspeed vs M3)是否刻意?未见 `.doc/ops` 对齐记录
|
||||
- `deploy/postgres/migrations/` 是否还有外部工具依赖?无则建议归档
|
||||
- H1 legacy 兜底是否有仍在使用的内部工具依赖?删除前需盘点
|
||||
+7
-2
@@ -5,7 +5,7 @@
|
||||
|
||||
## 焦点
|
||||
|
||||
1. **系统体检整改**:Wave 0–7 **done**(Wave 7 编排确认见 [决策记录](./short-term/2026-09-18-wave7-roadmap-orchestration.md))
|
||||
1. **2026-09-19 审计整改批 1–4 done**(合入 `844f757` / `08f4e0b` / `a2a49a6` / `d73bc79`)。余项见 [long-term](./long-term/2026-09-19-audit-remainder.md)。未晋升 test/main,未 rebuild 容器。
|
||||
2. **Control Center 已移出本仓库**:项目进度由独立统一管理系统承担;本仓库恢复为智能体系统。见 [任务](./short-term/2026-09-19-remove-control-center.md)
|
||||
3. **rdev 模板深度 / document-author-only**:已合入 `origin/dev`;未晋升 test/main
|
||||
4. **红线**:禁止整支 merge FAV;不默认升 `MULTI_INTENT_PLAN_TIER=full`;`SEMANTIC_SUMMARY_REPLACE` 不随 W2 开启;FAV live 观察窗证据驱动;`FAV_DEGRADED_READ=false`;项目 143 只读;SWBOOT-10 保持 fail-closed stub;D7 待合规签字
|
||||
@@ -14,6 +14,11 @@
|
||||
|
||||
| owner | task | branch | worktree | mutex | status |
|
||||
|-------|------|--------|----------|-------|--------|
|
||||
| Cursor | audit-b1-data-consistency | fix/audit-b1-data-consistency | - | docgov+workflow+chat | done |
|
||||
| Cursor | audit-b2-authz-hardening | fix/audit-b2-authz-hardening | - | authz | done |
|
||||
| Cursor | audit-b3-sse-events | fix/audit-b3-sse-events | - | chat+events | done |
|
||||
| Cursor | audit-b4-frontend | fix/audit-b4-frontend | - | web | done |
|
||||
| Cursor | audit-remainder-backlog | docs/audit-remediation-backlog | - | audit | done |
|
||||
| Cursor-Auto | 2026-09-19-remove-control-center | fix/remove-control-center | - | controlcenter | done |
|
||||
| Cursor-Auto | 2026-09-17-control-center-server | feature/control-center-server | - | controlcenter | cancelled |
|
||||
| Kimi | 2026-09-18-user-manual | feature/user-manual | .worktrees/feature-user-manual | docs | done |
|
||||
@@ -144,7 +149,7 @@
|
||||
|
||||
| holder | phase | since | scope | queue |
|
||||
|--------|-------|-------|-------|-------|
|
||||
| - | idle | 2026-09-19 | audit-b1~b3 已合入 dev(b3 merge a2a49a6,vet/test 全绿);批4 待开 | - |
|
||||
| - | idle | 2026-09-19 | 审计批 1–4 已合入 dev(844f757 / 08f4e0b / a2a49a6 / d73bc79);medium 见 long-term | - |
|
||||
|
||||
**phase**: `idle` | `merging` | `smoke` | `e2e`
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "2026-09-19 审计剩余项(medium/low,不挡已合入批 1–4)"
|
||||
status: planned
|
||||
created: 2026-09-19
|
||||
updated: 2026-09-19
|
||||
---
|
||||
|
||||
# 2026-09-19 审计剩余项
|
||||
|
||||
## 动机
|
||||
|
||||
[系统深度体检](../../audit/2026-09-19-system-deep-audit.md) 的 C1–C4 与 H1–H10 已按四批合入 `dev`。下列 medium/low 仍真实存在,但不进入本轮发布回退。
|
||||
|
||||
## 成功标准
|
||||
|
||||
- 每条有独立 short-term、负例测试或明确关闭理由后再标 done
|
||||
- 不把本清单自动写成 gap-matrix blocker
|
||||
|
||||
## 依赖
|
||||
|
||||
- 批 1–4 已在 `dev`:`844f757`、`08f4e0b`、`a2a49a6`、`d73bc79`
|
||||
|
||||
## 暂不启动原因
|
||||
|
||||
本轮范围只到 critical + high。下列项要么是加固、要么需要产品/合规决策,要么改动面大于收益。
|
||||
|
||||
## 清单
|
||||
|
||||
| ID | 项 | 位置 | 说明 |
|
||||
|----|----|------|------|
|
||||
| M1 | 安全响应头 | `internal/server/server.go` CORS 中间件 | 补 `nosniff` / `X-Frame-Options` / `Referrer-Policy` / 收敛 CSP |
|
||||
| M2 | 租约 TTL 无上限 | `handlers.go` AcquireLease | clamp 到 `DefaultHumanLeaseTTL`,Acquire 前校验编辑权 |
|
||||
| M3 | 关键词改写意图 + 硬编码「张工」 | `internal/coordinator/engine.go` | 移到意图层并加置信度;称呼取用户名 |
|
||||
| M4 | `fmt.Sscanf` 解析 `u_sess_*` 得到 UserID=0 | 同上 | 统一数字 ID |
|
||||
| M5 | `Runtime.Start` 双调用且吞错 | `cmd/server/main.go` 与 `server.go` | `sync.Once` 或删 Server.Start 内调用 |
|
||||
| M6 | sessions 无硬上限 | `server.go` cleanStaleSessionsLocked | LRU + 服务端发 session id |
|
||||
| M7 | 修订三阶段写无事务 | `document_revision_handlers.go` | outbox 或单事务投影 |
|
||||
| M9 | `SEMANTIC_SUMMARY_REPLACE` 只在 dev compose 声明;dev/test 默认模型不一致 | compose | 删未接线 flag 并钉死测试;确认 M3 是否刻意 |
|
||||
| M10 | cutover 只允许 `dev` | `internal/events/cutover.go` | 写明 test/main 切换路径 |
|
||||
| M13 | `deploy/postgres/migrations/` 死目录 | 与 goose 重复 | 确认无外部依赖后归档 |
|
||||
| M14 | ResolveDocTask 静默 0 值三权 | `orchestrator.go` | 找不到 duties 应报错 |
|
||||
| M15 | PG 投递允许乱序,MemoryBus 有 gap | `dispatcher.go` vs `bus.go` | 对齐测试替身与生产顺序语义 |
|
||||
| L1 | health 每次打两次 DB | `handlers.go` | 短缓存 + 超时 |
|
||||
| L2 | SSE marshal 错误被吞 | `task_run_handlers.go` | 失败写 error 帧 |
|
||||
| L3 | ReplayPlan digest 不含 DryRun | `replay.go` | 纳入 digest |
|
||||
| H1-del | 删除 legacy user-id=1 兜底 | `auth_middleware.go` | 已加日志;删除前盘点调用方 |
|
||||
| FE | App.tsx 巨石、localStorage 无版本、lucide 版本确认 | `web/` | 拆 hook;缓存加 version;确认包来源 |
|
||||
|
||||
## 相关链接
|
||||
|
||||
- 审计:[../../audit/2026-09-19-system-deep-audit.md](../../audit/2026-09-19-system-deep-audit.md)
|
||||
- 批 1–3 报告:`.doc/test-reports/2026-09-19-audit-b*.md`
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
title: "系统深度体检审计(独立审查潜在缺陷与未完善点)"
|
||||
status: done
|
||||
created: 2026-09-19
|
||||
updated: 2026-09-19
|
||||
owner: Cursor
|
||||
branch: docs/audit-remediation-backlog
|
||||
worktree: "-"
|
||||
mutex: audit
|
||||
---
|
||||
|
||||
# 系统深度体检审计(2026-09-19)
|
||||
|
||||
## 目标
|
||||
|
||||
在不改业务代码的前提下,对当前 dev(e8ed33b)做一次独立深度审查,输出 `.doc/audit/` 审计笔记,列出潜在 bug 与未完善项并给出严重度分级。
|
||||
|
||||
## 范围
|
||||
|
||||
- Go 静态验证:`go vet ./...` + `go test -short ./...`
|
||||
- 后端:server 路由/chat SSE/docgov/events 错误处理与并发风险
|
||||
- 前端 web:错误处理、SSE 重连、竞态
|
||||
- 配置:flag 默认值一致性、死代码、环境差异(dev/test schema 漂移)
|
||||
- 安全:IAM 旁路、密钥泄露面
|
||||
- DB:goose 迁移一致性与回滚风险
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不修改业务代码(docs-only 分支)
|
||||
- 不验证已明确 deferred 的事项本身(FAV live 放量、D7 签字、SWBOOT-10)——仅核对声明与代码是否一致
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [x] 创建 docs 分支、登记 CURRENT
|
||||
2. [x] go vet + go test -short
|
||||
3. [x] 并行子代理深潜后端/前端/配置/DB/安全
|
||||
4. [x] 汇总撰写 audit 笔记并提交
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [x] 每个发现均有代码路径 + 行号证据
|
||||
- [x] 严重度分级(critical/high/medium/low)
|
||||
- [x] 与 FEATURE-MATRIX 已声明的 partial/deferred 项对齐,不重复申报
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- go vet 零告警;go test -short 55 包全 PASS(dev@e8ed33b)
|
||||
- 审计笔记:[.doc/audit/2026-09-19-system-deep-audit.md](../../audit/2026-09-19-system-deep-audit.md)
|
||||
- 五路并行只读深潜全部完成;四条红线核实一致;新发现 4 critical(C1 docgov 吞错 / C2 Session 竞态 / C3 SSE 超时 / C4 工作流竞态)+ 10 high
|
||||
- 整改:critical/high 已分四批合入 `dev`(`844f757` / `08f4e0b` / `a2a49a6` / `d73bc79`)。medium/low 见 [long-term](../long-term/2026-09-19-audit-remainder.md)。
|
||||
@@ -1,6 +1,6 @@
|
||||
# 模块与功能完成度(SSOT)
|
||||
|
||||
**更新**: 2026-09-17(W3 PI 叙事 done;W4 多意图扩面 done)
|
||||
**更新**: 2026-09-19(审计整改批 1–4 已合入 dev;medium/low 见 [long-term](../ops/long-term/2026-09-19-audit-remainder.md))
|
||||
**production_ready**: yes(权威来源:[gap-matrix](../remediation/gap-matrix.md);本表不推导发布门禁)
|
||||
**发布缺口**: [../remediation/gap-matrix.md](../remediation/gap-matrix.md)
|
||||
**协作焦点**: [../ops/CURRENT.md](../ops/CURRENT.md)
|
||||
@@ -8,6 +8,8 @@
|
||||
**整改计划**: [../remediation/2026-09-16-feature-matrix-production-readiness-plan.md](../remediation/2026-09-16-feature-matrix-production-readiness-plan.md)
|
||||
|
||||
> 本表描述**能力成熟度**;上线 blocker 见 gap-matrix。二者正交:能力行不必全部 `done` 才能发布;`partial`/`deferred` 不得自动回退 `production_ready`。
|
||||
>
|
||||
> 2026-09-19 深度审计的 critical/high 已分四批合入 `dev`(数据一致性、鉴权、SSE/事件、前端 XSS)。不改 `production_ready`。未做项在 [long-term](../ops/long-term/2026-09-19-audit-remainder.md)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# 审计整改批 4(前端)测试报告
|
||||
|
||||
## 一、 测试背景 (Background)
|
||||
|
||||
审计 H9:KaTeX 失败回退把未转义公式放进占位符,还原发生在 `escapeHtml` 之后。另有未读乐观更新失败不回滚、会话切换后滚动基线不重置、Excel 全量进内存。
|
||||
|
||||
## 二、 测试目标 (Test Objectives)
|
||||
|
||||
- `npm test` 全绿(含伪造占位符用例)
|
||||
- `npm run build` 通过
|
||||
|
||||
## 三、 测试方案与环境 (Test Plan & Environment)
|
||||
|
||||
- 分支 `fix/audit-b4-frontend` → dev(merge `d73bc79`)
|
||||
- 命令:`cd web && npm test && npm run build`
|
||||
- 未在浏览器复现 KaTeX catch 与万行 Excel(依赖构造输入);XSS 主路径由单测钉住
|
||||
|
||||
## 四、 预期结果 (Expected Results)
|
||||
|
||||
- 伪造 `XMATHTOKENX0XENDX` 不会被还原成 HTML
|
||||
- catch 分支公式经 `escapeHtml`
|
||||
- 未读 POST 失败回滚本地集合
|
||||
- `sessionId` 变化时 `prevMsgCountRef` 归零
|
||||
- Excel 预览最多 1000 行并提示
|
||||
|
||||
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
|
||||
|
||||
### 用例 1:前端测试
|
||||
- 输入:`npm test`
|
||||
- 输出:`tests 406 pass`,vitest `3 files / 32 tests passed`,fail 0
|
||||
- 判定:PASS
|
||||
|
||||
### 用例 2:生产构建
|
||||
- 输入:`npm run build`
|
||||
- 输出:`tsc && vite build` 成功,`precompress: wrote 49 .br and 49 .gz`
|
||||
- 判定:PASS
|
||||
|
||||
## 六、 自动化测试套件汇总 (Test Suite Execution)
|
||||
|
||||
- node:test 406 + vitest 32,全部 PASS
|
||||
- `tsc` 无错误
|
||||
|
||||
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
|
||||
|
||||
- 批 4 已合入 dev(`d73bc79`)。
|
||||
- 浏览器端到端未覆盖 Excel 截断与未读回滚;需要时用真实文件和断网点测。
|
||||
- 容器仍是合入前二进制,前端 dist 由 Go 服务托管时需 rebuild 才进 `:8080`。
|
||||
|
||||
## 证据
|
||||
|
||||
- merge:`d73bc79`
|
||||
- commit:`6c28fca`
|
||||
Reference in New Issue
Block a user