收口多维系统审查(07-16-system-multidimensional-audit)
@@ -16,6 +16,91 @@ Start from `docs/文档索引.md` and `docs/文档事实源状态矩阵.md`.
|
||||
raw payloads, full account identifiers, invoice originals or confidential
|
||||
business content.
|
||||
|
||||
## Scenario: Finding Lifecycle And Audit Closeout
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
- Trigger: a review, audit or trial-run task records findings and later code,
|
||||
deployment or external evidence changes their current state.
|
||||
- Applies to Trellis PRDs, review reports, finding ledgers and management
|
||||
summaries.
|
||||
|
||||
### 2. Signatures
|
||||
|
||||
- Canonical ledger fields: `findingId`, `dimension`, `discoverySeverity`,
|
||||
`confidence`, `discoveryStatus`, `remediationStatus`, `deploymentStatus`,
|
||||
`externalVerificationStatus`, `evidenceRef`, `businessImpact`,
|
||||
`controlObjective`, `safeVerification`, `followUpWorkPackage`.
|
||||
- Delta fields: `discoveryCommit`, `reviewedCommit`, changed-commit list,
|
||||
validation command, result and explicit environment boundary.
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
- Preserve the discovery baseline, discovery severity and discovery status.
|
||||
Later remediation must add a delta; it must not rewrite history as if the
|
||||
finding never existed.
|
||||
- Record remediation, deployment and external-behavior verification as three
|
||||
independent states. A local test pass does not prove deployment, and a
|
||||
deployed build marker does not prove role-specific or real-device behavior.
|
||||
- A closeout task must have one canonical finding ledger. Component reports
|
||||
may retain their original wording, but duplicate IDs and reclassified items
|
||||
must point to the canonical ledger.
|
||||
- When HEAD moves after discovery, record the exact old and new commits,
|
||||
classify the delta and rerun the closeout gates. Do not relabel an old report
|
||||
as evidence for the new HEAD.
|
||||
- Use repo-relative evidence references and synthetic fixtures. Unknown or
|
||||
unauthorized deployment, public, production-data and real-device checks stay
|
||||
explicit as pending or externally gated.
|
||||
|
||||
### 4. Validation & Error Matrix
|
||||
|
||||
- Local fix tested, not deployed -> remediation may pass; deployment remains
|
||||
pending and external behavior remains pending when applicable.
|
||||
- Finding open with no fix artifact -> deployment is `NO_FIX_TO_DEPLOY`, not
|
||||
`DEPLOYMENT_PENDING`.
|
||||
- Static/tooling-only finding -> deployment may be `NOT_APPLICABLE`; the
|
||||
remediation state still records whether the contract itself is fixed.
|
||||
- Duplicate component finding -> preserve its source reference and map it to
|
||||
exactly one canonical ledger entry.
|
||||
|
||||
### 5. Good/Base/Bad Cases
|
||||
|
||||
- Good: a historical P0 remains P0/confirmed while local remediation passes,
|
||||
deployment is pending and external behavior is pending.
|
||||
- Base: an open local-only QA finding uses `NO_FIX_TO_DEPLOY`,
|
||||
`NOT_APPLICABLE` deployment or `NOT_REQUIRED` external verification as
|
||||
appropriate.
|
||||
- Bad: rename the discovery status to `RESOLVED` and omit whether the fix was
|
||||
deployed or observed externally.
|
||||
|
||||
### 6. Tests Required
|
||||
|
||||
- Task validation and Trellis governance.
|
||||
- Sensitive-content scan and document registry audit.
|
||||
- `git diff --check` plus a manual check that the recorded HEAD matches the
|
||||
evidence-producing checkout.
|
||||
|
||||
### 7. Wrong vs Correct
|
||||
|
||||
#### Wrong
|
||||
|
||||
```json
|
||||
{"findingId":"F-001","status":"resolved"}
|
||||
```
|
||||
|
||||
#### Correct
|
||||
|
||||
```json
|
||||
{
|
||||
"findingId": "F-001",
|
||||
"discoverySeverity": "P0",
|
||||
"discoveryStatus": "CONFIRMED",
|
||||
"remediationStatus": "LOCAL_FIX_VERIFIED",
|
||||
"deploymentStatus": "DEPLOYMENT_PENDING",
|
||||
"externalVerificationStatus": "EXTERNAL_BEHAVIOR_PENDING"
|
||||
}
|
||||
```
|
||||
|
||||
## Scenario: QA Readiness Report Summaries
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
@@ -18,6 +18,92 @@
|
||||
redacted form.
|
||||
- `scripts/qa/check-trellis-governance.mjs` must pass before commit.
|
||||
|
||||
## Scenario: Defensive Security Finding Summaries
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
- Trigger: a security review or remediation task writes findings into ordinary
|
||||
repository-visible Trellis material, specs, reports or management summaries.
|
||||
- This contract governs the shareable summary. It does not replace focused
|
||||
automated tests or the archived remediation task that carries engineering
|
||||
proof.
|
||||
|
||||
### 2. Signatures
|
||||
|
||||
- Allowed summary fields: `findingId`, `riskCategory`,
|
||||
`discoverySeverity`, repo-relative `codeLocations`, `businessImpact`,
|
||||
`controlObjective`, `safeVerification`, `remediationStatus`,
|
||||
`deploymentStatus`, `externalVerificationStatus`, `evidenceRef`.
|
||||
- Forbidden summary fields: exploit procedure, payload, bypass sequence,
|
||||
probability/throughput calculation, raw request/response, real-environment
|
||||
identifier or secret-bearing value.
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
- Keep the finding ID, risk category, discovery severity, repo-relative code
|
||||
locations, business impact, control objective, safe verification result and
|
||||
the separate remediation/deployment/external states.
|
||||
- Do not store attack procedures, working payloads, bypass instructions,
|
||||
probability calculations, composable endpoint sequences, raw provider or
|
||||
browser payloads, or identifying details from a real environment.
|
||||
- Phrase verification as a harmless control assertion, such as an unauthorized
|
||||
request being rejected, active content being forced to a non-executable
|
||||
download, or a negative-path test passing with synthetic data.
|
||||
- Detailed engineering proof belongs in focused automated tests and the
|
||||
archived remediation task. Ordinary finding ledgers reference that evidence
|
||||
instead of copying sensitive mechanics.
|
||||
- If evidence cannot be safely summarized, keep only metadata and a restricted
|
||||
evidence reference; do not place the raw material in the repository or chat.
|
||||
|
||||
### 4. Validation & Error Matrix
|
||||
|
||||
- Safe code location + defensive result -> allowed.
|
||||
- Real account, token, attachment, contract body, business payload or complete
|
||||
environment detail -> remove and regenerate the evidence.
|
||||
- Reproduction text that enables misuse -> replace with the control objective
|
||||
and a synthetic negative-path assertion.
|
||||
- Local remediation pass without deployment/public evidence -> keep deployment
|
||||
and external behavior pending.
|
||||
|
||||
### 5. Good/Base/Bad Cases
|
||||
|
||||
- Good: identify the affected module, state the business impact and assert that
|
||||
a synthetic unauthorized or active-content negative path is rejected.
|
||||
- Base: an unresolved static risk keeps a safe code reference and control
|
||||
objective while external behavior remains gated.
|
||||
- Bad: copy a working request sequence, payload, real endpoint context or real
|
||||
data fragment into a PRD or finding ledger.
|
||||
|
||||
### 6. Tests Required
|
||||
|
||||
- `node scripts/qa/check-sensitive-content.mjs`.
|
||||
- Manual review of security summaries for procedural or identifying detail.
|
||||
- Focused positive/negative automated tests using synthetic fixtures.
|
||||
|
||||
### 7. Wrong vs Correct
|
||||
|
||||
#### Wrong
|
||||
|
||||
```json
|
||||
{
|
||||
"findingId": "SEC-001",
|
||||
"reproduction": "step-by-step operational procedure",
|
||||
"rawPayload": "real or executable content"
|
||||
}
|
||||
```
|
||||
|
||||
#### Correct
|
||||
|
||||
```json
|
||||
{
|
||||
"findingId": "SEC-001",
|
||||
"riskCategory": "authorization boundary",
|
||||
"businessImpact": "data outside the actor's scope may be exposed",
|
||||
"controlObjective": "deny by default and enforce object scope",
|
||||
"safeVerification": "synthetic unauthorized request is rejected"
|
||||
}
|
||||
```
|
||||
|
||||
## Scenario: Business Attachment Governance
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{"file":".trellis/spec/hyb-oa/docs-and-evidence.md","reason":"复核审计基线、当前 delta 和四层状态没有混写。"}
|
||||
{"file":".trellis/spec/hyb-oa/security-privacy.md","reason":"复核提交材料不含攻击步骤、载荷、绕过方式或真实环境细节。"}
|
||||
{"file":".trellis/tasks/07-16-system-multidimensional-audit/research/findings.md","reason":"复核唯一 finding 台账、分级校准、去重和后续工作包映射。"}
|
||||
{"file":".trellis/tasks/07-16-system-multidimensional-audit/research/current-head-delta.md","reason":"复核当前 HEAD、增量提交、本地门禁与外部边界。"}
|
||||
@@ -0,0 +1,101 @@
|
||||
# 多维系统审查设计
|
||||
|
||||
## Safety Boundary
|
||||
|
||||
- 本任务是只读审查任务。默认允许读取代码、文档、Git 历史和本地测试输出,以及运行无凭据的本地构建、单测、静态门禁和 mock E2E。
|
||||
- 禁止修改业务代码、数据库、schema、迁移、权限、页面、生产配置或历史证据;发现问题只登记 finding。
|
||||
- 禁止访问带凭据公网环境、执行真实业务写入、企业微信写入、真实付款或数据库重置。
|
||||
- 生成截图或测试报告时,固定本轮输出目录并在结束前清理;既有历史证据目录保持不动。
|
||||
- 普通任务材料中的安全 finding 只保留代码位置、风险类别、业务影响、控制目标和无害验证结论;攻击步骤、载荷、绕过方式、概率推演、可组合接口细节和真实环境信息不进入 task、spec 或聊天摘要。
|
||||
|
||||
## Audit Model
|
||||
|
||||
审查采用三层证据模型:
|
||||
|
||||
1. **合同层**:当前 Trellis task、项目 spec、业务事实源和现行手册定义“应该是什么”。
|
||||
2. **实现层**:路由、页面、API、service、schema、权限和状态机定义“代码实际是什么”。
|
||||
3. **行为层**:单测、构建、E2E、截图和 QA runner 证明“当前本地行为是什么”。
|
||||
|
||||
只有三层一致时才可判为通过;缺一层时记录证据缺口或外部准入,不用历史结论补证。
|
||||
|
||||
## Execution Order
|
||||
|
||||
### 1. 冻结基线与资产清单
|
||||
|
||||
- 记录 `HEAD`、工作树、Node/npm/Prisma/浏览器版本和本地运行边界。
|
||||
- 建立功能域、路由、页面、API、schema、测试和事实源清单。
|
||||
- 标记 feature flag、冻结能力、历史兼容入口和只允许外部验证的能力。
|
||||
|
||||
### 2. 功能与业务闭环审查
|
||||
|
||||
- 按普通员工、审批人、财务/出纳、管理员等代表角色抽查核心业务链。
|
||||
- 从入口追踪到 API、service、storage、状态变化、附件/证据、通知和审计。
|
||||
- 对异常、重复提交、撤回、归档、无权限和外部依赖失败进行负路径审查。
|
||||
|
||||
### 3. 权限、状态机、数据与安全审查
|
||||
|
||||
- 对照导航/路由、前端动作和后端权限,定位“能看不能做”“前端隐藏但后端未拦”“后端拦截但前端误导”等不一致。
|
||||
- 追踪关键枚举、字段、金额/日期、附件归属和审计信息跨层传递。
|
||||
- 聚焦认证、导出、上传/下载、日志、错误响应、Secret/env 和外部集成边界。
|
||||
|
||||
### 4. 页面与设计审查
|
||||
|
||||
- 先审全局 shell、导航、搜索、通知、错误/空/加载/403/404,再审核心列表、详情和编辑流程。
|
||||
- PC 以 1440/1024 为主,移动以 375 为主并抽查 320/390/430;涉及企微时只做 UA/布局证据,真机结论保持外部准入。
|
||||
- 复核标题动作、筛选/表格、表单反馈、弹窗/危险操作、键盘/焦点、对比度、触控目标和横向滚动。
|
||||
|
||||
### 5. 测试、性能、可靠性与运维审查
|
||||
|
||||
- 先运行基础门禁,再按矩阵选择最小充分的 Playwright 集合;不以测试数量代替覆盖质量。
|
||||
- 检查前端没有 unit spec 是否造成关键纯逻辑/组件合同缺口;检查 E2E 是否陈旧、重复、依赖选择器或环境脆弱。
|
||||
- 通过静态证据、构建报告和必要的浏览器测量识别性能风险;不做无数据的泛化优化建议。
|
||||
- 核对 readiness、来源追溯、迁移、回滚、备份恢复准入、巡检、文档和培训口径。
|
||||
|
||||
### 6. Finding 收敛与交叉复核
|
||||
|
||||
- 每个 finding 先与现有任务、历史证据和其他维度去重。
|
||||
- P0/P1 finding 至少做一次独立只读复核;权限、状态机、迁移和审批规则 finding 必须跨层复核。
|
||||
- 将共因问题归并为根因,例如权限显隐合同缺失、页面模板未约束、测试与当前交互漂移。
|
||||
- 输出建议修复波次:P0 立即隔离、P1 核心闭环、P2 体验/维护、外部准入。
|
||||
|
||||
## Evidence Layout
|
||||
|
||||
- `research/baseline.md`:commit、环境和门禁结果。
|
||||
- `research/inventory.md`:功能/路由/页面/API/schema/test 资产矩阵。
|
||||
- `research/findings.md`:唯一 finding 台账。
|
||||
- `research/page-review.md`:页面、视觉、交互、响应式和可访问性证据。
|
||||
- `research/business-flow-review.md`:核心业务链和负路径证据。
|
||||
- `research/engineering-review.md`:权限、数据、安全、测试、性能和运维证据。
|
||||
|
||||
如现有文件可承载则复用,不为每个小问题新建文档。
|
||||
|
||||
## Finding Schema
|
||||
|
||||
```text
|
||||
ID | Dimension | Discovery Severity | Confidence | Discovery Status |
|
||||
Remediation Status | Deployment Status | External Verification |
|
||||
Evidence Ref | Business Impact | Control Objective | Safe Verification |
|
||||
Follow-up Work Package
|
||||
```
|
||||
|
||||
状态分层规则:
|
||||
|
||||
- `Discovery Status` 只描述发现时证据:`CONFIRMED`、`LIKELY`、`EXTERNAL_GATED`、`DUPLICATE` 或 `NOT_AN_ISSUE`。
|
||||
- `Remediation Status` 只描述当前本地修复,不因部署或公网未知而回退;常用值为 `OPEN`、`ACTIVE_TASK_OPEN`、`LOCAL_FIX_VERIFIED`、`FOLLOW_UP_RECOMMENDED`。`ACTIVE_TASK_OPEN` 只用于已有活动 task 承载但本轮不重复建账的 finding。
|
||||
- `Deployment Status` 独立使用 `DEPLOYMENT_PENDING`、`NO_FIX_TO_DEPLOY` 或 `NOT_APPLICABLE`。只有存在本地修复产物时才可写 `DEPLOYMENT_PENDING`。
|
||||
- `External Verification` 独立使用 `EXTERNAL_BEHAVIOR_PENDING`、`EXTERNAL_GATED` 或 `NOT_REQUIRED`。
|
||||
- `Safe Verification` 只写防御性断言、测试结论和浏览器尺寸结果,不写可操作的攻击复现过程。
|
||||
|
||||
## Exit Conditions
|
||||
|
||||
- P0/P1/P2 和 `EXTERNAL_GATED` 均有清晰定义与证据。
|
||||
- 所有计划内维度完成覆盖或明确说明为什么未覆盖。
|
||||
- 不存在因审查产生的业务代码、配置、数据或未清理生成物改动。
|
||||
- 最终报告能直接支持用户决定“立即修、分波修、接受、外部补证或暂缓”。
|
||||
- 原基线与当前 HEAD delta 均被保留;本地修复、部署和外部行为状态不互相替代。
|
||||
|
||||
## Rollback
|
||||
|
||||
- 审查正文和 task 记录可通过本任务提交回退。
|
||||
- 本任务不产生业务实现、schema、数据库或生产配置回滚。
|
||||
- 浏览器和测试生成物仅删除本轮明确生成的路径。
|
||||
@@ -0,0 +1,4 @@
|
||||
{"file":".trellis/spec/hyb-oa/project-governance.md","reason":"约束 Trellis-first、当前 task 执行合同与归档边界。"}
|
||||
{"file":".trellis/spec/hyb-oa/docs-and-evidence.md","reason":"约束发现、修复、部署、外部验证状态分离及证据收口。"}
|
||||
{"file":".trellis/spec/hyb-oa/security-privacy.md","reason":"约束安全 finding 的双层脱敏与无害验证表达。"}
|
||||
{"file":".trellis/tasks/07-16-system-multidimensional-audit/research/baseline.md","reason":"保留原审查基线、环境边界和旧门禁证据。"}
|
||||
@@ -0,0 +1,256 @@
|
||||
# 多维系统审查与问题分级
|
||||
|
||||
## Goal
|
||||
|
||||
以 2026-07-16 当前本地 `main` 为审查对象,从业务功能、页面体验、视觉与交互、权限与状态机、数据与安全、测试与性能、运维与文档等多个角度检查已经完成的系统,形成可复现、可去重、可排序的 P0/P1/P2 finding 和后续治理路线,而不是在审查过程中边看边改。
|
||||
|
||||
## Scope
|
||||
|
||||
- 审查当前本地前端、后端、数据模型、自动化、部署/运行脚本和现行文档事实源。
|
||||
- 覆盖功能与业务闭环、权限/状态机/数据、页面/设计/跨端、安全/隐私/依赖、测试/性能/可靠性、运维/交付/文档。
|
||||
- 只运行本地、无凭据、无业务写入的静态检查、构建、单测、mock E2E 和浏览器复核。
|
||||
- 产出证据化 finding、风险地图和建议修复波次;不在本任务实施业务修复。
|
||||
|
||||
## What I Already Know
|
||||
|
||||
- 遗留任务和运行手册已经完成收口;当前工作树在审查 task 创建前干净。
|
||||
- 最后有证据的公网部署来源为 `df26922`;当前本地 `main` 包含后续修复与收口,但尚未 push、部署或完成公网复检。本任务只审查本地基线,不能代表当前公网状态。
|
||||
- 技术栈为 React + TypeScript + Vite + Tailwind 前端,以及 Fastify + Prisma + PostgreSQL 后端。
|
||||
- 当前仓库约有 75 个前端页面文件、60 个前端组件文件、76 个路由声明、68 个后端 route 文件、63 个 service 文件、117 个 Prisma model。
|
||||
- 自动化资产约有 63 个 Playwright spec、153 个后端测试文件和 50 个 QA 脚本;前端源码目录没有独立 unit spec,页面行为主要由 E2E 覆盖。
|
||||
- 页面操作区任务已登记 5 类既有 finding:付款/合同/票据权限显隐、资产旧测试交互、标题动作合同与项目/资产视觉覆盖不足。本轮应复核和去重,不重复制造同一问题。
|
||||
- `ui-ux-pro-max` 对企业后台给出的高价值检查项包括键盘可达、可见焦点、表格移动适配、表单反馈、标题层级、移动端横向滚动、固定导航遮挡和响应式断点;其生成的红/金活泼视觉建议与当前成熟 OA 基线不匹配,不作为换肤或重品牌依据。
|
||||
- 用户已经确认:先完成收口,再独立从功能、页面、设计等多个角度审查系统并查看问题。
|
||||
|
||||
## Confirmed Constraints
|
||||
|
||||
- 用户于 2026-07-16 选择方案 1:审查采用“先广度扫描和风险分级,再对高风险链路深挖”的方式,避免只看页面或只跑测试。
|
||||
- 用户于 2026-07-16 已最终批准本 PRD 与 `design.md`,可以启动本地只读审查;外部动作仍未授权。
|
||||
- 默认只使用本地、mock、静态和无凭据验证;不连接生产数据库,不运行 live spec,不执行真实 OCR、企微写入、付款、部署或公网配置动作。
|
||||
- 审查输出写入当前 Trellis task 的 `research/` 和 PRD,不新建重复的业务手册或泛化审计文档。
|
||||
- finding 只有在有代码位置、命令结果、截图或稳定复现步骤时才标为已确认;需要公网、真机或真实角色才能判断的事项单列为 `EXTERNAL_GATED`,不虚报 PASS/FAIL。
|
||||
|
||||
## Open Questions
|
||||
|
||||
- 无。
|
||||
|
||||
## Requirements (Evolving)
|
||||
|
||||
### 1. 功能与业务闭环
|
||||
|
||||
- 按实际小团队使用路径审查登录/身份、工作台、报销与 PDF OCR、审批、采购、合同、项目、资产、票据、付款批次/AP/代账交接、人员/考勤/企微边界和系统管理。
|
||||
- 对每个域确认入口、创建/编辑/提交、审批/复核、异常/撤回、附件/证据、导出/归档、权限与审计是否闭环。
|
||||
- 区分“代码存在”“自动化通过”“本地可用”“公网已部署”“真实业务已验证”,不得互相替代。
|
||||
|
||||
### 2. 权限、状态机与数据
|
||||
|
||||
- 对照路由显隐、前端动作显隐和后端权限校验,检查只读角色、跨人员数据、管理能力和高敏附件边界。
|
||||
- 抽查核心状态机的合法迁移、幂等、并发、失败回滚、撤回/归档和审计记录。
|
||||
- 检查 Prisma schema、迁移、route/service/前端类型之间的字段和枚举一致性;不执行数据库 reset 或生产 drift 修复。
|
||||
|
||||
### 3. 页面、信息架构与设计
|
||||
|
||||
- 建立 PC 页面清单、移动页面清单和企微入口映射,检查菜单、路由、标题、面包屑、列表/详情/编辑结构及空/错/加载/无权限状态。
|
||||
- 检查视觉层级、间距、密度、颜色/对比度、图标、表格、表单、弹窗、危险操作、反馈、焦点与键盘可达性。
|
||||
- 检查 375、768、1024、1440 等代表性视口,并按产品规则补充必要的小屏和企业微信 UA;不以普通浏览器 UA 代替真机结论。
|
||||
- 设计审查尊重既有品牌与组件体系,不把外部推荐的调色板或字体直接当作改版结论。
|
||||
|
||||
### 4. 跨端和外部边界
|
||||
|
||||
- 检查 PC、移动、企业微信 deeplink/通知/只读镜像之间的功能归属与信息一致性。
|
||||
- 对 OA 主办、企微主办、OA 镜像、应急接管和高敏附件归属进行抽查,避免入口存在但业务责任不清。
|
||||
- 需要真实企业微信、真机、live OCR 或公网来源确认的 finding 只记录准入条件和证据缺口。
|
||||
|
||||
### 5. 安全、依赖与隐私
|
||||
|
||||
- 静态检查认证、授权、上传/下载、导出、日志、错误响应、敏感内容、Secret/env、依赖风险和外部集成 fail-closed 边界。
|
||||
- 不在报告中写真实票据、合同正文、完整账号、银行资料、token、Secret、完整本地路径或原始 payload。
|
||||
|
||||
### 6. 测试、性能与可靠性
|
||||
|
||||
- 评估后端测试、前端 E2E、视觉测试、权限测试和 QA runner 对真实核心路径的覆盖与重复/陈旧/脆弱情况。
|
||||
- 检查构建体积、懒加载、列表/搜索/表格、重复请求、长任务、轮询、后台 job、失败重试、超时和可观测性风险;先测量再给性能建议。
|
||||
- 环境性失败、测试缺陷和产品缺陷分开归类。
|
||||
|
||||
### 7. 运维、交付与文档
|
||||
|
||||
- 检查部署来源、环境合同、迁移/回滚、readiness、备份恢复准入、试运行、告警、巡检、操作手册和培训材料是否一致。
|
||||
- 不把历史 `issues/*.csv` 当作当前执行合同,不把旧试运行或旧公网证据当作当前 PASS。
|
||||
|
||||
### 8. Finding 合同
|
||||
|
||||
- 每条 finding 至少包含:ID、维度、严重级别、置信度、状态、证据、复现、影响、建议、修复边界、是否需要用户决策、是否已有 task。
|
||||
- `P0`:存在现实的数据泄露/丢失、越权、高风险资金或系统不可用风险,或核心业务无法继续且没有可接受绕行。
|
||||
- `P1`:核心业务链路、广泛角色权限、关键数据一致性或主要跨端体验显著受损,但存在临时绕行或影响范围可控。
|
||||
- `P2`:局部一致性、可用性、维护性、覆盖率、性能观察项或文档问题,不阻断核心业务。
|
||||
- 状态使用 `CONFIRMED`、`LIKELY`、`EXTERNAL_GATED`、`DUPLICATE`、`NOT_AN_ISSUE`,避免把证据不足的问题强行定级。
|
||||
|
||||
## Initial Acceptance Criteria(Superseded)
|
||||
|
||||
> 以下清单保留原始全维审查合同,用于说明发现阶段的覆盖意图。2026-07-17
|
||||
> 起本任务按后文“风险收敛收口”验收,不据此声称已经完成穷尽式全仓审计。
|
||||
|
||||
- 固定本地审查 commit、环境边界、命令和生成物清理规则。
|
||||
- 建立功能域 × 角色 × 页面/接口 × 证据的审查矩阵。
|
||||
- 覆盖核心业务闭环、权限/状态机/数据、页面/设计、跨端、安全、测试/性能、运维/文档八大类。
|
||||
- 运行批准范围内的基础门禁与聚焦自动化;所有失败按产品/测试/环境分类。
|
||||
- 关键 PC/移动页面形成可追溯的结构或截图证据,不把旧截图当作当前基线。
|
||||
- 已有页面操作区 finding 完成复核和去重。
|
||||
- 所有确认 finding 具备证据、复现、影响和建议;外部受限项明确准入条件。
|
||||
- 输出管理摘要、P0/P1/P2 清单、跨域根因、建议修复波次和需要用户决策的事项。
|
||||
- 审查阶段不修改业务代码、schema、配置或真实数据,不自动创建一批修复实现。
|
||||
- task validate、Trellis governance、敏感内容检查和 `git diff --check` 通过。
|
||||
|
||||
## Risk Convergence Closeout(2026-07-17)
|
||||
|
||||
### Closeout Decision
|
||||
|
||||
**Context**:原发现基线为 `bbb5c89`,当前本地目标已前移到 `8f8606c`,期间两个原 P0 已在独立任务完成本地修复与归档。继续按原始清单扩大审查会降低边际收益,也会混淆发现历史、当前修复、部署和外部行为。
|
||||
|
||||
**Decision**:本任务从“继续扩大全维扫描”转为“风险收敛收口”。保留原基线与分域报告,新增当前 HEAD delta、唯一 finding 台账、本地浏览器行为证据和双层脱敏规则;不修改业务代码,不创建下游修复 task,只登记推荐工作包顺序。
|
||||
|
||||
**Consequences**:可以稳定回答“发现过什么、当前本地修到哪里、哪些尚未部署或外部验证”,但不能据此声称当前代码已部署、公网角色可用、企微真机通过或真实业务已经完成新一轮试运行。
|
||||
|
||||
### Management Summary
|
||||
|
||||
- 唯一台账共 34 条:发现时 P0 2、P1 11、P2 21;当前开放 P0 为 0。
|
||||
- 两个原 P0 均保持发现时 P0/`CONFIRMED`,当前为 `LOCAL_FIX_VERIFIED`、`DEPLOYMENT_PENDING`、`EXTERNAL_BEHAVIOR_PENDING`。
|
||||
- 当前最重要的开放项是员工敏感数据范围、付款状态一致性、高敏合同附件和发布门禁可信度。
|
||||
- 两个已本地修复 P0 的部署与外部行为复核是另行授权的 Gate 0;六个工作包只排序本地开放问题,不能替代 Gate 0。
|
||||
- 768×1024 与 1024×768 浏览器量测确认共享表格容器隐藏超宽内容,多个核心列表的右侧操作不可达,`RESP-TABLE-001` 定为 P1。
|
||||
- 375×812 归档页的路由、空态、列表和底栏通过;长详情内部约 105px 被隐藏,形成 P2 `MOB-ARCHIVE-001`。这一区分证明静态移动路由合同失败本身不直接等于产品缺陷。
|
||||
- 后端正确拒绝的按钮显隐、全局搜索列表落点、通知目标缺失、可恢复动作确认和持续可访问性治理均按批准口径收敛为 P2;移动考勤入口自循环保留 P1。
|
||||
- 页面工作包内部先处理不可逆/资金动作确认、核心长表单保护、移动考勤自循环和中间断点表格四条 P1,再处理权限显隐与现有 `05-31` 任务;其他页面 P2 按触达治理,不一次打成巨型实施任务。
|
||||
|
||||
### Revised Acceptance Mapping
|
||||
|
||||
| 收口验收项 | 状态 | 证据 |
|
||||
| --- | --- | --- |
|
||||
| 保留原基线并补当前 HEAD delta,不改写历史结论 | PASS | `research/baseline.md`、`research/current-head-delta.md` |
|
||||
| 形成唯一 finding 台账,统一分级、去重和四层状态 | PASS | `research/findings.md` |
|
||||
| 完成 375 移动归档与 768/1024 五个共享表格页面行为量测 | PASS | `research/browser-review.md`、`research/evidence/local-browser-8f8606c/` |
|
||||
| 安全材料完成双层脱敏并沉淀稳定摘要规则 | PASS | `research/business-security-review.md`、`.trellis/spec/hyb-oa/security-privacy.md` |
|
||||
| 发现/修复/部署/外部验证状态分离成为稳定证据合同 | PASS | `design.md`、`.trellis/spec/hyb-oa/docs-and-evidence.md` |
|
||||
| 后续工作包按批准顺序登记且未创建下游 task | PASS | `research/findings.md#推荐工作包顺序` |
|
||||
| 当前 HEAD 全量本地基础门禁与收口治理门禁 | `COMPLETE_WITH_KNOWN_FINDINGS` | `research/current-head-delta.md#最终本地收口门禁`;完整基础门禁通过,专项移动合同按预期失败,流程覆盖证据保持不可信 finding,均未被掩盖。 |
|
||||
| 提交范围仅含当前 task、必要 spec 与脱敏合成截图 | PASS | `git status`、`git diff --check` 与最终只读 reviewer;0 blocker / 0 major / 0 minor。 |
|
||||
|
||||
### Revised Closeout Acceptance
|
||||
|
||||
- [x] 原发现基线 `bbb5c89` 和当前目标 `8f8606c` 均有明确、不可互相替代的证据。
|
||||
- [x] 所有分域 finding 已映射到唯一台账,批准的严重度校准和拆分已执行。
|
||||
- [x] 两个原 P0 分别记录本地修复、部署和外部行为状态,没有改写发现时严重度。
|
||||
- [x] 浏览器证据记录 viewport、最终 URL、标题、角色 fixture、横向溢出、操作可达和底栏边界,且只使用合成数据。
|
||||
- [x] 普通安全摘要不含攻击步骤、载荷、绕过方式、概率推演、可组合接口细节或真实环境资料。
|
||||
- [x] 外部未覆盖项标记为 `EXTERNAL_GATED`、`EXTERNAL_BEHAVIOR_PENDING` 或后续工作包。
|
||||
- [x] 全量本地基础门禁、task validate、governance、敏感扫描、文档 registry、测试资产清单和 `git diff --check` 已按当前工作树重跑。
|
||||
- [x] 只读复核确认 P0/P1 当前状态、提交范围和未授权边界准确。
|
||||
|
||||
### Uncovered And Authorization-Gated Boundaries
|
||||
|
||||
- 未部署,未检查公网 build SHA、边缘响应头、真实代理链或公网角色矩阵。
|
||||
- 未连接生产数据库,未执行迁移状态、drift、备份恢复、并发付款或任何真实数据写入。
|
||||
- 未读取真实员工档案、合同正文、附件、票据、银行资料、导出文件或客户端设备存储。
|
||||
- 未执行企业微信真机、真实通知、真实 OCR、在线依赖审计或外部服务写入。
|
||||
- 旧 Day 1–Day 4 试运行不复用;未来部署和外部门禁通过后必须从新的 Day 1 开始。
|
||||
- 上述边界不阻塞本地只读审查归档,但阻塞“已部署”“可公网测试”和“真实业务通过”等对外表述。
|
||||
|
||||
## Definition of Done
|
||||
|
||||
- 当前本地系统的主要能力、页面和风险有可追溯的审查覆盖,而不是只罗列已有测试。
|
||||
- finding 分级一致、去重、可复现,并能直接转成后续独立 Trellis task。
|
||||
- 明确哪些结论只适用于本地,哪些仍需部署、公网、真机或真实角色验证。
|
||||
- 给出推荐修复顺序,但不在本任务实施业务修复。
|
||||
|
||||
## Feasible Approaches
|
||||
|
||||
### 方案 1:全维度风险优先(推荐)
|
||||
|
||||
- 先做全系统静态、自动化和页面矩阵扫描,快速形成 P0/P1/P2 初版;再对 P0/P1 及跨域根因深挖。
|
||||
- 优点:覆盖用户要求的多个角度,较早暴露致命风险,也能控制审查范围。
|
||||
- 代价:首轮每个业务域的深度有限,需要第二轮按高风险聚焦。
|
||||
|
||||
### 方案 2:核心业务流深挖优先
|
||||
|
||||
- 先深挖报销/OCR/审批、采购/合同/项目、付款/AP 和人员/企微主链,再补页面与横向治理。
|
||||
- 优点:核心业务证据最扎实。
|
||||
- 代价:页面、设计、文档和低频管理能力的问题会较晚出现。
|
||||
|
||||
### 方案 3:页面与设计优先
|
||||
|
||||
- 先完成全部路由、PC/移动视口、信息架构、交互和视觉一致性审查,再回到后端与业务闭环。
|
||||
- 优点:用户可见问题收敛快。
|
||||
- 代价:越权、状态机和数据一致性等高风险问题可能被延后。
|
||||
|
||||
## Decision (ADR-lite)
|
||||
|
||||
**Context**:系统覆盖前后端、移动/企微、财务与审批等多个域;只做页面审查会遗漏越权、状态机和数据风险,只深挖业务流又会延后用户可见问题。
|
||||
|
||||
**Decision**:采用方案 1。第一轮先建立全系统资产和证据矩阵,完成八大维度广度扫描并形成 P0/P1/P2 初版;随后只对 P0/P1、跨域共因和证据冲突进行第二轮深挖。
|
||||
|
||||
**Consequences**:可以尽早得到完整风险地图,并控制审查期间不混入修复。代价是首轮不会对每个 P2 做同等深度分析;P2 在风险地图稳定后按修复波次再展开。
|
||||
|
||||
## Execution Plan
|
||||
|
||||
### Wave 1:冻结基线与全量资产矩阵
|
||||
|
||||
- 记录本地 commit、环境、功能域、角色、路由、页面、API、schema、测试和事实源。
|
||||
- 运行基础静态/构建/单测门禁,分类现有失败和 warning。
|
||||
|
||||
### Wave 2:业务、权限、状态机、数据与安全扫描
|
||||
|
||||
- 追踪核心业务闭环和代表角色的正/负路径。
|
||||
- 对导航、动作、API 权限与数据范围做跨层对照。
|
||||
- 检查状态迁移、附件/导出、审计、敏感内容和外部集成边界。
|
||||
|
||||
### Wave 3:页面、设计、响应式与跨端扫描
|
||||
|
||||
- 使用本地 Vite dev + Playwright 复核核心 PC/移动页面和企业微信 UA 布局。
|
||||
- 检查信息架构、视觉层级、表单/表格/反馈、键盘/焦点、危险操作和跨端归属。
|
||||
- 复核并去重页面操作区任务已有 5 类 finding。
|
||||
|
||||
### Wave 4:测试、性能、可靠性、运维与文档扫描
|
||||
|
||||
- 评估 63 个 E2E spec、153 个后端测试文件和 50 个 QA 脚本的覆盖、重复、陈旧和环境脆弱性。
|
||||
- 基于构建/运行证据检查性能、任务调度、重试、可观测性、部署来源、回滚、备份和文档培训。
|
||||
|
||||
### Wave 5:Finding 收敛与独立复核
|
||||
|
||||
- 统一 finding schema,合并重复问题和跨域根因。
|
||||
- 对 P0/P1、权限、状态机、迁移和审批规则 finding 做独立只读复核。
|
||||
- 输出管理摘要、问题分级、修复波次、外部补证项和需要用户决策的事项。
|
||||
|
||||
## Test Plan (Draft)
|
||||
|
||||
```bash
|
||||
cd server && npm run prisma:validate
|
||||
cd server && npm test
|
||||
cd client && npm run typecheck
|
||||
cd client && npm run build
|
||||
cd client && npx playwright test --list
|
||||
node scripts/qa/check-process-contract.mjs --baseline --json
|
||||
node scripts/qa/check-oa-permission-matrix.mjs
|
||||
node scripts/qa/check-mobile-route-contract.mjs
|
||||
node scripts/qa/check-sensitive-content.mjs
|
||||
node scripts/qa/audit-docs.mjs --check-registry
|
||||
node scripts/qa/check-trellis-governance.mjs
|
||||
git diff --check
|
||||
```
|
||||
|
||||
- Playwright 实跑范围在方案确认后冻结,优先选择本地 mock、核心流程、权限直连、跨页面一致性、项目级视觉和移动路由相关 spec;明确排除 `manual/` 和 `live-smoke.spec.ts`。
|
||||
- 浏览器复核需要本地 Vite dev,避免 production preview 的 PWA Service Worker 绕过 route mock;生成物只清理本轮明确产生的目录。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- 修复审查发现的业务代码、页面、schema、测试或文档问题。
|
||||
- push、部署、公网检查、生产配置、数据库 reset、真实数据、企业微信写入、真实付款和真实 OCR。
|
||||
- 补造旧试运行、真机或人工业务闭环证据。
|
||||
- 为追求 warning 数字归零而批量重写历史证据或无关脚本。
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- 审查设计见 `design.md`。
|
||||
- 基线盘点见 `research/audit-scope-baseline.md`。
|
||||
- 事实源入口:`docs/文档索引.md`、`docs/文档事实源状态矩阵.md`。
|
||||
- 设计事实与工程规则:`docs/产品设计规则.md`、`.trellis/spec/hyb-oa/frontend-react-vite-design.md`。
|
||||
- 权限、审批、报销/OCR、企微、部署和安全分别读取 `.trellis/spec/hyb-oa/` 对应规约。
|
||||
@@ -0,0 +1,52 @@
|
||||
# 多维系统审查范围基线
|
||||
|
||||
## Repository Snapshot
|
||||
|
||||
- 审查 task 创建日期:2026-07-16。
|
||||
- 创建 task 前工作树:clean。
|
||||
- 当前技术栈:React/TypeScript/Vite/Tailwind;Fastify/Prisma/PostgreSQL。
|
||||
- 前端资产:75 个 page 文件、60 个 component 文件、76 个 `<Route>` 声明。
|
||||
- 后端资产:68 个 route 文件、63 个 service 文件、117 个 Prisma model。
|
||||
- 验证资产:63 个 Playwright spec、153 个后端测试文件、50 个 QA 脚本;`client/src` 下没有独立 unit spec。
|
||||
|
||||
这些数字只用于确定审查规模,不等同于功能完成率或测试覆盖率。
|
||||
|
||||
## Current Truth Boundary
|
||||
|
||||
- 最后有证据的公网部署来源为 `df26922`。
|
||||
- 当前本地 `main` 包含后续可信度修复和治理收口,尚无对应公网部署证据。
|
||||
- 旧 7 天试运行只完成 Day 1–Day 4,原目标未完成;不得用于证明当前系统已经连续稳定运行。
|
||||
- 本轮只读审查默认只对当前本地基线作结论。
|
||||
|
||||
## Existing Findings To Reconcile
|
||||
|
||||
- 付款页对仅有复核权限的角色仍显示新建批次。
|
||||
- 合同只读角色仍看到新增、编辑、续约和归档入口。
|
||||
- 票据上传按钮未使用已有上传权限判断。
|
||||
- 两个资产 E2E 仍按旧“资产分类”直接按钮交互。
|
||||
- 标题动作容器只有布局,没有动作数量合同;项目/资产视觉覆盖不足。
|
||||
|
||||
以上问题来自 `05-31-unified-page-header-actions`,新审查应复核、补证和归因,不重复登记。
|
||||
|
||||
## UI/UX Rubric Input
|
||||
|
||||
`ui-ux-pro-max` 对本任务有价值的通用检查项:
|
||||
|
||||
- 键盘可达、焦点可见、标题层级和颜色不能作为唯一提示。
|
||||
- 表格在移动端应使用可控横向滚动或卡片化,不能撑破 viewport。
|
||||
- 表单需要 loading/success/error 反馈,并在 blur 或合理时机提供校验。
|
||||
- 固定导航不能遮挡内容;交互状态不应引发布局位移。
|
||||
- 代表视口至少覆盖 375、768、1024、1440,并检查移动横向滚动。
|
||||
- React 搜索/筛选需要测量后再决定 debounce 或 `useDeferredValue`,不凭感觉优化。
|
||||
|
||||
该 skill 生成的“红/金 + 活泼块状”样式与当前成熟、低认知负担的企业 OA 目标冲突,因此不作为品牌、配色或换肤建议。现有产品事实与组件设计规则优先。
|
||||
|
||||
## Initial Risk Hypotheses
|
||||
|
||||
- 前端动作显隐与后端权限校验可能存在系统性合同缺口,而不只是三个页面的局部问题。
|
||||
- 大量 E2E、零前端 unit spec 可能导致纯逻辑、组件合同和测试维护成本不平衡。
|
||||
- 历史页面/视觉 spec 数量多,可能存在旧交互断言、重复覆盖和环境性脆弱。
|
||||
- 117 个数据模型与多个集成/试运行脚本增加跨层状态、迁移和外部依赖口径漂移风险。
|
||||
- 本地与公网来源分离后,任何“正式可用”结论都必须重新标注适用环境。
|
||||
|
||||
这些是假设,不是 finding;只有后续证据支持时才进入正式台账。
|
||||
@@ -0,0 +1,59 @@
|
||||
# 本地审查基线
|
||||
|
||||
## Snapshot
|
||||
|
||||
- 审查对象:本地 `main`,`bbb5c89825b0fbee60d5f093d7b30368cb7a5104`。
|
||||
- commit 时间:2026-07-16 20:52:42 +08:00。
|
||||
- task 创建前工作树:clean;审查期间仅当前 task 目录为未跟踪内容,未修改业务代码、schema、迁移、部署配置或真实数据。
|
||||
- 环境:Linux、Node.js `v22.22.2`、npm `10.9.7`、Prisma / `@prisma/client` `7.8.0`、Fastify `5.10.0`、Playwright `1.58.2`。
|
||||
- 结论边界:所有结果仅证明该本地 commit;最后有证据的公网部署来源仍是 `df26922`,不得据此声称公网已同步或可供用户测试。
|
||||
|
||||
## 基础门禁结果
|
||||
|
||||
| 检查 | 结果 | 证据摘要 |
|
||||
|---|---|---|
|
||||
| `./scripts/check-minimal.sh` | PASS | 首次因当前 PRD 缺 `## Scope` 被治理门禁正确阻断;补齐任务合同后重跑通过。 |
|
||||
| Process contract | PASS | baseline 模式无阻断。 |
|
||||
| Trellis governance | PASS | 当前 task 和治理合同有效。 |
|
||||
| 敏感内容检查 | PASS | 扫描 30 个文件,0 finding。 |
|
||||
| `cd server && npm run prisma:validate` | PASS | Prisma schema 有效。 |
|
||||
| Server static checks | PASS | 脚本语法/静态门禁通过。 |
|
||||
| `cd server && npm test` | PASS | 153/153 文件、786/786 用例通过。 |
|
||||
| `cd client && npm run typecheck` | PASS | TypeScript 无错误。 |
|
||||
| `cd client && npm run build` | PASS | Vite 处理 2381 modules;PWA 生成 102 个 precache entries。 |
|
||||
| Feature matrix | PASS | 无阻断。 |
|
||||
| 部署环境合同 | PASS | 无阻断。 |
|
||||
| UI 静态设计规则 | PASS | 扫描 137 个文件,0 finding。 |
|
||||
| `cd client && npx playwright test --list` | PASS | 枚举 144 tests / 56 files;只代表清单可解析,尚不代表行为通过。 |
|
||||
| 文档审计 | PASS with warnings | 0 error;22 个未登记文件、19 条既有启发式 warning,后续单独归类。 |
|
||||
|
||||
基础门禁观察到两个非阻断工具链提示:Node `punycode` 弃用提示、Browserslist 数据陈旧提示。二者不等同于产品故障,进入工程维护观察项。
|
||||
|
||||
## 已确认的门禁缺口
|
||||
|
||||
### 移动路由静态合同
|
||||
|
||||
`node scripts/qa/check-mobile-route-contract.mjs` 返回 1 个 finding:
|
||||
|
||||
- `client/src/router/index.tsx:336` 的 `/mobile/wecom-approval-archive` 直接挂载 PC 页面组件 `WecomApprovalArchivePage`。
|
||||
- 脚本规则明确禁止 `/mobile` 路由直挂非 `Mobile*Page` 组件。
|
||||
- 当前状态:`LIKELY`。静态合同失败已经确认,但最终严重级别和用户影响需结合 375px 浏览器复核后裁定。
|
||||
|
||||
### 真实角色权限矩阵
|
||||
|
||||
`node scripts/qa/check-oa-permission-matrix.mjs` 未执行:
|
||||
|
||||
- 脚本默认访问公网地址,并要求多个真实角色凭据;同时会写入时间戳报告目录。
|
||||
- 这超出当前“无公网、无凭据、无真实数据”的批准边界。
|
||||
- 当前状态:`EXTERNAL_GATED`,不能记为 PASS 或 FAIL;准入条件是另行批准公网只读检查并提供脱敏测试角色。
|
||||
|
||||
## 生成物所有权与清理
|
||||
|
||||
- `client/dist/` 由本轮前端 build 于 2026-07-16 21:33 生成,已被 `.gitignore` 忽略;任务结束前可安全删除。
|
||||
- `client/playwright-report/` 于 2026-07-16 21:34 生成,已被 `.gitignore` 忽略;聚焦 E2E 完成后与本轮 `test-results/`、专用截图目录一并清理。
|
||||
- `artifacts/` 下已有历史审查证据不属于本轮生成物,不删除、不改写。
|
||||
|
||||
## 安全边界复核记录
|
||||
|
||||
- 未发现 `dangerouslySetInnerHTML`、直接 `innerHTML`、`eval`、字符串代码执行或不安全 `postMessage` 等明显前端执行 sink。
|
||||
- 安全结论仍需结合认证/授权、cookie/CSRF、代理信任、signed URL 和附件下载链路;“未命中关键词”不能替代这些跨层检查。
|
||||
@@ -0,0 +1,87 @@
|
||||
# 本地浏览器复核
|
||||
|
||||
## 结论摘要
|
||||
|
||||
- 复核基线:本地 `HEAD 8f8606c328c4754901e045c34b071ecd36215bd3`。
|
||||
- `RESP-TABLE-001`:`P1 / CONFIRMED`。768×1024 与 1024×768 均没有页面级横向滚动,但共享表格容器固定为 `overflow-x: hidden`,表格右侧被裁切且用户不能横向滚动恢复;1024×768 下五个受检页面的右侧操作均不可达。
|
||||
- `MOB-ARCHIVE-001`:`P2 / CONFIRMED`。375×812 下空态、列表卡片、角色范围和底栏安全间距通过;详情展开后,长标识会把“历史详情”内部内容撑宽并被 `overflow-x: hidden` 裁切,页面本身又不提供横向滚动。
|
||||
- 两组桌面标题动作均保持一行、完整位于视口内,标题区无横向溢出。本轮没有确认标题动作换行故障。
|
||||
- 本轮没有访问公网、真实账号或真实业务数据;所有 API 响应均为本地合成 mock,浏览器上下文阻断 Service Worker,未发现未知 API、控制台错误或页面异常。
|
||||
|
||||
## 验证边界
|
||||
|
||||
- 服务:仅监听 `127.0.0.1` 的本地 Vite。
|
||||
- 浏览器:本地 Playwright Chromium,`serviceWorkers: "block"`,`prefers-reduced-motion: reduce`。
|
||||
- 网络:只允许本地 Vite 同源请求;本轮外部来源请求数为 0。
|
||||
- 数据:全部为 `SYN-*` 合成对象;未使用真实姓名、票据、合同正文、账号、凭据、银行信息或原始 payload。
|
||||
- 角色 fixture:移动空态使用 `employee`,移动有记录/详情使用 `hr`,桌面页面使用 `admin`。
|
||||
- 页面加载、截图和量测均由 `/tmp` 临时脚本执行,未修改业务代码或测试代码。
|
||||
|
||||
## 375×812 移动企微审批归档
|
||||
|
||||
### 空态与列表
|
||||
|
||||
| 场景 | 角色 | 最终 URL | H1 | 页面横溢 | 桌面表格 | 底栏遮挡 | 结论 |
|
||||
| --- | --- | --- | --- | ---: | ---: | --- | --- |
|
||||
| 空态 | `employee` | `/mobile/wecom-approval-archive` | 企微审批历史 | `375 / 375`,0px | 0 | 滚动到底后末段距底栏 18.5px | PASS |
|
||||
| 有记录 | `hr` | `/mobile/wecom-approval-archive` | 企微审批历史 | `375 / 375`,0px | 0,显示 1 张移动卡片 | 滚动到底后末段距底栏 18.5px | PASS |
|
||||
|
||||
角色范围符合 fixture:`employee` 只显示“与我相关 / 直属团队”,`hr` 额外显示“HR/管理员全量”。长申请人名称和长单号在列表卡片中可换行,没有形成页面级横向溢出。
|
||||
|
||||
### 详情展开
|
||||
|
||||
- 最终 URL 和标题保持不变。
|
||||
- 内部移动滚动容器宽度为 `375 / 375`,滚动到底后详情末段与固定底栏仍有 18.5px 净距,底栏没有遮挡末尾内容。
|
||||
- “历史详情”面板 `clientWidth=351px`、`scrollWidth=457px`,内部内容向右超出约 `105px`。
|
||||
- 面板计算样式为 `overflow-x: hidden`;文档和移动滚动容器都没有横向滚动,因此超出内容被裁切且用户无法恢复查看。
|
||||
- 该问题只在长详情合成数据下确认;空态和列表态没有同类右侧溢出。
|
||||
|
||||
据此,移动路由不能整体判定为失败:空态、列表、角色范围与底栏通过;详情长标识裁切作为 `P2 / CONFIRMED` 独立保留。
|
||||
|
||||
## 桌面中间断点量测
|
||||
|
||||
所有页面最终 URL 均与目标路由一致,浏览器标题为“海音达工作台”,页面 `document.scrollWidth` 均等于 viewport;问题发生在共享表格容器内部。
|
||||
|
||||
| viewport | 路由 | H1 | 容器 client/scroll | 可裁切宽度 | overflow-x | 右侧操作初始可达 |
|
||||
| --- | --- | --- | --- | ---: | --- | --- |
|
||||
| 768×1024 | `/projects` | 项目 | 702 / 760 | 58px | hidden | 否 |
|
||||
| 768×1024 | `/assets` | 资产 | 702 / 760 | 58px | hidden | 否 |
|
||||
| 768×1024 | `/contracts-registry` | 合同 | 702 / 760 | 58px | hidden | 是;截图中“编辑/更多”均可见,但容器合同仍失败 |
|
||||
| 768×1024 | `/payment-batches` | 付款 | 702 / 760 | 58px | hidden | 否 |
|
||||
| 768×1024 | `/reimbursements` | 我的报销 | 702 / 760 | 58px | hidden | 否 |
|
||||
| 1024×768 | `/projects` | 项目 | 654 / 760 | 106px | hidden | 否 |
|
||||
| 1024×768 | `/assets` | 资产 | 654 / 760 | 106px | hidden | 否 |
|
||||
| 1024×768 | `/contracts-registry` | 合同 | 654 / 760 | 106px | hidden | 否 |
|
||||
| 1024×768 | `/payment-batches` | 付款 | 654 / 760 | 106px | hidden | 否 |
|
||||
| 1024×768 | `/reimbursements` | 我的报销 | 654 / 760 | 106px | hidden | 否 |
|
||||
|
||||
裁切后的操作在程序化设置 `scrollLeft` 后可以重新进入容器,但 `overflow-x: hidden` 不向用户提供横向滚动,因此不视为可达。标题动作方面:五页在两个 viewport 下均为 1 行,资产页的两个标题动作也未换行;标题动作完整位于 viewport 内,标题容器横溢均为 0。
|
||||
|
||||
## 当前主证据
|
||||
|
||||
证据目录:`research/evidence/local-browser-8f8606c/`。
|
||||
|
||||
- 结构化量测:`metrics.json`
|
||||
- 移动空态:`mobile-375x812-wecom-archive-empty-employee.png`
|
||||
- 移动空态底部:`mobile-375x812-wecom-archive-empty-employee-bottom.png`
|
||||
- 移动列表:`mobile-375x812-wecom-archive-record-hr.png`
|
||||
- 移动列表底部:`mobile-375x812-wecom-archive-record-hr-bottom.png`
|
||||
- 移动详情:`mobile-375x812-wecom-archive-detail-hr.png`
|
||||
- 移动详情底部:`mobile-375x812-wecom-archive-detail-hr-bottom.png`
|
||||
- 768×1024:`desktop-768x1024-projects.png`、`desktop-768x1024-assets.png`、`desktop-768x1024-contracts-registry.png`、`desktop-768x1024-payment-batches.png`、`desktop-768x1024-reimbursements.png`
|
||||
- 1024×768:`desktop-1024x768-projects.png`、`desktop-1024x768-assets.png`、`desktop-1024x768-contracts-registry.png`、`desktop-1024x768-payment-batches.png`、`desktop-1024x768-reimbursements.png`
|
||||
|
||||
`research/screenshots/mobile-wecom-approval-archive-375.png` 已人工复核,画面本身使用 synthetic 内容,但缺少本轮精确 SHA、角色和尺寸量测合同,因此只作为旧辅助截图,不作为当前 finding 的主证据。
|
||||
|
||||
## 证据完整性与脱敏复核
|
||||
|
||||
- `metrics.json` 只记录本地 URL、当前 SHA、viewport、最终路由、页面标题、角色代码、DOM 尺寸、截图文件名和诊断计数。
|
||||
- 对 `metrics.json` 进行敏感关键词复核,未发现公网域名、邮箱、密码、token、Secret、账号、银行资料、企业微信完整标识或真实业务字段。
|
||||
- 两个移动上下文和两个桌面上下文均为未知 API 0、console error 0、page error 0、外部来源请求 0。
|
||||
- Service Worker 在浏览器上下文层阻断;本轮页面没有发起 Service Worker 请求。
|
||||
|
||||
## 建议验收合同
|
||||
|
||||
- 共享表格修复后,两组 viewport 的容器应满足:右侧操作完整可见,或容器提供用户可操作的横向滚动;页面级 `document.scrollWidth` 继续等于 viewport。
|
||||
- 移动详情修复后,“历史详情”面板应满足 `scrollWidth <= clientWidth + 2px`,长字段名、长人员摘要、长单号和 finding 类型均可换行,不通过隐藏溢出来消除页面横滚。
|
||||
- 修复回归继续使用本地合成数据;真机企业微信 WebView 仍保持 `EXTERNAL_GATED`,不能由本轮 Chromium 结果替代。
|
||||
@@ -0,0 +1,56 @@
|
||||
# 业务、权限、数据与安全防御性审查摘要
|
||||
|
||||
> 本文件是可共享的防御性摘要。唯一分级与当前生命周期状态以
|
||||
> `research/findings.md` 为准;原始发现基线仍为 `bbb5c89`,当前增量复核
|
||||
> 见 `research/current-head-delta.md`。
|
||||
|
||||
## 摘要边界
|
||||
|
||||
- 只保留 finding ID、风险类别、发现时严重度、置信度、代码位置、业务影响、控制目标和无害验证结论。
|
||||
- 不保留攻击步骤、可执行载荷、绕过方式、概率推演、可组合接口细节、真实环境信息或原始业务资料。
|
||||
- 本地测试与归档修复任务承载必要工程证明;本摘要不复制敏感实现细节。
|
||||
- 未访问公网、生产数据库、真实员工资料、真实附件、企业微信或付款能力。
|
||||
- “本地修复通过”不等于“已部署”或“外部行为通过”。
|
||||
|
||||
## 防御性 finding 摘要
|
||||
|
||||
<a id="bsr-sec-001"></a><a id="bsr-sec-002"></a>
|
||||
<a id="bsr-authz-001"></a><a id="bsr-data-001"></a>
|
||||
<a id="bsr-priv-001"></a><a id="bsr-sec-003"></a>
|
||||
<a id="bsr-priv-002"></a><a id="bsr-sec-004"></a>
|
||||
<a id="bsr-authz-002"></a><a id="bsr-data-002"></a>
|
||||
<a id="bsr-sec-005"></a><a id="bsr-ux-001"></a>
|
||||
|
||||
| 原 ID | 风险类别 | 发现时严重度 | 置信度 | 发现状态 | 代码与证据位置 | 业务影响 | 控制目标 | 无害验证结论 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `BSR-SEC-001` | 认证 / 代理信任 | P0 | 高 | `CONFIRMED` | `server/src/app.js`、`server/src/config.js`、`server/src/routes/auth.js`、`server/tests/unit/routes/auth.login.test.js`、归档任务 `07-17-auth-challenge-trusted-proxy-hardening` | 认证挑战边界不足可能导致账号被未授权控制。 | 挑战记录单次有效、受限速与并发约束;代理来源必须显式可信。 | 当前 HEAD 的聚焦负路径、完整服务端回归和隔离并发验证均通过;仅证明本地修复,部署与公网代理行为待授权验证。 |
|
||||
| `BSR-SEC-002` | 业务附件 / 浏览器隔离 | P0 | 高 | `CONFIRMED` | `server/src/routes/purchaseRequests.js`、`server/src/services/purchaseAttachmentPolicy.js`、`client/src/api/purchaseRequests.ts`、`server/tests/unit/routes/purchase.attachments.test.js`、归档任务 `07-17-purchase-attachment-xss-hardening` | 主动内容若在 OA 同源上下文呈现,可能破坏用户会话和业务数据边界。 | 上传按实际内容验证;下载重新授权、审计并强制非执行呈现。 | 当前 HEAD 的策略、路由、完整服务端和聚焦浏览器测试均通过;仅证明本地修复,部署、边缘响应和历史资料检查待授权。 |
|
||||
| `BSR-AUTHZ-001` | 员工敏感数据授权 | P1 | 高 | `CONFIRMED` | `server/src/constants/permissions.js`、`server/src/routes/employees.js`、`server/prisma/schema.prisma` | 广泛报表能力可能越过岗位所需范围读取员工敏感字段。 | 字段级授权与人员数据范围同时生效,默认最小披露,拒绝路径可审计。 | 只读跨层检查确认当前权限粒度不足;未请求或展示任何真实员工资料。 |
|
||||
| `BSR-DATA-001` | 付款状态一致性 | P1 | 高 | `LIKELY` | `server/src/routes/paymentBatches.js`、`server/prisma/schema.prisma` | 并发状态变化可能形成重复成功或证据覆盖,影响资金状态可信度。 | 使用数据库条件更新/锁、幂等键和不可覆盖的审计证据保证单一结果。 | 静态事务边界检查发现并发保护证据不足;本轮未连接数据库或执行付款。 |
|
||||
| `BSR-PRIV-001` | 员工合同附件 | P1 | 高 | `CONFIRMED` | `server/src/routes/employees.js`、`server/prisma/schema.prisma`、`server/tests/unit/routes/employees.attachments.test.js` | 普通人员管理能力可能覆盖高敏合同资料,且用途与下载审计不足。 | 高敏附件使用独立最小权限、对象级授权、用途记录、下载审计和安全 DTO。 | 只读路由/测试合同检查确认专用控制缺口;未读取真实合同或附件。 |
|
||||
| `BSR-SEC-003` | 统一导出 | P1 | 高 | `CONFIRMED` | `server/src/routes/exports.js` 及各业务导出调用方 | 导出内容在表格软件中打开时可能被解释为活动内容,影响使用者终端边界。 | 所有 CSV/表格导出统一经过安全编码器,并以合成样例覆盖危险前缀和正常中文内容。 | 静态检查确认通用编码层缺少该类中和合同;未生成或打开真实业务导出。 |
|
||||
| `BSR-PRIV-002` | 客户端数据生命周期 | P1 | 高 | `CONFIRMED` | `client/src/auth/AuthContext.tsx`、`client/src/mobile/workflowActionQueue.ts`、`client/src/pwa.ts`、`client/src/api/workflow.ts` | 退出或切换账号后残留的身份、审批详情和草稿可能被后续设备使用者读取。 | 先决定离线业务必要性;按账号隔离、最小缓存,并在退出/切换时可验证清除。 | 静态生命周期检查确认持久化与清理合同不闭合;未检查真实设备存储。 |
|
||||
| `BSR-SEC-004` | 下载凭证 / 日志面 | P2 | 中高 | `LIKELY` | `server/src/routes/invoicePool/read.js`、`client/src/api/invoicePool.ts`、相关边缘日志合同 | URL 中的短期访问凭据可能进入浏览器或代理的常规记录面。 | 优先使用当前认证上下文的 API 下载、最小化 URL 敏感信息并约束日志与缓存。 | 采购附件分支已由独立修复任务关闭;当前其他业务下载链与默认日志面仍存在风险可能性。未访问真实边缘日志,因此保持 `LIKELY`。 |
|
||||
| `BSR-AUTHZ-002` | 受限资料规则 | P2 | 中高 | `LIKELY` | `server/src/routes/confidentialDocRefs.js`、`server/src/routes/projects.js`、`server/prisma/schema.prisma` | 已保存但未执行的访问规则可能让用户误以为资料位置受到限制。 | 产品先确认字段是正式 ACL 还是废弃元数据;若保留,必须由后端强制执行并有拒绝测试。 | 静态检查只确认规则与执行证据不一致;未访问任何真实资料位置。 |
|
||||
| `BSR-DATA-002` | 付款取消审计 | P2 | 高 | `CONFIRMED` | `server/src/routes/paymentBatches.js`、`server/prisma/schema.prisma` | 取消缺少结构化原因、并发保护和独立审计时,难以还原资金流程责任。 | 取消必须记录操作者、原因、前后状态和并发条件,且不能覆盖既有证据。 | 静态路由与模型检查确认合同缺口;未执行真实状态变化。 |
|
||||
| `BSR-SEC-005` | 浏览器防御纵深 | P2 | 高 | `CONFIRMED` | `server/src/app.js`、`server/src/config.js`、部署响应头合同 | 缺少内容执行限制会降低浏览器端对未知缺陷的纵深保护。 | 基于实际资源清单分阶段收紧 CSP,先报告后阻断,并保持附件下载独立沙箱。 | 本地配置检查确认当前未启用全站策略;不据此推断单独的可利用路径。 |
|
||||
| `BSR-UX-001` | 页面能力显隐 | P2(收敛校准) | 高 | `DUPLICATE` | `research/page-static-review.md`、活动任务 `05-31-unified-page-header-actions` | 后端正确拒绝但页面仍展示写操作会误导用户并造成表单后失败。 | 前端能力显隐与后端拒绝测试采用同一权限合同;后端始终保持权威。 | 只读跨层复核确认重复 finding;统一降为 P2,不作为新的下游 task。 |
|
||||
|
||||
## 当前状态说明
|
||||
|
||||
- `BSR-SEC-001`、`BSR-SEC-002` 保留发现时 P0 和 `CONFIRMED`;当前修复状态统一为 `LOCAL_FIX_VERIFIED`,部署状态为 `DEPLOYMENT_PENDING`,外部验证为 `EXTERNAL_BEHAVIOR_PENDING`。
|
||||
- 其他 finding 没有在本审查任务中实施业务修复;其当前状态和去重关系只在唯一台账维护。
|
||||
- 付款、权限、附件和客户端生命周期涉及状态机、数据范围或隐私边界,后续实施完成后必须进行独立只读复核。
|
||||
|
||||
## 后续工作包映射
|
||||
|
||||
Gate 0:`BSR-SEC-001`、`BSR-SEC-002` 的部署和外部行为复核须另行授权;获准后优先于下面六个本地开放问题工作包,且不会因本任务归档而视为完成。
|
||||
|
||||
1. 员工敏感数据范围授权:`BSR-AUTHZ-001`。
|
||||
2. 付款状态一致性与审计:`BSR-DATA-001`、`BSR-DATA-002`。
|
||||
3. 员工合同附件权限与访问审计:`BSR-PRIV-001`。
|
||||
4. 发布门禁可信化:由工程 finding 承接,不在本文件扩写。
|
||||
5. 客户端数据生命周期与统一导出:`BSR-PRIV-002`、`BSR-SEC-003`,并评估 `BSR-SEC-004`。
|
||||
6. 核心页面可靠性、权限显隐及旧标题任务收口:本文件映射 `BSR-UX-001`,页面 P1/P2 内部顺序见唯一台账。
|
||||
|
||||
部署、公网角色、真实边缘日志、企业微信真机、历史真实资料治理和新 Day 1 试运行均保持另行授权;本任务不创建对应下游 task。
|
||||
@@ -0,0 +1,65 @@
|
||||
# 当前 HEAD 增量复核
|
||||
|
||||
## 基线与范围
|
||||
|
||||
- 原发现基线:`bbb5c89825b0fbee60d5f093d7b30368cb7a5104`(简称 `bbb5c89`)。
|
||||
- 本次收敛复核目标:`8f8606c328c4754901e045c34b071ecd36215bd3`(简称 `8f8606c`)。
|
||||
- 原 `research/baseline.md` 保持历史事实,不改写为当前 HEAD 证据。
|
||||
- 本次只检查本地代码、任务材料、合成数据和无凭据门禁;未访问公网、生产数据库、真实业务资料或外部写入能力。
|
||||
|
||||
## 提交分类
|
||||
|
||||
`bbb5c89..8f8606c` 共 4 个提交:
|
||||
|
||||
| 提交 | 分类 | 结论 |
|
||||
| --- | --- | --- |
|
||||
| `6ddedf1` | 认证安全修复 | 收敛认证挑战、并发和可信代理边界。 |
|
||||
| `4c5eb7e` | 认证任务归档 | 归档本地修复与验证证据。 |
|
||||
| `f424492` | 采购附件安全修复 | 收敛上传内容验证、下载授权/审计和浏览器隔离边界。 |
|
||||
| `8f8606c` | 采购附件任务归档 | 归档本地修复与验证证据。 |
|
||||
|
||||
累计影响 47 个文件,按职责分为 Trellis spec、归档任务材料、客户端适配、部署合同、QA runner、服务端/迁移/测试。该范围没有其他 finding 的完整修复证据,因此其余开放项不能因 HEAD 前移而自动标记为已解决。采购附件任务同时关闭了该模块原有的 URL 下载凭证分支;`DATA-DOWNLOAD-001` 已收窄为当前仍存在的其他业务下载链,而不是继续引用已修分支。
|
||||
|
||||
## 两个原 P0 的当前状态
|
||||
|
||||
| 原 finding | 本地修复证据 | 修复状态 | 部署状态 | 外部验证 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `BSR-SEC-001` | `6ddedf1`、归档任务 `07-17-auth-challenge-trusted-proxy-hardening`;聚焦负路径、完整服务端和隔离并发验证通过。 | `LOCAL_FIX_VERIFIED` | `DEPLOYMENT_PENDING` | `EXTERNAL_BEHAVIOR_PENDING` |
|
||||
| `BSR-SEC-002` | `f424492`、归档任务 `07-17-purchase-attachment-xss-hardening`;策略/路由、完整服务端和聚焦浏览器验证通过。 | `LOCAL_FIX_VERIFIED` | `DEPLOYMENT_PENDING` | `EXTERNAL_BEHAVIOR_PENDING` |
|
||||
|
||||
以上状态不表示当前公网来源已变化。最后有证据的公网来源仍是 `df26922`,且本轮没有获得部署、边缘响应、真实历史资料或公网角色复核授权。
|
||||
|
||||
## 收敛前只读门禁快照
|
||||
|
||||
| 检查 | 结果 | 解释 |
|
||||
| --- | --- | --- |
|
||||
| 当前 task validate | PASS | 命令可执行;占位上下文随后已替换为真实 spec/research 引用。 |
|
||||
| Trellis governance | PASS | 当前两个活动 task 合同可识别。 |
|
||||
| 敏感内容扫描 | PASS | 当前事实源扫描无 finding。 |
|
||||
| 文档 registry 审计 | PASS with known warning | 0 error;保留既有未登记文档 warning。 |
|
||||
| Playwright `--list` | PASS | 144 tests / 56 files;只证明资产可解析,不代表行为通过。 |
|
||||
| 移动路由静态合同 | FAIL with finding | 共享归档页组件不符合脚本命名/挂载规则;该结果本身不直接认定产品页面缺陷。后续浏览器量测独立确认长详情裁切为 P2。 |
|
||||
| 流程覆盖扫描 | COMMAND PASS / EVIDENCE UNTRUSTED | 68 条路由中 39 条未映射仍未形成 gap,且覆盖来源混入默认不执行的 manual 资产。 |
|
||||
|
||||
## 最终本地收口门禁
|
||||
|
||||
| 检查 | 结果 | 当前 HEAD 结论 |
|
||||
| --- | --- | --- |
|
||||
| `bash scripts/check-minimal.sh` | PASS | Prisma、服务端静态检查、157/157 测试文件与 896/896 用例、前端 typecheck/build、功能矩阵均通过。首次受限执行中两个需要子进程/本地 stub 的测试因 `EPERM` 失败;在允许本地子进程但仍无公网/生产访问的同一命令下全量通过,归类为环境限制。 |
|
||||
| 当前 task validate | PASS | `implement.jsonl`、`check.jsonl` 各 4 条真实上下文。 |
|
||||
| Trellis governance | PASS | 2 个活动 task 合同有效,无 warning/error。 |
|
||||
| 敏感内容扫描 | PASS | 30 个当前事实源文件,0 finding。 |
|
||||
| 文档 registry 审计 | PASS with known warning | 0 error;22 个既有未登记 docs 文件形成 1 条 warning。 |
|
||||
| Playwright `--list` | PASS | 144 tests / 56 files;只证明可解析。 |
|
||||
| 移动路由静态合同 | EXPECTED FAIL | 1 条共享组件挂载 finding;浏览器行为另确认 `MOB-ARCHIVE-001` 为 P2,不把命名规则直接当产品结论。 |
|
||||
| 流程覆盖扫描 | COMMAND PASS / EVIDENCE UNTRUSTED | 68 条路由中 39 条未映射仍未形成 gap,52 条路由的证据引用 manual 资产;保留 `REL-GATE-001`。 |
|
||||
| `git diff --check` | PASS | 无空白/补丁格式错误。 |
|
||||
|
||||
## 浏览器增量结论
|
||||
|
||||
- 375×812:归档页 URL、H1、空态、移动卡片、角色范围和底栏通过;长详情内部 351/457px,约 105px 内容被隐藏,定为 P2 `MOB-ARCHIVE-001`。
|
||||
- 768×1024:共享表格容器 702/760px、隐藏 58px;五页中四页右侧操作不可达。
|
||||
- 1024×768:共享表格容器 654/760px、隐藏 106px;五页右侧操作均不可达,定为 P1 `RESP-TABLE-001`。
|
||||
- 所有浏览器数据为本地合成 fixture,外部请求、未知 API、console/page error 均为 0;真机企业微信仍为 `EXTERNAL_GATED`。
|
||||
|
||||
收口目标 HEAD 在所有证据生成期间保持 `8f8606c`。若工作提交前业务 HEAD 发生变化,必须扩大 delta 并重跑,不复用本页 PASS;收口文档自身的后续提交不改变被审查的业务代码基线。
|
||||
@@ -0,0 +1,80 @@
|
||||
# 工程、测试、性能与运维审查
|
||||
|
||||
> 本文件保留原发现基线的分域证据。当前 HEAD 增量、唯一分级和生命周期状态
|
||||
> 分别以 `research/current-head-delta.md` 与 `research/findings.md` 为准。
|
||||
|
||||
## 测试资产与实测覆盖率
|
||||
|
||||
- 后端:153 个 Vitest 文件、786 个用例;普通回归与 V8 coverage 运行均为 153/153、786/786 PASS。
|
||||
- coverage 实跑耗时 196.80 秒;统计范围为 198 个源码文件,lines/statements `57.34%`、functions `71.03%`、branches `57.93%`。
|
||||
- 前端:Playwright 默认清单为 144 tests / 56 files;`client/src` 没有独立 unit/component spec,纯函数和组件合同主要依赖 TypeScript、静态门禁与 E2E 间接覆盖。
|
||||
- `server/vitest.config.cjs` 配置 coverage 报告,但没有最低阈值;因此 `npm run test:coverage` 即使整体或关键目录覆盖下降也不会失败。
|
||||
- 低覆盖集中在作业编排、部分管理/财务 route 和运行脚本。例如 delegation revoke、invoice archive、integration outbox、ERP master-data sync 等 job 的 lines 覆盖约 `6%–13%`;`src/index.js`、`src/worker.js` 及多项生产运维脚本为 0%。这不说明实现错误,但说明“全部用例通过”不能覆盖启动、调度与恢复行为。
|
||||
|
||||
### 候选 finding:测试通过不等于核心运行面已覆盖
|
||||
|
||||
- 建议级别:P2 / `CONFIRMED`。
|
||||
- 影响:回归能够发现大量 route/service 逻辑问题,但无法通过阈值防止覆盖率缓慢退化;作业入口和运维脚本的回归更多依赖 mock/手册,生产调度错误可能较晚暴露。
|
||||
- 建议:按风险设分层阈值而非一次追求全仓高数字;优先给认证恢复、资金状态、worker/job 注册、迁移/备份脚本设置关键文件阈值和负路径测试。前端先为权限显隐、路由映射和共享页面模板补小型 unit/component 合同,不必把所有页面复制成 unit spec。
|
||||
|
||||
## 流程覆盖扫描可信度
|
||||
|
||||
执行 `node scripts/qa/check-flow-coverage.mjs --json`:
|
||||
|
||||
- 报告摘要为 68 条前端路由、5 个业务域、68 个后端 route 文件、`highRiskGapCount=0`。
|
||||
- 实际 68 条前端路由中只有 29 条映射到业务域,39 条标为 `unmapped`;未映射包括合同、项目、资产、票据、付款、差旅、人员及绝大多数 `/system/*` 页面。
|
||||
- 矩阵使用 `/system/*`,而 `routeTokenMatches` 只处理完全相等、参数路由或 path prefix,不实现 `*` 通配,因此整组系统页面无法映射。
|
||||
- `specMatchesRoute` 在精确路径之外使用整个业务域的宽泛关键词;认证域含 `login` / `mobile` 等高频词,导致每条认证/移动路由都被匹配到全部 63 个 spec,并全部显示 WeCom、visual、flow 已覆盖。
|
||||
- 扫描还把默认 Playwright 配置会排除的 `manual/` live spec 纳入覆盖证据。
|
||||
- `scripts/qa/run-release-gate.sh` 生成该报告时没有传 `--fail-on-gaps`;即使扫描识别出缺口也只写报告,不阻断门禁。
|
||||
|
||||
### 候选 finding:覆盖扫描产生系统性假阳性
|
||||
|
||||
- 建议级别:P1 / `CONFIRMED`。
|
||||
- 影响:项目级发布证据可以在 39 条路由未映射、单路由无直接断言时仍显示“P0 缺口 0”;这会掩盖权限、视觉和业务流的真实测试缺口。
|
||||
- 建议:要求所有受支持路由显式映射;实现 `*` 语义;只认精确 route/test manifest 或测试内结构化标签,不以业务域关键词推断;默认排除 manual/live;发布门禁在 unmapped 或 P0 缺口时失败。
|
||||
|
||||
## 项目级发布门禁可执行性
|
||||
|
||||
`scripts/qa/run-release-gate.sh project-wide` 的静态阶段存在当前环境可确认的阻断:
|
||||
|
||||
- 第 88–89 行固定要求历史 `issues/2026-05-08_23-38-37-project-wide-qa-second-pass.csv`。
|
||||
- 校验器硬编码为用户目录下旧 `plan` skill 的绝对路径;当前机器该文件不存在。
|
||||
- 因为脚本启用 `set -euo pipefail`,执行到该行会直接退出,后续 UI、移动路由、流程覆盖、迁移诊断和浏览器门禁均不会运行。
|
||||
- 这也与当前 Trellis-first / Trellis-only 入口冲突:历史 Issue CSV 可以保留审计,但不应重新成为新发布门禁的隐含执行合同。
|
||||
|
||||
### 候选 finding:项目级发布门禁依赖已不存在的个人工具
|
||||
|
||||
- 建议级别:P1 / `CONFIRMED`。
|
||||
- 影响:当前 checkout 无法从仓库自身执行标准 `project-wide` 门禁,在新机器/CI 上同样不可移植,容易迫使发布者绕过标准路径。
|
||||
- 建议:删除历史 Issue/外部 skill 前置,改为仓库内 Trellis governance + 当前 task validate;需要 CSV 导出时使用仓库内受控脚本并作为显式可选步骤。
|
||||
|
||||
## 依赖与供应链边界
|
||||
|
||||
- `npm ls --depth=0 --json`:server 35 个直接依赖、client 26 个直接依赖,均 exit 0 且无 missing/invalid/extraneous problem。
|
||||
- 按当前无公网边界未执行 `npm audit`,因此不能声称不存在已知 CVE。上线 checklist 要求 `npm audit --omit=dev --audit-level=high`;当前结论为 `EXTERNAL_GATED`,准入条件是允许访问 npm advisory registry 并记录锁文件对应结果。
|
||||
- 运行中仍出现 Node `punycode` 弃用提示;属于依赖维护观察项,尚无证据证明影响业务。
|
||||
|
||||
## 前端构建与性能观察
|
||||
|
||||
- production build 总体约 2.8 MiB、94 个 asset 文件,页面主体采用 `React.lazy` 拆分。
|
||||
- `index.html` 初始 preload 包含 React、Query、UI、app-core、app-domain-shared;最大扫码依赖 chunk `vendor-scan` 约 411 KiB,但未被首页 HTML preload,按路由延迟加载。
|
||||
- 初始入口相关的未压缩 JS/CSS 约为:entry 127 KiB、React 166 KiB、UI 145 KiB、Query 41 KiB、app-core 72 KiB、app-domain-shared(较小)以及 CSS 89 KiB;另有 Material Symbols 字体约 479 KiB。当前没有基于网络/设备的 LCP、INP 或内存实测,不能据体积直接判定性能故障。
|
||||
- Topbar 和移动底栏各 30 秒轮询通知;OCR pending 时 3 秒轮询。代码证据表明 OCR 轮询按 pending 条件关闭,暂无“永久 3 秒轮询”证据。
|
||||
|
||||
### 性能结论
|
||||
|
||||
- 当前无 P0/P1 性能 finding。
|
||||
- P2 观察:建立 build budget 和低端移动网络测量,重点关注图标字体、初始 UI chunk、通知双入口轮询以及 OCR 多页面重复查询;先测量再优化。
|
||||
|
||||
## 运维、迁移与恢复
|
||||
|
||||
- 部署合同具备 Docker healthcheck、`/ready`、完整后端 SHA / 12 位前端 SHA、init migration、runtime smoke、external-deps smoke、live readiness、DB + 文件存储备份/恢复脚本和回滚手册。
|
||||
- 仓库内确有 `scripts/backup-db.sh`、`backup-storage.sh`、`restore-db.sh`、`restore-storage.sh`;运行手册引用不是悬空命令。
|
||||
- Prisma schema validate 通过;共有 58 个迁移目录。本任务未连接数据库,`migrate status` / drift、恢复演练和公网 source provenance 均为 `EXTERNAL_GATED`。
|
||||
- 旧 7 日试运行只完成 Day 1–Day 4;当前本地 commit 未部署。因此恢复、真实调度、告警和公网 readiness 只能报告“合同存在、行为待外部补证”,不能记为 PASS。
|
||||
|
||||
## 本轮生成物
|
||||
|
||||
- `server/coverage/` 由本轮 coverage 运行生成且被忽略,最终汇总取证后删除。
|
||||
- 不删除历史 `artifacts/` 或其他任务的证据。
|
||||
|
之后 宽度: | 高度: | 大小: 91 KiB |
|
之后 宽度: | 高度: | 大小: 92 KiB |
|
之后 宽度: | 高度: | 大小: 70 KiB |
|
之后 宽度: | 高度: | 大小: 85 KiB |
|
之后 宽度: | 高度: | 大小: 88 KiB |
|
之后 宽度: | 高度: | 大小: 71 KiB |
|
之后 宽度: | 高度: | 大小: 74 KiB |
|
之后 宽度: | 高度: | 大小: 51 KiB |
|
之后 宽度: | 高度: | 大小: 65 KiB |
|
之后 宽度: | 高度: | 大小: 69 KiB |
|
之后 宽度: | 高度: | 大小: 71 KiB |
|
之后 宽度: | 高度: | 大小: 64 KiB |
|
之后 宽度: | 高度: | 大小: 61 KiB |
|
之后 宽度: | 高度: | 大小: 70 KiB |
|
之后 宽度: | 高度: | 大小: 65 KiB |
|
之后 宽度: | 高度: | 大小: 70 KiB |
@@ -0,0 +1,68 @@
|
||||
# 多维系统审查唯一 Finding 台账
|
||||
|
||||
## 台账口径
|
||||
|
||||
- 本文件是当前任务唯一的分级与生命周期事实源。分域报告保留发现证据,但不再各自决定当前严重度或状态。
|
||||
- 发现基线为 `bbb5c89`;当前本地增量目标为 `8f8606c`。发现时严重度不因后续修复而改写,收敛校准会在单元格中显式注明。
|
||||
- 发现状态、当前修复状态、部署状态、外部验证状态彼此独立。
|
||||
- `NO_FIX_TO_DEPLOY` 表示尚无修复产物,不等于待部署;`NOT_APPLICABLE` 仅用于非运行时代码/纯测试合同。
|
||||
- `ACTIVE_TASK_OPEN` 表示该项仍开放但已由现有活动 task 承载;本轮只做去重,不另建 task。`FOLLOW_UP_RECOMMENDED` 表示持续治理建议,不是已修复。
|
||||
- 证据和验证只保留防御性结论。安全工程细节由聚焦测试和已归档修复任务承载。
|
||||
|
||||
## 唯一台账
|
||||
|
||||
| ID | 维度 | 发现时严重度 | 置信度 | 发现状态 | 当前修复状态 | 部署状态 | 外部验证状态 | 证据引用 | 业务影响 | 控制目标 | 无害验证 | 后续工作包 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `SEC-AUTH-001` | 认证 / 代理信任 | P0 | 高 | `CONFIRMED` | `LOCAL_FIX_VERIFIED` | `DEPLOYMENT_PENDING` | `EXTERNAL_BEHAVIOR_PENDING` | `business-security-review.md#bsr-sec-001`;归档任务 `07-17-auth-challenge-trusted-proxy-hardening` | 认证边界不足可能导致账号被未授权控制。 | 挑战单次有效、并发一致、来源可信且可审计。 | 当前 HEAD 聚焦负路径、完整服务端与隔离并发验证通过。 | 另行授权:部署与公网复核 |
|
||||
| `SEC-ATT-001` | 业务附件 / 浏览器隔离 | P0 | 高 | `CONFIRMED` | `LOCAL_FIX_VERIFIED` | `DEPLOYMENT_PENDING` | `EXTERNAL_BEHAVIOR_PENDING` | `business-security-review.md#bsr-sec-002`;归档任务 `07-17-purchase-attachment-xss-hardening` | 主动内容可能破坏 OA 同源会话与业务数据边界。 | 实际内容验证、重新授权/审计、非执行下载。 | 当前 HEAD 策略/路由、完整服务端与聚焦浏览器验证通过。 | 另行授权:部署与公网复核 |
|
||||
| `DATA-EMP-001` | 员工敏感数据授权 | P1 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `EXTERNAL_BEHAVIOR_PENDING` | `business-security-review.md#bsr-authz-001` | 广泛能力可能读取超出岗位需要的员工敏感字段。 | 字段级授权与人员范围同时最小化。 | 只读跨层检查确认权限粒度不足,未读取真实资料。 | WP-1 员工敏感数据范围授权 |
|
||||
| `PAY-STATE-001` | 付款状态机 / 并发 | P1 | 高 | `LIKELY` | `OPEN` | `NO_FIX_TO_DEPLOY` | `EXTERNAL_BEHAVIOR_PENDING` | `business-security-review.md#bsr-data-001` | 并发状态变化可能造成重复结果或证据覆盖。 | 条件更新/锁、幂等和不可覆盖审计保证单一结果。 | 静态事务检查发现保护证据不足,未连接数据库或执行付款。 | WP-2 付款状态一致性与审计 |
|
||||
| `DATA-HR-ATT-001` | 员工合同附件 | P1 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `EXTERNAL_BEHAVIOR_PENDING` | `business-security-review.md#bsr-priv-001` | 高敏合同资料可能受过宽权限控制且缺访问用途审计。 | 独立最小权限、对象级授权、安全 DTO 和下载审计。 | 只读路由/测试合同确认缺口,未读取真实合同。 | WP-3 员工合同附件权限与访问审计 |
|
||||
| `DATA-EXPORT-001` | 统一导出 | P1 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `business-security-review.md#bsr-sec-003` | 导出内容可能在表格软件中形成非预期活动行为。 | 全部 CSV/表格出口统一安全编码并有合成负例。 | 静态检查确认缺少统一中和合同,未使用真实导出。 | WP-5 客户端数据生命周期与统一导出 |
|
||||
| `PRIV-OFFLINE-001` | 客户端数据生命周期 | P1 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `EXTERNAL_BEHAVIOR_PENDING` | `business-security-review.md#bsr-priv-002` | 退出或换账号后残留身份、审批或草稿可能被后续使用者读取。 | 先确认离线必要性,再按账号隔离、最小缓存并可靠清除。 | 静态检查确认持久化和清理未闭合,未检查真实设备。 | WP-5 客户端数据生命周期与统一导出 |
|
||||
| `DATA-DOWNLOAD-001` | 下载凭证 / 日志面 | P2 | 中高 | `LIKELY` | `OPEN` | `NO_FIX_TO_DEPLOY` | `EXTERNAL_GATED` | `business-security-review.md#bsr-sec-004` | 短期访问凭据可能进入常规浏览器或边缘记录面。 | 使用当前认证上下文下载并最小化 URL、日志和缓存暴露。 | 代码存在风险可能性;真实边缘日志未获授权检查。 | WP-5 客户端数据生命周期与统一导出 |
|
||||
| `DATA-ACL-001` | 受限资料规则 | P2 | 中高 | `LIKELY` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `business-security-review.md#bsr-authz-002` | 已保存但未执行的规则会造成受限资料边界误判。 | 产品明确其为 ACL 或废弃元数据;保留则由后端强制执行。 | 静态检查确认规则与执行证据不一致。 | WP-5 客户端数据生命周期与统一导出 |
|
||||
| `PAY-AUDIT-001` | 付款取消审计 | P2 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `business-security-review.md#bsr-data-002` | 取消责任与前后状态难以完整还原。 | 记录原因、操作者、前后状态与并发条件。 | 静态路由/模型检查确认缺口,未执行真实状态变化。 | WP-2 付款状态一致性与审计 |
|
||||
| `WEB-DEFENSE-001` | 浏览器防御纵深 | P2 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `EXTERNAL_BEHAVIOR_PENDING` | `business-security-review.md#bsr-sec-005` | 缺少内容执行限制会降低未知缺陷的纵深保护。 | 基于资源清单分阶段收紧 CSP 并保持附件独立沙箱。 | 本地配置确认当前未启用全站策略;未推断具体利用路径。 | WP-5 客户端数据生命周期与统一导出 |
|
||||
| `UI-PERM-001` | PC 写动作显隐 | P2(收敛校准;原分域报告 P1/P2 不一) | 高 | `CONFIRMED` | `ACTIVE_TASK_OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#既有-finding-复核与去重`;`BSR-UX-001`;活动任务 `05-31-unified-page-header-actions` | 后端虽拒绝写入,PC 用户仍可能进入最终失败的流程。 | PC 显隐与后端拒绝共享同一能力合同,后端保持权威。 | 付款、合同、票据三处既有 PC finding 完成只读去重;移动导航由 `MOB-PERM-001` 单列。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `PAY-UX-001` | 付款业务可用性 | P1 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p1-001` | 财务人员难以凭业务信息选择待付对象,可能错选或无法创建。 | 以待付池和业务编号/人员/金额选择对象,内部标识仅由系统传递。 | 静态页面与 E2E 合同确认普通流程依赖内部标识。 | WP-2 付款状态一致性与审计 |
|
||||
| `UX-SAFE-001` | 不可逆证据 / 资金动作 | P1(收敛后边界) | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p1-002` | 误触可能删除不可逆证据或改变资金结果。 | 强确认展示对象、后果、可逆性与必要理由。 | 静态检查确认代表性高影响动作在 mutation 前缺少强确认。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `UX-SAFE-002` | 可恢复管理动作 | P2(由原 PAGE-P1-002 拆分校准) | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p1-002` | 普通启停等可恢复动作存在误触和反馈不清。 | 使用轻确认或可撤销反馈,按可逆性分级。 | 只读检查确认部分可恢复动作仍直接执行。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `UX-FORM-001` | 核心长表单可靠性 | P1 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p1-003` | 采购、报销、合同、资产等长输入可能因离开页面丢失。 | 共享 dirty-state 合同覆盖路由离开、刷新和记录切换。 | 静态检查未找到未保存保护实现。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `MOB-ATTEND-001` | 移动考勤入口 | P1(由原 PAGE-P1-004 拆分) | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `EXTERNAL_BEHAVIOR_PENDING` | `page-static-review.md#page-p1-004` | 企业微信/触控小屏考勤入口会回到原移动首页。 | 提供明确移动镜像或允许只读响应式页,不形成自循环。 | 静态路由解析确认自循环;真机点击待另行授权。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `MOB-TARGET-001` | 移动通知定位 | P2(由原 PAGE-P1-004 拆分校准) | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `EXTERNAL_BEHAVIOR_PENDING` | `page-static-review.md#page-p1-004` | 部分通知不能定位原业务对象,用户需重新查找。 | 每种通知保留稳定对象标识并验证最终 URL/内容。 | 静态链接映射确认目标参数不完整;真实通知待授权。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `SEARCH-NAV-001` | 全局搜索导航 | P2(收敛校准;原报告 P1) | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p1-005` | 点击部分搜索结果只到列表,不能确认命中对象。 | 对象型结果提供稳定详情或定位/高亮合同。 | 静态 href 与现有单实体 E2E 确认覆盖不完整。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `RESP-TABLE-001` | 中间断点表格 | P1 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p1-006`;`browser-review.md` | 共享表格隐藏超出宽度,多个核心列表的右侧操作不可达。 | 操作列可见或容器可控横滚,页面本身不溢出。 | 768 下容器缺 58px、1024 下缺 106px 且 `overflow-x:hidden`;代表页面操作命中失败。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `A11Y-FORM-001` | 表单可访问性 | P2(收敛校准;原报告 P1) | 高 | `CONFIRMED` | `FOLLOW_UP_RECOMMENDED` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p1-007` | 辅助技术用户较难识别字段和动态错误。 | 共享字段/错误组件提供名称、关联、错误状态和 live feedback。 | 静态样例确认语义缺口;无行为证据证明核心流程完全不可完成。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `NAV-META-001` | 路由 / 标题元数据 | P2 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p2-001` | 标题、最近访问和浏览器 tab 语义漂移。 | 统一 typed route manifest 与页面可控覆写。 | 静态映射确认缺失、误匹配与固定浏览器标题。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `ERR-RECOVERY-001` | 错误恢复 | P2 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p2-002` | 403/404/渲染错误可能把用户带向隐藏旧入口。 | 所有恢复动作回到稳定工作台或安全上一页。 | 静态链接确认仍指向旧路径。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `SCOPE-TRAVEL-001` | 冻结能力范围 | P2 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p2-003` | 冻结差旅仍占用付款、通知与审批认知空间。 | 用户可见入口按启用状态显式隐藏或标为只读兼容。 | 静态入口清单确认非差旅页面仍暴露选项。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `UX-ERROR-001` | 普通页面错误文案 | P2 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p2-004` | 用户先看到内部码/枚举,难以理解原因与下一步。 | 普通界面展示自然语言和恢复动作,诊断码仅进受控区域。 | 静态样例确认普通页面直接组合技术信息。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `A11Y-TABLE-001` | 表格键盘可达 | P2 | 高 | `CONFIRMED` | `FOLLOW_UP_RECOMMENDED` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p2-005` | 键盘用户无法等价选择部分表格记录。 | 使用真实按钮/链接和明确选中状态。 | 静态样例确认行点击缺少键盘等价入口。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `A11Y-VISUAL-001` | 对比度 / 减弱动效 | P2 | 高 | `CONFIRMED` | `FOLLOW_UP_RECOMMENDED` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p2-006` | 低视力与减弱动效用户体验下降。 | 共享 token 达到既定对比度并尊重 reduced motion。 | 静态 token/样式检查确认当前合同不足。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `QA-VISUAL-001` | 视觉证据可信度 | P2 | 高 | `CONFIRMED` | `OPEN` | `NOT_APPLICABLE` | `NOT_REQUIRED` | `page-static-review.md#page-p2-007` | 报告可能遗漏真实路由/中间断点却给出过强信心。 | 显式路由计划、最终 URL/标题/错误页断言和代表断点。 | 静态矩阵确认通配、旧路由和断点缺口。 | WP-4 发布门禁可信化 |
|
||||
| `MOB-PERM-001` | 移动导航权限 | P2 | 中高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `NOT_REQUIRED` | `page-static-review.md#page-p2-008` | 最小权限角色看到无效入口或进入 403。 | 移动入口统一复用能力谓词,未授权默认隐藏。 | 静态导航与守卫对照确认不一致。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `QA-ASSET-001` | 资产 E2E 漂移 | P2 | 高 | `DUPLICATE` | `ACTIVE_TASK_OPEN` | `NOT_APPLICABLE` | `NOT_REQUIRED` | `page-static-review.md#page-dup-p2-001`;活动任务 `05-31-unified-page-header-actions` | 自动化仍按旧交互执行,不能证明当前页面。 | 测试跟随当前“更多”菜单交互,不为旧测试恢复旧按钮。 | 只读测试/页面对照确认重复项。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `QA-HEADER-001` | 标题动作合同 / 视觉覆盖 | P2 | 高 | `DUPLICATE` | `ACTIVE_TASK_OPEN` | `NOT_APPLICABLE` | `NOT_REQUIRED` | `page-static-review.md#page-dup-p2-002`;活动任务 `05-31-unified-page-header-actions` | 标题区可能继续堆叠动作且现有回归不报警。 | 可测试的主操作/更多槽位及项目、资产代表性视觉断言。 | 静态组件与测试矩阵确认重复项。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
| `QA-COVERAGE-001` | 风险型测试覆盖 | P2 | 高 | `CONFIRMED` | `OPEN` | `NOT_APPLICABLE` | `NOT_REQUIRED` | `engineering-review.md#测试资产与实测覆盖率` | 全量用例通过仍不能防止关键 worker/脚本覆盖退化。 | 对认证、资金、worker、迁移/恢复入口设置分层防回退门禁。 | 旧基线 coverage 与入口清单确认关键运行面无阈值。 | WP-4 发布门禁可信化 |
|
||||
| `REL-GATE-001` | 发布门禁可信度 | P1 | 高 | `CONFIRMED` | `OPEN` | `NOT_APPLICABLE` | `NOT_REQUIRED` | `engineering-review.md#流程覆盖扫描可信度`、`#项目级发布门禁可执行性`;`current-head-delta.md` | 标准门禁不可移植且会把大量未映射路由报告成无高风险缺口。 | 仓库内可执行、显式映射/豁免、排除 manual/live、缺口非零退出并自测反例。 | 当前 HEAD 扫描 68 路由仍有 39 未映射却无 gap;标准 runner 依赖失效外部前置。 | WP-4 发布门禁可信化 |
|
||||
| `MOB-ARCHIVE-001` | 移动归档详情响应式 | P2 | 高 | `CONFIRMED` | `OPEN` | `NO_FIX_TO_DEPLOY` | `EXTERNAL_BEHAVIOR_PENDING` | `baseline.md#移动路由静态合同`;`browser-review.md` | 长标识使详情内部内容被隐藏,用户无法横向找回。 | 保持路由/卡片/底栏基线并让详情长字段安全换行或可控滚动。 | 375×812 的 URL、H1、空态、列表和底栏通过;长详情 panel 351/457,约 105px 被 `overflow-x:hidden` 裁切。 | WP-6 页面权限显隐及旧标题任务收口 |
|
||||
|
||||
## 不进入 Finding 的观察与外部补证
|
||||
|
||||
- 构建体积、通知轮询、工具链弃用提示目前没有行为故障证据,保留为观察项,不进入台账。
|
||||
- 依赖在线审计、数据库迁移状态、备份恢复演练、公网来源、真实角色矩阵、企业微信真机、真实 OCR、真实付款和连续试运行属于外部补证边界,不伪装成产品 finding。
|
||||
- 外部补证不阻塞本只读审查任务归档,但会阻塞“已部署”“可公网测试”或“真实业务通过”的对外结论。
|
||||
|
||||
## 推荐工作包顺序
|
||||
|
||||
Gate 0:两个已本地修复 P0 的部署与外部行为复核必须另行授权,并在获准后优先完成;它不被下面六个“本地开放问题”工作包的顺序替代。
|
||||
|
||||
1. WP-1 员工敏感数据范围授权。
|
||||
2. WP-2 付款状态一致性与审计。
|
||||
3. WP-3 员工合同附件权限与访问审计。
|
||||
4. WP-4 发布门禁可信化。
|
||||
5. WP-5 客户端数据生命周期与统一导出。
|
||||
6. WP-6 核心页面可靠性、权限显隐及旧标题任务收口。它只是管理伞,不应一次形成 19 项巨型实施任务:先处理 `UX-SAFE-001`、`UX-FORM-001`、`MOB-ATTEND-001`、`RESP-TABLE-001` 四条 P1,再收口页面权限显隐和现有 `05-31` 任务;其余 P2 按触达持续治理。
|
||||
|
||||
本任务只登记顺序,不创建下游 Trellis task。部署、公网角色、企微真机和新 Day 1 试运行必须另行授权。
|
||||
@@ -0,0 +1,375 @@
|
||||
# 页面、信息架构与跨端静态审查
|
||||
|
||||
> 本文件保留 `bbb5c89` 分域静态审查的原始分级和证据,不再作为当前唯一台账。
|
||||
> 2026-07-17 的严重度校准、浏览器行为结论和四层状态以 `research/findings.md`
|
||||
> 与 `research/browser-review.md` 为准;不要直接汇总本文件中的旧 P1/P2 数量。
|
||||
|
||||
## 结论摘要
|
||||
|
||||
- 静态覆盖了 `client/src/pages/` 下 75 个 TSX 页面/页面子模块(约 4.15 万行)、`client/src/router/index.tsx` 的 76 个 `<Route>` 声明、PC/移动导航、全局壳、共享列表/详情/编辑模板,以及 63 个 Playwright spec 的路由与页面相关资产;对标题动作、移动路由、全局视觉、权限负例和既有 finding 对应 spec 做了重点抽读。
|
||||
- 本轮只读静态审查没有发现 P0。
|
||||
- 新增唯一 finding 为 **P1 7 条、P2 8 条**;其中 1 条 P1 因必须在 768/1024 浏览器中观察实际裁切而标为 `LIKELY`,其余为 `CONFIRMED`。
|
||||
- 从 `05-31-unified-page-header-actions` 复核出 **P1 3 条、P2 2 条**,全部保持 `DUPLICATE`,没有重复创建新问题。
|
||||
- 若把重复项也计入风险地图,当前页面维度合计为 **P0 0 / P1 10 / P2 10**;用于后续建修复 task 时,应以唯一新增的 **P0 0 / P1 7 / P2 8** 为准。
|
||||
- 本文件只代表当前本地代码静态结论;没有访问公网、真实数据或企业微信真机,也没有运行浏览器。真机 WebView 结论仍属外部准入。
|
||||
|
||||
| 状态 | P0 | P1 | P2 | 说明 |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `CONFIRMED`(新增) | 0 | 6 | 8 | 可由当前代码路径、DOM 结构或测试合同直接证明 |
|
||||
| `LIKELY`(新增) | 0 | 1 | 0 | 表格在 768/1024 的实际裁切需浏览器量测 |
|
||||
| `DUPLICATE`(既有) | 0 | 3 | 2 | 已登记在 `05-31-unified-page-header-actions` |
|
||||
|
||||
## 审查口径
|
||||
|
||||
1. 合同层:当前 PRD/design、`.trellis/spec/hyb-oa/frontend-react-vite-design.md`、`docs/产品设计规则.md`。
|
||||
2. 实现层:路由、导航、页面元数据、共享模板、页面状态与动作、移动/企微路由转换。
|
||||
3. 证据层:相关 E2E 的路由、视口、断言和覆盖矩阵;未用旧截图代替当前行为。
|
||||
4. `ui-ux-pro-max` 只用于补充表格响应式、表单可访问性、错误反馈、焦点、对比度和 `prefers-reduced-motion` 检查。其外部配色/风格建议不用于替换当前 OA 视觉基线。
|
||||
|
||||
## PC、移动与企业微信入口映射
|
||||
|
||||
### 路由资产
|
||||
|
||||
| 表面 | 路由族 | 页面/模板归属 | 当前跨端归属 |
|
||||
| --- | --- | --- | --- |
|
||||
| 认证与兜底 | `/login`、`/forgot-password`、`/change-password`、`/403`、`*` | `AuthLayout` 或独立全屏状态页 | 普通浏览器与企微共用;不进入 PC/移动业务壳 |
|
||||
| PC 工作台与协作 | `/portal`、`/announcements`、`/team`、`/weekly-reports`、`/todos`、`/dashboard`、`/notifications`、`/settings/profile` | 工作台、台账列表或个人设置 | 移动端分别映射首页、通知、个人设置;其余多折叠回移动首页 |
|
||||
| PC 业务台账 | `/reimbursements`、`/purchase-requests`、`/contracts-registry`、`/projects`、`/assets`、`/payment-batches`、`/ap-operations`、`/invoice-pool`、`/budgets`、`/inventory-checks`、`/travel-requests`、`/leave-requests`、`/attendance`、`/wecom-approval-archive` | `BusinessListTemplate`、页面本地台账或记录视图 | 报销、采购、请假、票据、资产/盘点有专用移动表达;项目、合同、付款/AP、预算、差旅等折叠回移动首页 |
|
||||
| PC 详情/处理 | `/projects/:projectId`、`/reimbursements/:reimbursementId`、`/reimbursements/:reimbursementId/print`、`/workflow/tasks/:taskId`,以及采购/资产/付款/票据的 `?id=` 模式 | `BusinessDetailTemplate`、`EntityOverviewHero` 或显式详情区 | 报销、审批、采购有移动详情;资产只映射扫码页;项目、合同和财务详情没有移动详情 |
|
||||
| PC 管理 | `/audit-logs`、`/delegations`、`/payroll`、`/performance`、`/organization`、`/people/**`、`/system/**` | 管理配置页、审计/排障页 | 小屏/企微统一折叠到 `/mobile/me`,不复制 PC 管理台 |
|
||||
| 移动工作台 | `/mobile`、`/mobile/me`、`/mobile/profile`、`/mobile/notifications`、`/mobile/wecom-approval-archive`、`/mobile/capture`、`/mobile/reimbursements/**`、`/mobile/leave/**`、`/mobile/purchase-requests/**`、`/mobile/assets/scan`、`/mobile/approvals/**` | 12 个 `Mobile*Page`,部分列表/详情复用同页 | 企业微信 WebView、钉钉容器或触控小屏优先进入该路由族 |
|
||||
|
||||
### 自动转换规则
|
||||
|
||||
- 精确映射:工作台/数据看板 → 移动首页;通知 → 移动通知;个人设置 → 移动个人设置;报销/审批/采购/请假 → 对应移动列表或详情;票据 → 移动上传;资产/盘点 → 移动扫码。
|
||||
- 管理映射:`/system*`、`/people*`、`/organization*`、`/payroll*`、`/performance*` → `/mobile/me`。
|
||||
- 折叠映射:项目、合同、差旅、付款、AP、周报、待办、团队、考勤、预算、公告、委派 → `/mobile`。
|
||||
- 触发条件:企业微信/钉钉 UA,或 `maxTouchPoints > 0` 且视口不大于 768px。真机企业微信仍需人工复核,普通桌面浏览器缩窄视口不能替代。
|
||||
- 移动底栏只固定 `首页 / 待办或进度 / 报销 / 我的`;请假、采购、通知和资产扫码从首页或“我的”进入。
|
||||
|
||||
### 当前设计中做得较好的部分
|
||||
|
||||
- PC 业务列表已普遍分离标题、命令栏、桌面表格和移动卡片;项目、资产、合同、付款、票据、采购和报销不再默认自动选择首条记录填充右侧详情。
|
||||
- 报销、审批、采购和请假已有独立移动列表/详情;移动壳处理了视觉视口高度、safe area、深层详情隐藏底栏等基础问题。
|
||||
- 请假/考勤页面总体明确“企微主办、OA 镜像/应急接管”,普通员工的 OA 日常请假表单已隐藏。
|
||||
- 审批 PC/移动详情的通过、退回和驳回都进入 `ConfirmDialog`,没有直接从按钮瞬时执行审批动作。
|
||||
- 共享 `BusinessDetailTemplate`、`BusinessEditTemplate`、空状态、骨架屏、状态徽标和确认弹窗已形成可继续治理的基础;问题主要是合同未覆盖权限、未保存、可访问性和响应式边界。
|
||||
|
||||
### `/mobile/wecom-approval-archive` 的 375px 专项静态预期
|
||||
|
||||
- 该移动路由并非独立移动页,而是直接复用 `WecomApprovalArchivePage`;路由允许具备 `leave.view_own` 或 `attendance.view_own` 的普通查看角色进入,并非仅 HR/管理员路径(`client/src/router/index.tsx:336`、`:338`、`:339`)。
|
||||
- 在 375px 下,四项筛选静态上应由 `md:grid-cols-4` 回落为单列;桌面表格由 `hidden ... md:block` 隐藏,`md:hidden` 的卡片列表显示;详情主栅格到 `lg` 才切三列,字段摘要和参与人/动作到 `md` 才切多列,因此静态结构预期为单列移动表达,而不是压缩的 PC 宽表(`client/src/pages/WecomApprovalArchivePage.tsx:176`、`:227`、`:246`、`:276`、`:297`、`:307`)。
|
||||
- 列表加载态虽然调用六列 `TableSkeleton`,但骨架只由可收缩的 `flex-1` 短条组成,没有 table 或 `min-width`;静态上不应制造横向滚动,不过六列在 375px 下是否显得过碎仍需截图判断(`client/src/pages/WecomApprovalArchivePage.tsx:218`;`client/src/components/common/TableSkeleton.tsx:11`、`:12`、`:18`)。
|
||||
- 该路由不属于移动深层详情,底栏会保持显示;移动壳已按底栏高度、页面纵向间距和 safe area 增加内容底部 padding,静态上末尾详情不应被遮挡(`client/src/layouts/AppShellLayout.tsx:15`、`:18`、`:71`、`:79`)。
|
||||
- 以上仅是 DOM/Tailwind 合同推导,不是浏览器 PASS。必须在 375px 实跑空态、加载态、有记录、打开详情、长文案和长人员名,量测页面 `scrollWidth`、末尾内容与底栏位置,并分别覆盖普通员工“与我相关”和 HR/管理员范围;真实企业微信 WebView 仍是外部准入。
|
||||
|
||||
## 新增 P1 Finding
|
||||
|
||||
### PAGE-P1-001:付款批次仍以“粘贴内部 ID”作为首屏主操作
|
||||
|
||||
- 维度:功能闭环 / 信息语义 / 财务页面。
|
||||
- 严重级别:P1。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`client/src/pages/PaymentBatchesPage.tsx:347`、`:356`、`:377`、`:403`;`client/tests/e2e/reimbursement-payment-batch-flow.spec.ts:107`;`.trellis/spec/hyb-oa/frontend-react-vite-design.md:777`;`docs/产品设计规则.md:110`。
|
||||
- 证据:付款页把 `新建批次`放在标题主操作区;创建面板要求用户输入“待付款单据 ID”,占位文案明确要求粘贴报销或差旅单据 ID。现有 E2E 只能先从 API 取得 `reimbursementId` 再填入。当前 spec 同时规定付款首屏应先展示待复核/待付款/异常,批次创建不应成为首屏主操作;普通路径不得要求 UUID/内部 ID。
|
||||
- 影响:真实财务用户通常只知道报销编号、人员、金额和付款状态,无法可靠取得 UUID;复制错误 ID 可能造成错批次、漏单或批次创建失败。当前自动化能跑通不代表人工可完成。
|
||||
- 确认方式:用付款管理员打开 `/payment-batches`,点击新建后确认只有 ID 文本框而没有待付候选列表;尝试输入业务编号验证是否无法完成。静态接口与 E2E 已证明当前合同使用内部 ID。
|
||||
- 建议:从 AP/待付池按业务编号、对象、人员、金额、证据状态提供可搜索多选;前端内部再提交 ID。批次创建进入待付列表的上下文动作或明确的角色工具,不作为普通首屏主 CTA。
|
||||
- 修复边界:付款页、待付候选查询/API、付款批次创建 E2E;不改变付款状态机或真实付款边界。
|
||||
- 是否需用户决策:是——确认以“应付账款待付池发起”还是“付款页候选选择器”为唯一主入口。
|
||||
|
||||
### PAGE-P1-002:危险动作确认合同没有系统性执行
|
||||
|
||||
- 维度:交互安全 / 证据链 / 管理操作。
|
||||
- 严重级别:P1。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`docs/产品设计规则.md:81`;`.trellis/spec/hyb-oa/frontend-react-vite-design.md:1189`;`client/src/pages/PurchaseRequestsPage.tsx:1630`;`client/src/pages/PaymentBatchesPage.tsx:595`;`client/src/pages/ReimbursementDetailPage.tsx:1537`;`client/src/pages/UserManagementPage.tsx:299`;`client/src/pages/PortalAnnouncementsPage.tsx:190`;`server/src/routes/reimbursements.js:2660`;`server/src/routes/paymentBatches.js:1062`。
|
||||
- 证据:采购附件、报销附件和付款回单的“删除”按钮直接调用 delete mutation;后端执行 `deleteMany`。用户禁用/启用、重置密码、公告停用/归档也从列表按钮直接 mutation,没有对象摘要、后果、理由或确认词。
|
||||
- 影响:一次误点即可删除财务/采购证据、使用户失去登录能力、停用制度公告或改变配置状态;即使后端记录审计,也不能代替前置防误触。
|
||||
- 确认方式:在本地 mock 数据中点击上述动作,确认 mutation 前没有 `action-confirm-dialog`;同时检查后端是否物理删除或可恢复。
|
||||
- 建议:把持久化附件删除、账号禁用/密码重置、公告发布/停用/归档等接入带类型的共享确认合同;至少展示业务编号/文件名/用户、影响、可逆性和必要理由。附件删除应明确是否物理删除、软删除或仅解除关联。
|
||||
- 修复边界:共享确认组件及上述核心页面/回归测试;不在页面任务中改变后端权限和审计语义。
|
||||
- 是否需用户决策:否——现行产品规则已经明确要求二次确认;仅删除/保留策略需要在具体修复 task 内确认。
|
||||
|
||||
### PAGE-P1-003:长表单没有未保存更改保护
|
||||
|
||||
- 维度:表单可靠性 / 数据丢失防护。
|
||||
- 严重级别:P1。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`.trellis/spec/hyb-oa/frontend-react-vite-design.md:920`;`client/src/components/patterns/BusinessEditTemplate.tsx:8`、`:35`;`client/src/pages/PurchaseRequestsPage.tsx:793`、`:809`;`client/src/pages/AssetRegistryPage.tsx:717`、`:732`;`client/src/pages/ContractsRegistryPage.tsx:410`。
|
||||
- 证据:全前端没有 `useBlocker`、`beforeunload`、dirty-state 或“未保存”实现。共享编辑模板的返回动作是直接 `<Link>`;采购、资产在包含大量字段/明细/材料的编辑状态下点击“返回列表”会直接清空详情/创建状态。
|
||||
- 影响:采购明细、资产建卡、合同登记、报销编辑等长表单可能因误点返回、侧栏跳转、浏览器返回或刷新而丢失尚未保存的输入,用户无法恢复。
|
||||
- 确认方式:分别在采购草稿、资产新建和合同编辑中修改字段但不保存,点击返回列表、侧栏或浏览器返回/刷新,观察没有离开确认且输入丢失。
|
||||
- 建议:新增共享 `useUnsavedChanges`/dirty 合同,覆盖路由离开、浏览器刷新、弹窗关闭和切换记录;保存成功后清除 dirty。先覆盖采购、报销、资产、合同,再覆盖管理长表单。
|
||||
- 修复边界:共享 hook/编辑模板与 A/B 类长表单;不把自动保存作为本轮默认扩张。
|
||||
- 是否需用户决策:否——保护原则已由 spec 明确;自动保存是否引入另行决定。
|
||||
|
||||
### PAGE-P1-004:移动/企微考勤入口自循环,通知直达对多类对象丢失目标
|
||||
|
||||
- 维度:跨端归属 / 企业微信 deeplink / 移动信息架构。
|
||||
- 严重级别:P1。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`docs/产品设计规则.md:101`、`:106`、`:116`;`client/src/pages/MobilePortalPage.tsx:348`、`:362`;`client/src/lib/notificationLinks.ts:52`、`:67`、`:75`;`client/src/lib/runtimeContext.ts:99`、`:113`;`client/src/pages/MobileNotificationsPage.tsx:124`、`:167`。
|
||||
- 证据:移动首页“查看考勤汇总”链接到 `/attendance`;在企微/触控小屏中该 PC 路由又被 `resolveMobileEquivalentPath` 折叠回 `/mobile`,形成自循环。移动通知把考勤修正目标也映射为 `/attendance`;资产/盘点目标统一映射 `/mobile/assets/scan`,不携带资产 ID 或现有的 `inventoryCheckId` 参数。
|
||||
- 影响:企微用户点击考勤入口回到原首页;考勤、资产和盘点通知虽然显示“直达详情”,实际无法定位原对象,用户必须重新查找,破坏消息到业务目标的闭环。
|
||||
- 确认方式:用 WeCom UA 访问 `/mobile` 点击“查看考勤汇总”;再构造 `attendance_correction`、`asset`、`inventory_check` 三类通知,核对最终 URL 与目标对象是否保留。
|
||||
- 建议:为考勤提供明确的移动镜像/摘要路由,或允许该只读页面在企微中响应式打开;资产目标传 `id`/查询值,盘点传 `inventoryCheckId`;每种通知类型增加“最终 URL + 目标内容”断言。
|
||||
- 修复边界:移动首页、通知目标解析、移动考勤/资产/盘点入口和相关 E2E;不触碰企微真实发送或写入。
|
||||
- 是否需用户决策:是——确定考勤汇总采用专用移动页,还是允许现有 PC 只读页在企微 WebView 中打开。
|
||||
|
||||
### PAGE-P1-005:全局搜索对多类命中只跳列表,不跳命中对象
|
||||
|
||||
- 维度:全局导航 / 搜索可用性。
|
||||
- 严重级别:P1。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`server/src/routes/search.js:173`、`:179`、`:201`、`:206`、`:341`、`:349`、`:378`、`:386`;`client/src/components/GlobalSearchDialog.tsx:95`、`:157`;`client/src/pages/AssetRegistryPage.tsx:233`;`client/tests/e2e/global-search.spec.ts:53`、`:59`。
|
||||
- 证据:项目、报销和采购结果携带对象路由/`?id=`,但资产、请假、合同、资料引用、公告、周报和待办结果只返回通用列表路径。搜索弹窗点击时原样导航 `item.href`;资产页本可接收 `?id=`,合同页只有 `projectId`,请假 PC 页没有命中 ID 处理。现有 E2E 只点击并断言报销结果。
|
||||
- 影响:用户明确点击一个资产、合同或请假搜索结果后,只看到普通列表且无法确认命中项,数据量稍大时“全局搜索”失去直接导航价值。
|
||||
- 确认方式:搜索一条非首屏资产、合同和请假记录,点击结果后检查是否打开/高亮该对象;当前静态 href 已足以证明目标参数缺失。
|
||||
- 建议:所有对象型结果统一返回稳定详情路由或 `?id=/highlight=`;页面接收参数并打开/高亮对象。公告/周报/待办若无详情路由,至少滚动定位并高亮;补每种实体的点击回归。
|
||||
- 修复边界:搜索 API href 合同、对应页面 deeplink 处理和搜索 E2E;不扩大搜索数据权限。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-P1-006:共享业务表格在 768/1024 断点存在右侧列被裁切风险
|
||||
|
||||
- 维度:响应式 / 表格可用性。
|
||||
- 严重级别:P1。
|
||||
- 置信度:高。
|
||||
- 状态:`LIKELY`。
|
||||
- 文件与行号:`client/src/components/patterns/BusinessListTemplate.tsx:24`、`:34`;`client/src/components/patterns/ListWorkspace.tsx:92`;`client/src/index.css:318`、`:547`;`client/src/layouts/AppShellLayout.tsx:65`;`client/src/components/navigation/Sidebar.tsx:6`。
|
||||
- 证据:`BusinessTable` 从 `md` 开始显示、内部表格最小宽度 760px;外层 `.table-container` 是 `overflow-hidden` 而不是横向滚动。768px 下内容区扣除页面边距后不足 760px;1024px 时侧栏开始占 288px,主内容区同样不足 760px。项目、资产、合同、付款、票据、报销六个核心列表复用该结构。
|
||||
- 影响:常见 768/1024 视口可能裁掉最右“状态/操作”列,且容器没有横向滚动,直接影响查看详情或处理入口。
|
||||
- 确认方式:在 768×1024 与 1024×768 分别打开 `/projects`、`/assets`、`/contracts-registry`、`/payment-batches`、`/invoice-pool`、`/reimbursements`,量测 table/container 的 `clientWidth`、`scrollWidth`、`overflowX`,确认操作列是否可见和可滚动。
|
||||
- 建议:让共享表格容器 `overflow-x-auto`,或把桌面表格断点提高到内容真正容得下的宽度并继续显示卡片;在 768/1024 加操作列可见断言。
|
||||
- 修复边界:共享表格 CSS/模板及六页响应式回归;不逐页打补丁。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-P1-007:核心表单标签与动态错误缺少可访问性语义
|
||||
|
||||
- 维度:可访问性 / 表单反馈。
|
||||
- 严重级别:P1。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`client/src/pages/ContractsRegistryPage.tsx:416`、`:425`、`:456`;`client/src/pages/ProjectsPage.tsx:201`;`client/src/components/patterns/BusinessEditTemplate.tsx:131`;`client/src/pages/PurchaseRequestsPage.tsx:830`、`:966`;`client/src/pages/MobileNotificationsPage.tsx:218`。
|
||||
- 证据:合同和项目等核心编辑表单大量使用独立 `<Label>`,但没有 `htmlFor`,相邻 Input/select 也没有 `id`,因此视觉标签没有程序化关联。共享验证摘要和采购/移动通知动态错误只渲染红色块,没有 `role="alert"`、`aria-live`、`aria-invalid` 或字段级 `aria-describedby`。启发式扫描发现页面/组件约 529 个表单控件、375 个 label,但只有 177 个 `htmlFor`;整个页面/组件范围只有登录与忘记密码两处 `aria-live`。数量仅用于说明规模,finding 以列出的确定样例为准。
|
||||
- 影响:屏幕阅读器无法可靠读出字段名称或获知异步错误;键盘/辅助技术用户在合同、项目、采购和移动流程中可能无法定位失败字段,核心流程并非等价可用。
|
||||
- 确认方式:对合同/项目创建表单取 accessibility snapshot 或运行 axe;触发采购列表/表单错误,确认 live region 是否产生公告;逐字段核对 accessible name。
|
||||
- 建议:建立共享 Field/FieldError 合同,强制稳定 id、`htmlFor`、`aria-invalid`、`aria-describedby`;动态错误使用适当的 `role=alert`/`aria-live` 并把焦点移动到摘要或首个错误字段。
|
||||
- 修复边界:共享表单/验证组件和核心表单分波迁移;不以批量字符串替换代替逐页验证。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
## 新增 P2 Finding
|
||||
|
||||
### PAGE-P2-001:路由元数据、页面标题与浏览器标题存在系统性漂移
|
||||
|
||||
- 维度:信息架构 / 标题与导航。
|
||||
- 严重级别:P2。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`client/src/features/navigation/schema.ts:5`、`:53`;`client/src/components/navigation/Topbar.tsx:56`、`:168`;`client/src/layouts/AppShellLayout.tsx:49`;`client/index.html:7`;`client/src/pages/ReimbursementDashboardPage.tsx:138`;`client/src/pages/NotificationsPage.tsx:82`;`client/src/pages/TeamPresencePage.tsx:262`。
|
||||
- 证据:`PAGE_TITLES` 只覆盖部分 PC 路由,未命中时把原始 pathname 当标题并写入最近访问。`/reimbursements/dashboard` 被较长的 `/reimbursements/` 误识别成“报销详情”;`/system/users`、`/system/departments`、`/system/master-data`、`/delegations`、`/payroll`、`/performance` 等会显示原始路径。已有映射也存在“通知/通知中心”“团队/团队状态”“数据看板/仪表盘”等漂移。浏览器 `<title>` 始终是“海音达工作台”,没有按路由更新。
|
||||
- 影响:顶部标题、页面 H1、最近访问和浏览器 tab/back 历史语义不一致;管理页可能直接暴露内部路由文本。
|
||||
- 确认方式:依次打开统计、系统用户、通知、团队页面,对比 Topbar、H1、最近访问和 `document.title`。
|
||||
- 建议:建立唯一 typed route manifest,统一标题、分组、权限、导航和可选详情标题;路由变化时同步 `document.title`。详情标题可由页面覆写,但不得回落原始 pathname。
|
||||
- 修复边界:前端路由元数据、Topbar、最近访问和路由标题测试;不改业务路由 URL。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-P2-002:403、404 和渲染错误的恢复按钮仍指向隐藏旧仪表盘
|
||||
|
||||
- 维度:错误恢复 / 信息架构。
|
||||
- 严重级别:P2。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`client/src/pages/ForbiddenPage.tsx:9`、`:13`;`client/src/pages/NotFoundPage.tsx:9`、`:11`;`client/src/components/common/ErrorBoundary.tsx:33`、`:50`;`client/src/router/index.tsx:154`;`server/src/services/workspaceSettings.js:136`。
|
||||
- 证据:三类兜底都把“返回首页/工作台”链接写成 `/dashboard`;当前默认工作台是 `/portal`,Dashboard 在默认工作区中为 hidden,且普通用户进入后可能再次看到看板无权限状态。
|
||||
- 影响:发生 403/404/渲染错误时,用户没有被带回稳定可用入口,容易进入第二个无权限/空错误页面;文案与实际去向也不一致。
|
||||
- 确认方式:普通员工访问无权限路由、未知路由,并触发 ErrorBoundary 测试 fallback,点击返回按钮核对最终页面。
|
||||
- 建议:统一使用 `/portal` 或 `resolveDefaultWorkspacePath()`;错误页提供“返回上一页 + 回到工作台”,不要显示原始错误 message 作为普通用户主文案。
|
||||
- 修复边界:共享错误/403/404 页面及聚焦 E2E。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-P2-003:冻结的差旅能力仍散落在非差旅页面和入口合同中
|
||||
|
||||
- 维度:范围收口 / 兼容残留 / 跨页面一致性。
|
||||
- 严重级别:P2。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`docs/产品设计规则.md:151`;`.trellis/spec/hyb-oa/frontend-react-vite-design.md:189`、`:241`;`client/src/router/index.tsx:244`;`server/src/services/workspaceSettings.js:99`、`:138`;`client/src/pages/PaymentBatchesPage.tsx:387`;`client/src/pages/MobileApprovalsPage.tsx:84`;`client/src/pages/NotificationsPage.tsx:17`;`client/src/pages/MobileNotificationsPage.tsx:17`。
|
||||
- 证据:当前事实源要求差旅不进入主线、冻结模块不静默恢复;但差旅路由仍注册为管理/更多入口,付款批次无条件提供“差旅订单付款”,PC/移动通知筛选和移动审批筛选持续显示差旅。
|
||||
- 影响:冻结能力继续占用普通流程的认知空间,测试和维护容易误把差旅当作启用主线;付款用户甚至能选择一个当前不应扩展的实体类型。
|
||||
- 确认方式:使用付款管理员和普通移动角色检查上述入口是否在没有独立恢复 task/feature gate 时可见。
|
||||
- 建议:先移除非差旅页面的差旅选项和筛选;差旅路由保持隐藏或显式冻结边界。若为历史数据查询必须保留,只在独立只读/诊断入口通过明确 feature flag 开放。
|
||||
- 修复边界:页面入口、导航/feature gate、相关旧 E2E;数据模型/API 删除应另做兼容与迁移评估。
|
||||
- 是否需用户决策:是——确认“仅隐藏/冻结兼容”还是在独立清理 task 中删除前端和无消费者代码;结合用户已表达偏好,推荐先删用户可见入口,再审计后端消费者。
|
||||
|
||||
### PAGE-P2-004:普通路径仍暴露内部错误码与技术状态文案
|
||||
|
||||
- 维度:文案语义 / 错误恢复。
|
||||
- 严重级别:P2。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`.trellis/spec/hyb-oa/frontend-react-vite-design.md:688`、`:1151`;`client/src/pages/MobilePortalPage.tsx:36`;`client/src/pages/MobileApprovalsPage.tsx:194`;`client/src/pages/PurchaseRequestsPage.tsx:78`;`client/src/pages/ContractsRegistryPage.tsx:94`;`client/src/components/GlobalSearchDialog.tsx:118`;`client/src/components/common/ErrorBoundary.tsx:33`;`client/src/pages/WecomApprovalArchivePage.tsx:40`、`:47`、`:124`、`:222`、`:258`、`:328`、`:332`;`client/src/router/index.tsx:336`、`:338`。
|
||||
- 证据:静态扫描有 56 个页面/组件文件使用 `${error.code}: ${mapApiErrorMessage(...)}` 一类模式,覆盖移动首页、移动审批、采购、合同、搜索等普通路径;ErrorBoundary 直接展示 `error.message`。移动企微审批归档页也在空态暴露 `PARTIAL_ARCHIVE_NEEDS_DATA`,在筛选、卡片和详情中直接使用英文 `finding`,并把 `findingType`、`status`、`severity` 原值直接输出。该路由允许 `leave.view_own` / `attendance.view_own` 查看角色进入,不是仅管理员可见的排障页。当前 spec 明确普通用户不得看到错误码、内部状态码或技术 dump。
|
||||
- 影响:异常或对账信息出现时,用户先看到 `PERM_001`、`VALID_001`、`finding`、内部验收状态或原始枚举等平台语言,弱化“原因 + 影响 + 下一步”,也可能暴露不必要的内部实现信息;375px 卡片上的技术文案更直接占用有限空间。
|
||||
- 确认方式:分别 mock 权限、校验和网络错误,检查普通页面/移动页可见文本;在 375px 企微归档页覆盖空态、含 finding 的卡片和详情,并核对普通员工角色可见文本;管理员审计/排障页可作为允许显示技术摘要的对照组。
|
||||
- 建议:共享错误解析返回 `userMessage` 与可选 `diagnosticCode`;普通页面只显示自然中文和恢复动作,技术码只在管理/审计折叠区或日志中显示。企微归档页把 `finding` 统一翻译为“对账问题”,为类型、状态和严重度建立中文映射,并移除面向验收脚本的空态 token。
|
||||
- 修复边界:共享错误解析与普通页面调用点分波迁移;不改变服务端错误合同。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-P2-005:多处桌面表格行只能鼠标点击,缺少键盘等价入口
|
||||
|
||||
- 维度:键盘可达 / 表格交互。
|
||||
- 严重级别:P2。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`client/src/pages/InventoryChecksPage.tsx:323`;`client/src/pages/AssetRegistryPage.tsx:856`;`client/src/pages/PurchaseRequestsPage.tsx:1046`;`client/src/pages/PerformancePage.tsx:207`;`client/src/components/master-data/HolidayCalendarTab.tsx:368`。
|
||||
- 证据:上述 `<TableRow>/<tr>` 直接挂 `onClick`,但没有可聚焦语义、键盘处理或统一行内操作。盘点和部分管理表格依赖点击整行选择记录。
|
||||
- 影响:只用键盘或开关设备的用户无法选择盘点、资产分类、绩效周期等记录;鼠标悬停样式无法提供等价可达性。
|
||||
- 确认方式:从页面标题开始只按 Tab/Enter/Space,尝试选择上述行并进入后续操作。
|
||||
- 建议:优先在操作列放真实 `<button>/<Link>`;确需整行选择时仍保留显式可聚焦主操作,并给选中状态 `aria-selected`,不要只给 `tr` 增加伪按钮语义。
|
||||
- 修复边界:共享表格行操作约定和列出的五处页面。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-P2-006:共享视觉 token 与动效未达到当前可访问性基线
|
||||
|
||||
- 维度:视觉设计 / 低视力与动态效果。
|
||||
- 严重级别:P2。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`client/src/design/theme.css:8`、`:10`;`client/src/index.css:64`、`:318`、`:327`、`:559`、`:1098`。
|
||||
- 证据:`--color-text-tertiary: #94a3b8` 在白色背景的 WCAG 对比度约 2.56:1,却被用于 12px 表头/元信息;`text-zinc-400` 也约 2.56:1。所有 `.page-scaffold` 固定执行 320ms 位移动画,代码没有 `prefers-reduced-motion` 分支。
|
||||
- 影响:低视力用户难以识别表头和关键元信息;明确请求减少动态效果的用户仍会看到页面位移动画。
|
||||
- 确认方式:在 100%/200% 缩放下检查表头/元信息对比度,并在系统启用 reduce motion 时记录 computed animation。
|
||||
- 建议:语义正文/表头至少使用达到 AA 的色阶,浅色只保留非必要装饰;添加 `@media (prefers-reduced-motion: reduce)` 关闭页面位移及非必要过渡。
|
||||
- 修复边界:共享主题/CSS token 与全局视觉回归,不逐页改色。
|
||||
- 是否需用户决策:是——若项目尚无可访问性等级,建议把 WCAG 2.1 AA 设为普通文字与交互的验收基线。
|
||||
|
||||
### PAGE-P2-007:“全页面视觉巡检”矩阵与路由已漂移,且缺关键中间断点
|
||||
|
||||
- 维度:视觉验证可信度 / 页面覆盖。
|
||||
- 严重级别:P2。
|
||||
- 置信度:高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`docs/trialrun/项目级流程覆盖矩阵.csv:2`、`:6`;`client/tests/e2e/project-wide-visual.spec.ts:129`、`:363`、`:390`、`:405`;`client/tests/e2e/r106-visual-audit.spec.ts:506`、`:532`;`client/tests/e2e/r103-cross-page-ui-consistency.spec.ts:339`;`client/src/router/index.tsx:336`;`client/tests/e2e/oafront3-pc-readonly-visual.spec.ts:118`。
|
||||
- 证据:项目级覆盖矩阵只有 5 个业务行,系统管理写为 `/system/*`;runner 只替换少数动态 ID,不展开 wildcard,会把 `/system/*` 原样导航成 404,同时只审 1440/390。R106 仍把 PC 请假写成不存在的 `/leave`,审查函数没有校验预期 H1/404,可能给 404 截图记“PC 请假”。R103 只有采购、票据和移动票据三项,未覆盖项目/资产,也没有 768/1024。仓库已注册 `/mobile/wecom-approval-archive`,但当前只找到 PC `/wecom-approval-archive` 的 HR 视觉条目,没有该移动路由的 375/390 覆盖。
|
||||
- 影响:测试名称和报告容易给出“全页面已看”的错误信心;正好遗漏共享表格最危险的中间断点和多个管理/业务页面。
|
||||
- 确认方式:运行 `--list` 后打印最终 route plans,断言不得含 `*`,每页必须核对最终 URL、预期 H1 且不得出现 403/404;统计与真实路由清单的差集。
|
||||
- 建议:从 typed route manifest 生成显式审查矩阵;动态详情由 fixture 解析,冻结/无权限明确标注;增加 768/1024,失败条件包含错误页、4xx 页面和标题不匹配。
|
||||
- 修复边界:视觉矩阵、项目级/R106/R103 E2E 和报告 schema;不在测试 task 中改页面实现。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-P2-008:移动导航和“我的”仍显示无权限或未校验权限的入口
|
||||
|
||||
- 维度:权限显隐 / 移动信息架构。
|
||||
- 严重级别:P2。
|
||||
- 置信度:中高。
|
||||
- 状态:`CONFIRMED`。
|
||||
- 文件与行号:`.trellis/spec/hyb-oa/frontend-react-vite-design.md:632`、`:644`;`client/src/components/mobile/MobileBottomNav.tsx:39`、`:46`;`client/src/pages/MobileMePage.tsx:54`、`:112`;`client/src/router/index.tsx:353`、`:371`。
|
||||
- 证据:移动底栏对无报销权限角色仍渲染 disabled“报销不可用”,而不是隐藏;移动“我的”只检查采购/资产/审批,却无条件显示“请假记录”和“报销”,对应路由本身又有权限守卫。
|
||||
- 影响:特殊只读、停用或最小权限角色会看到不可用入口,点击“我的”中的未校验链接可能直接进入 403;与“未授权动作通常隐藏”合同不一致。
|
||||
- 确认方式:用不含 `expense.view_*`、`leave.view_*` 的最小权限 fixture 打开 `/mobile` 与 `/mobile/me`,检查底栏/入口和点击结果。
|
||||
- 建议:入口清单统一使用同一 permission predicate,未授权业务入口直接隐藏;只有确有申请权限/配置缺失说明时才显示 disabled 状态和真实下一步。
|
||||
- 修复边界:移动导航 schema、BottomNav、MobileMe 与角色矩阵 E2E。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
## 既有 Finding 复核与去重
|
||||
|
||||
以下 5 条均已在 `.trellis/tasks/05-31-unified-page-header-actions/prd.md:108` 登记,本轮不重复建账。
|
||||
|
||||
### PAGE-DUP-P1-001:复核角色仍看到“新建批次”
|
||||
|
||||
- 维度:付款权限显隐。
|
||||
- 严重级别:P1。
|
||||
- 置信度:高。
|
||||
- 状态:`DUPLICATE`。
|
||||
- 文件与行号:`client/src/pages/PaymentBatchesPage.tsx:110`、`:347`、`:356`、`:372`;既有记录 `.trellis/tasks/05-31-unified-page-header-actions/prd.md:110`。
|
||||
- 证据:页面已计算 `canManageBatch`,但列表标题“新建批次”没有按它隐藏;复核用户点击后才看到只读说明。
|
||||
- 影响:误导复核角色进入无法完成的写流程;服务端 403 虽防止写入,但不修复页面合同。
|
||||
- 确认方式:仅授予 `risk.review.manage` 的角色打开付款列表,检查标题按钮。
|
||||
- 建议:按钮和创建面板都以 `canManageBatch` 为条件;增加 review-only 负例。
|
||||
- 修复边界:独立权限显隐修复 task。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-DUP-P1-002:合同只读角色仍看到完整写动作
|
||||
|
||||
- 维度:合同权限显隐。
|
||||
- 严重级别:P1。
|
||||
- 置信度:高。
|
||||
- 状态:`DUPLICATE`。
|
||||
- 文件与行号:`client/src/pages/ContractsRegistryPage.tsx:200`、`:284`、`:310`、`:334`、`:798`、`:861`;既有记录 `.trellis/tasks/05-31-unified-page-header-actions/prd.md:111`。
|
||||
- 证据:页面只对人员目录做权限判断,没有合同写权限布尔值;新增、编辑、续约和归档对 `project.view_own/view_all` 只读用户可见,最终依赖 API 403。
|
||||
- 影响:只读用户无法判断真实能力,可能填写整张合同后才失败。
|
||||
- 确认方式:`project.view_own`/`project.view_all` 且无 manage/settings 的角色打开合同页。
|
||||
- 建议:建立合同 view/manage 权限动作矩阵,写动作默认隐藏,保留只读详情/台账。
|
||||
- 修复边界:独立合同权限 task,需跨层 reviewer。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-DUP-P1-003:票据上传按钮没有使用已计算的上传权限
|
||||
|
||||
- 维度:票据权限显隐。
|
||||
- 严重级别:P1。
|
||||
- 置信度:高。
|
||||
- 状态:`DUPLICATE`。
|
||||
- 文件与行号:`client/src/pages/InvoicePoolPage.tsx:56`、`:59`、`:475`、`:485`;既有记录 `.trellis/tasks/05-31-unified-page-header-actions/prd.md:112`。
|
||||
- 证据:`canUploadInvoice` 已计算,但标题“上传票据”和上传面板没有引用它。
|
||||
- 影响:只读/管理范围角色可能进入最终失败的上传流程。
|
||||
- 确认方式:无 `invoice.upload`、有只读入口权限的 fixture 检查标题动作和面板。
|
||||
- 建议:按上传权限隐藏标题动作和上传面板,并补直连负例。
|
||||
- 修复边界:独立票据权限 task。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-DUP-P2-001:两条资产 E2E 仍点击旧的直接“资产分类”按钮
|
||||
|
||||
- 维度:测试与交互漂移。
|
||||
- 严重级别:P2。
|
||||
- 置信度:高。
|
||||
- 状态:`DUPLICATE`。
|
||||
- 文件与行号:`client/tests/e2e/assets-flow.spec.ts:88`;`client/tests/e2e/manual/asset1d-public-trial.spec.ts:165`;`client/src/pages/AssetRegistryPage.tsx:743`、`:754`;既有记录 `.trellis/tasks/05-31-unified-page-header-actions/prd.md:113`。
|
||||
- 证据:页面已把“资产分类”放入“更多”,两条测试仍按直接按钮点击。
|
||||
- 影响:自动化不能验证当前真实交互,并可能在恢复公网试录时直接失败。
|
||||
- 确认方式:运行对应 mock E2E;manual spec 只做静态修复后在另行批准的公网场景验证。
|
||||
- 建议:测试先打开“更多”再选“资产分类”;不要为旧测试恢复直接按钮。
|
||||
- 修复边界:测试修复 task;不改资产页面。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
### PAGE-DUP-P2-002:标题动作容器没有数量合同,项目/资产视觉覆盖仍缺
|
||||
|
||||
- 维度:共享组件合同 / 视觉覆盖。
|
||||
- 严重级别:P2。
|
||||
- 置信度:高。
|
||||
- 状态:`DUPLICATE`。
|
||||
- 文件与行号:`client/src/components/patterns/ListWorkspace.tsx:36`;`client/tests/e2e/r103-cross-page-ui-consistency.spec.ts:339`;既有记录 `.trellis/tasks/05-31-unified-page-header-actions/prd.md:114`。
|
||||
- 证据:`HeaderActionGroup` 仅是 flex 布局,不限制“一主操作 + 最多一个更多”;R103 只覆盖采购、票据和移动票据,未覆盖项目、资产或七页面统一动作断言。
|
||||
- 影响:页面后续可继续在标题区堆按钮,而现有回归不报警。
|
||||
- 确认方式:静态枚举七个页面标题动作,并在 1440/1024 截图核对。
|
||||
- 建议:用可测试的 slot/variant 合同表达 primary/more,增加七页面统一断言和项目/资产截图。
|
||||
- 修复边界:共享标题动作组件及聚焦测试。
|
||||
- 是否需用户决策:否。
|
||||
|
||||
## 建议主线程优先做的浏览器复核
|
||||
|
||||
按风险收益排序,均应使用本地 Vite dev、mock/无凭据数据,不使用公网或真实资料:
|
||||
|
||||
1. **768/1024 共享表格**:`/projects`、`/assets`、`/contracts-registry`、`/payment-batches`、`/invoice-pool`、`/reimbursements`;检查右侧操作列、横向滚动、标题动作换行和页面整体 `scrollWidth`。
|
||||
2. **付款角色与创建**:review-only 与 manage 两种角色;检查“新建批次”显隐、候选来源、内部 ID 文案和表单 accessible name。
|
||||
3. **合同/票据只读角色**:复核新增/编辑/续约/归档、上传票据是否隐藏,避免只在 API 403 时才告知权限不足。
|
||||
4. **375px 企微审批归档专项**:以 375×812(可补 375×667)和 WeCom UA 打开 `/mobile/wecom-approval-archive`,分别 mock 空态、加载态、有记录和打开详情;覆盖长页面文案、长人员名、含对账问题记录,断言桌面表格隐藏、卡片/详情单列、`documentElement.scrollWidth <= clientWidth`、末尾内容不被底栏遮挡。至少使用普通员工查看权限与 HR/管理员两类角色,核对范围选项和可见数据;真机 WebView 另记 `EXTERNAL_GATED`。
|
||||
5. **移动/企微直达**:390px WeCom UA 打开 `/mobile` 点击考勤汇总;在 `/mobile/notifications` 注入考勤、资产、盘点通知,检查最终目标和返回语义。
|
||||
6. **全局搜索**:从 `/portal` 搜索并点击资产、合同、请假、公告、周报和待办;检查是否打开/高亮唯一结果,以及状态是否仍显示 `in_use/reviewing` 等原始码。
|
||||
7. **未保存保护**:采购、资产、合同、报销分别修改字段后点击返回、侧栏、浏览器返回和刷新。
|
||||
8. **键盘与可访问性**:合同/项目表单 accessible name,采购错误 live announcement,盘点/资产分类/绩效表格的 Tab/Enter,移动导航最小权限角色;建议输出 accessibility snapshot 或 axe 结果。
|
||||
9. **错误恢复**:普通员工走 403、404、ErrorBoundary 和典型 API 错误,确认回到工作台且不展示内部码。
|
||||
|
||||
## 建议修复波次
|
||||
|
||||
1. **页面 P1 闭环**:付款候选选择、危险确认、未保存保护、移动 deeplink、全局搜索直达、核心表单可访问性。
|
||||
2. **共享响应式与权限显隐**:确认 768/1024 后修 BusinessTable;同时处理 3 条既有权限显隐 finding。
|
||||
3. **范围收口与语义**:差旅用户可见残留、路由/标题 manifest、错误文案与 recovery 入口。
|
||||
4. **视觉/测试治理**:对比度与 reduce motion、键盘表格、显式全路由视觉矩阵和已漂移 E2E。
|
||||
|
||||
审查阶段不应在同一 task 中混改上述页面;每波先建独立 Trellis task,并对权限、付款、审批和状态动作安排只读 reviewer。
|
||||
|
之后 宽度: | 高度: | 大小: 60 KiB |
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"id": "system-multidimensional-audit",
|
||||
"name": "system-multidimensional-audit",
|
||||
"title": "多维系统审查与问题分级",
|
||||
"description": "在不修改业务实现和不访问生产的前提下,从功能、业务闭环、页面、设计、权限、数据、安全、性能、测试、运维和文档等维度审查当前本地系统,并输出证据化 P0/P1/P2 finding。",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": "audit/full-system",
|
||||
"package": null,
|
||||
"priority": "P1",
|
||||
"creator": "shunli",
|
||||
"assignee": "shunli",
|
||||
"createdAt": "2026-07-16",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [
|
||||
".trellis/tasks/archive/2026-07/07-16-legacy-task-runbook-closeout",
|
||||
".trellis/tasks/05-31-unified-page-header-actions",
|
||||
".trellis/spec/hyb-oa",
|
||||
"docs/文档索引.md",
|
||||
"docs/文档事实源状态矩阵.md",
|
||||
"docs/产品设计规则.md",
|
||||
"client/src/router/index.tsx",
|
||||
"server/prisma/schema.prisma",
|
||||
"client/tests/e2e",
|
||||
"server/tests/unit",
|
||||
"scripts/qa"
|
||||
],
|
||||
"notes": "用户已批准风险收敛收口:保留发现基线 bbb5c89,并对当前本地 HEAD 8f8606c 补充 delta。两个原 P0 已完成本地修复验证,但均未获部署或外部行为验证;不得据此声称公网已同步。本轮只更新当前 task、必要 spec 与合成浏览器证据,不修改业务代码、API、schema、生产配置或真实数据,也不创建下游修复 task。后续仅按员工敏感数据、付款一致性、高敏合同附件、发布门禁、客户端数据生命周期/导出、页面权限显隐与旧标题任务的顺序登记建议;部署、公网角色、企微真机和新 Day 1 试运行须另行授权。",
|
||||
"meta": {}
|
||||
}
|
||||