文件
hyb-oa/issues/2026-02-09_13-39-02-p5-blueprint-v3.csv
T
wangsli 3ae9e08692 chore(issues): 新增 P5 蓝图执行合同快照 v1-v3(F1)
- v3 修正通知依赖:F30 依赖 F14(不再被邮件阻塞)

- 提升关键项 Test_Method 为可复现 curl 步骤

- 新增回归脚本条目:F40/F41
2026-02-09 16:20:40 +08:00

26 KiB

1IDTitleDescriptionAcceptanceTest_MethodToolsDev_StatusReview1_StatusRegression_StatusFilesDependenciesNotes
2F1CSV快照收口(P5蓝图v2)创建P5蓝图v2执行合同快照:补齐组织/票据人工修正/配置只读/通知触发等缺口;旧快照不回改CSV通过校验;依赖关系正确;旧快照不回改python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-02-09_12-34-42-p5-blueprint-v2.csvmanualDONEDONEDONEissues/2026-02-09_12-34-42-p5-blueprint-v2.csv[]none
3F2费用类型只读API(expense-types)补齐费用类型查询接口(enabled/sort_order),供报销明细下拉使用GET /api/expense-types?enabled=true 返回启用项(默认37)按 sort_order 排序;登录即可访问manual: 启动 server;以 [email protected]/AdminPassword1234 登录拿 accessToken;curl -sS -H 'authorization: Bearer <TOKEN>' 'http://127.0.0.1:3000/api/expense-types?enabled=true' | jq -e '.data.items|length>0';确认 items 按 sort_order 升序manualDONEDONEDONEserver/src/routes/expenseTypes.js | server/src/app.js | server/README.md["F1"]优先复用既有 ExpenseType seed,不引入新依赖
4F3费用类型管理API(system.settings)新增费用类型增改启停接口,并写入 audit_logsfinance_mgr/admin 可启停费用类型;禁用后不出现在 enabled 查询;审计日志包含变更摘要manual: curl 调用创建/禁用/启用并查询验证;同时查询 /api/audit-logs 筛选 actionmanualDONEDONEDONEserver/src/routes/expenseTypes.js | server/src/routes/audit.js | server/src/constants/permissions.js["F2"]只做最小可运营;复杂排序/导入后置
5F4报销单编辑与删除(补齐CRUD)补齐 PATCH/DELETE 报销单能力(仅 draft/rejected 可编辑;仅 draft 可删除);删除 draft 必须自动解绑其绑定票据并回到 available状态/权限校验正确;删除不影响其他实体;删除 draft 时 invoice_pool 自动解绑;workflow/audit 证据一致cd server && ./scripts/regression-workflow-actions.shmanualDONEDONEDONEserver/src/routes/reimbursements.js | server/scripts/regression-workflow-actions.sh["F1"]复用现有 ensureOwnOrCanViewAll 与 AppError 体系
6F5报销明细CRUD与总金额重算新增报销明细 items 的增改删;每次变更事务内重算 reimbursement_forms.total_amountitems CRUD 只允许 draft/rejected;total_amount=items.sum;submit 按 total_amount 匹配 approval_rulecd server && ./scripts/regression-workflow-actions.shmanualDONEDONEDONEserver/src/routes/reimbursements.js | server/scripts/regression-workflow-actions.sh["F2","F4"]金额字段统一 toMoneyString;避免浮点误差
7F6前端报销编辑器(明细+费用类型)在报销详情页补齐明细编辑能力(费用类型下拉+日期+金额+说明),并保持现有提交/撤回/支付闭环employee 可完整填写明细并提交;列表/详情金额一致;typecheck/build/e2e 通过cd client && npm run typecheck && npm run build && npm run test:e2emanualTODOTODOTODOclient/src/pages/ReimbursementDetailPage.tsx | client/src/api/reimbursements.ts | client/src/api/expenseTypes.ts["F3","F5"]UI继续复用现有 shadcn 风格组件;加 data-testid
8F7代提交(expense.proxy_submit)允许 administration 为员工 owner 创建/提交报销(submitter=行政,owner=员工):POST /api/reimbursements 支持 ownerEmployeeId;强制 delegation_grants 有效期校验;workflow 解析以 owner 为基准;必要时补齐 administration 角色最小权限(expense.create/submit/withdraw/invoice.upload)无授权时 403;有授权可 create/submit 且审批人按 owner.direct_manager 解析;own 口径包含 submitter_id=me;audit_logs 记录 proxy 行为cd server && ./scripts/regression-workflow-actions.shmanualDONEDONEDONEserver/src/routes/reimbursements.js | server/src/utils/delegation.js | server/src/routes/workflow.js | server/src/constants/permissions.js | server/scripts/regression-workflow-actions.sh["F5"]前端可后置:先保证后端权限链/审计链正确
9F8行政代上传(owner≠uploaded_by)放开 invoice-pool/upload 跨 owner 上传:system.users 允许;administration 需具备 expense.proxy_submit 且存在有效 delegation_grants(scope=reimbursement_submit/all);并写 audit_logs行政可为已授权员工上传;未授权拒绝;owner/uploaded_by 记录正确;发票归属与可见性规则不被破坏;审计可追踪cd server && ./scripts/regression-ocr.sh && ./scripts/regression-audit.shmanualDONEDONEDONEserver/src/routes/invoicePool.js | server/src/utils/delegation.js | server/src/routes/audit.js | server/src/constants/permissions.js["F7"]保持上传不阻塞 OCR;ownerScope 查询语义不变
10F9票据解绑/重绑(bound->available)新增 unbind 接口:仅当报销单处于 draft/rejected 时允许解绑;解绑后票据回到 available 并清理 linked_*解绑权限与状态校验正确;解绑后可重新绑定其他报销草稿;不破坏判重约束cd server && ./scripts/regression-workflow-actions.shmanualTODOTODOTODOserver/src/routes/invoicePool.js | server/scripts/regression-workflow-actions.sh["F1"]与 invoice_pool_status_invariants_chk 保持一致
11F10判重例外(override duplicate)新增 finance_mgr 判重例外接口:标记 invoice_pool.is_duplicate_override=true 并记录引用原单号+原因;写 audit_logs命中判重时普通用户仍 VALID_003;finance_mgr 可 override 后成功 bind/submit;若原单 status=approved/paid 则 VALID_004cd server && ./scripts/regression-dedup.sh && ./scripts/regression-audit.shmanualTODOTODOTODOserver/src/routes/invoicePool.js | server/src/routes/reimbursements.js | server/scripts/regression-dedup.sh | server/src/routes/audit.js["F9"]严格遵守规格书:例外必须可审计可追溯
12F11OCR失败重试API(次数/频控)新增 POST /api/invoice-pool/:id/retry-ocr:attempt<=3 且 60 秒频控;超限返回 VALID_006/VALID_007;写 audit_logsocr_failed 可重试回到 pending_ocr 并由 job 处理;频控与次数校验正确;mock 模式可回归cd server && ./scripts/regression-ocr.sh && ./scripts/regression-audit.shmanualTODOTODOTODOserver/src/routes/invoicePool.js | server/src/jobs/ocrJob.js | server/prisma/schema.prisma | server/prisma/migrations/* | server/scripts/regression-ocr.sh["F1"]错误码新增需同步 client 错误文案映射
13F1290天未绑定自动归档(unused_timeout)新增作业:available/ocr_failed 超过 90 天未绑定自动归档为 archived_reason=unused_timeout;并保证不参与判重作业可重复运行幂等;归档后仍可查询/预览;不影响全局判重历史口径cd server && ./scripts/regression-ocr.sh && manual: 调整 created_at 模拟超期后跑 job 断言manualTODOTODOTODOserver/src/jobs/invoiceArchiveJob.js | server/src/app.js | server/README.md["F11"]后续迁移到 pg-boss;当前可先 node-cron 实现
14F13signed-url审计与下载行为记录对 signed-url 签发与下载两类事件写 audit_logs(不记录敏感 token 明文)无权限仍 403;有权限获取 signed-url 与下载时均可在 audit_logs 检索到对应记录cd server && ./scripts/regression-audit.shmanualTODOTODOTODOserver/src/routes/invoicePool.js | server/src/routes/audit.js["F1"]extra 仅保存 invoiceId/actorId/expireAt 等脱敏信息
15F14站内通知基础设施(DB+API)新增 notifications 表与 API(list/markRead),用于工作流与系统事件通知可分页读取;可标记已读;权限隔离正确;最小索引满足试运行cd server && npm run prisma:migrate:dev && ./scripts/regression-all.shmanualTODOTODOTODOserver/prisma/schema.prisma | server/src/routes/notifications.js | server/src/app.js["F1"]只做最小字段:title/body/type/targetId/readAt
16F15邮件通知(SMTP/Nodemailer)引入 nodemailer 发送邮件:新待办/审批结果/付款完成/密码重置等;失败降级不阻塞主流程;可配置开关EMAIL_ENABLED=false 时不发送;开启后可发出测试邮件;失败仅记录 audit/日志不影响业务manual: 配置 SMTP 并触发一次待办通知/重置密码邮件manualTODOTODOTODOserver/src/services/email/* | server/src/config.js | server/package.json["F14"]优先复用成熟 nodemailer;写回滚说明
17F16前端通知入口(Bell)新增通知列表页/弹层与未读角标;支持标记已读四角色均可见自己的通知;读写后角标正确;e2e 覆盖核心路径cd client && npm run test:e2emanualTODOTODOTODOclient/src/components/navigation/Topbar.tsx | client/src/pages/NotificationsPage.tsx | client/src/api/notifications.ts["F14"]保持 UI 轻量,不做复杂订阅推送
18F17报表导出(CSV/Excel)新增报销/票据/审计的导出接口(权限控制),前端提供下载入口导出字段与权限正确;大数据量时可分页/流式输出;审计记录导出操作manual: 导出后核对字段;并在 audit_logs 中检索 EXPORT 动作manualTODOTODOTODOserver/src/routes/exports.js | client/src/pages/* | server/package.json["F6","F16"]推荐 exceljs 或 csv-stringify(二选一并写 Notes:用途/版本/回滚)
19F18审批规则维护(system.settings)补齐 approval_rules 维护 API 与最小前端页(finance_mgr/admin),支持启停与优先级/金额段维护规则变更可立即影响新 submit;历史 instance 不回写;审计记录变更cd server && ./scripts/regression-workflow-actions.shmanualTODOTODOTODOserver/src/routes/approvalRules.js | client/src/pages/ApprovalRulesPage.tsx | server/src/app.js["F5"]只做最小可运营;复杂可视化后置
20F19作业系统升级(pg-boss 基础设施)引入 pg-boss(Postgres 队列)作为作业基础设施:提供统一注册/执行框架与开关;保持 node-cron 作业可回滚;并文档化单机用法pg-boss 可在单机/多进程下可靠运行;最小示例 job 可跑通;不影响现有回归cd server && ./scripts/regression-all.shmanualTODOTODOTODOserver/src/jobs/* | server/src/app.js | server/package.json | deploy/trialrun/* | server/README.md["F1"]选择 pg-boss(成熟/无 Redis);回滚:关闭开关并切回 node-cron
21F19b作业迁移(OCR -> pg-boss)将 OCR 异步处理迁移到 pg-boss:保持并发锁语义、幂等与回归脚本不变mock/tencent 两种 provider 下 OCR 仍可跑;并发下单条仅处理一次;回归全绿cd server && ./scripts/regression-ocr.sh && ./scripts/regression-all.shmanualTODOTODOTODOserver/src/jobs/ocrJob.js | server/src/services/ocr/* | server/README.md["F19"]迁移后移除/停用对应 node-cron tick(保留回滚路径)
22F19c作业迁移(委派回收 -> pg-boss)将委派过期回收迁移到 pg-boss:保持 FOR UPDATE SKIP LOCKED + UPDATE RETURNING 原子认领语义多进程并发下审计不重复写;回收逻辑不变;回归全绿cd server && RUN_DELEGATION_CONCURRENCY_CHECK=1 ./scripts/regression-workflow-actions.shmanualTODOTODOTODOserver/src/jobs/delegationRevokeJob.js | server/README.md["F19"]仍需保留原子认领+审计只基于 RETURNING 结果集
23F19d作业迁移(超期归档 -> pg-boss)将 90 天游离归档迁移到 pg-boss(替代 node-cron),统一重试/并发/可观测字段作业可重复执行幂等;多进程不重复处理;回归全绿cd server && ./scripts/regression-ocr.sh && ./scripts/regression-all.shmanualTODOTODOTODOserver/src/jobs/invoiceArchiveJob.js | server/README.md["F19","F12"]迁移后在 README 标注调度频率与开关
24F20Worker进程拆分(可选)提供 API 进程与 Worker 进程拆分的部署方式(compose 开关),保持单机也可跑开启后:API 不跑作业;Worker 只跑作业;两者共享 DATABASE_URL;功能不回归manual: docker compose 起两个进程并跑回归脚本manualTODOTODOTODOdeploy/trialrun/docker-compose.yml | server/src/index.js | server/README.md["F19"]仍保持单机;为未来横向扩展铺路
25F21对象存储(MinIO/S3兼容)存储从本地目录演进到 S3 兼容(先 MinIO),保持 signed-url 契约不变或提供兼容层上传/预览/签名URL 在 MinIO 下可用;回归与 E2E 通过;迁移路径清晰可回滚manual: trialrun 环境启用 MinIO 并完成一次上传预览manualTODOTODOTODOserver/src/services/storage/* | deploy/trialrun/* | server/README.md["F20"]优先用 @aws-sdk/client-s3;单机优先 MinIO
26F22可观测性增强(metrics/日志)新增 /metrics(Prometheus)与更完整的结构化日志字段规范(不落敏感)metrics 可抓取关键指标(HTTP/作业/DB);日志具备 requestId/actorId/targetId 等字段manual: curl /metrics 并核对字段;触发作业观察指标变化manualTODOTODOTODOserver/src/app.js | server/src/observability/* | deploy/trialrun/*["F19"]优先用 prom-client;OTel 放更后
27F23SSO/OIDC(可选,P7+)支持 OIDC 登录(企业 SSO),保留现有密码登录作为 fallback可通过 OIDC 登录并绑定员工;权限模型不变;可配置开关manual: 配置 OIDC provider 后走一次登录回调manualTODOTODOTODOserver/src/routes/auth.js | server/src/services/oidc/* | server/README.md["F1"]优先复用 openid-client/passport 策略
28F24工作流扩展到其他实体(P7+)抽象 entity_type 扩展到请假/采购等(先骨架:definition+instance+task 复用)新实体可创建 instance 并走同审批动作;不影响报销既有链路manual: seed 一个 leave 定义并跑一条最小链路manualTODOTODOTODOserver/src/routes/workflow.js | server/src/routes/leave.js | server/prisma/schema.prisma["F19"]只做骨架与复用点,不做完整业务表单
29F25敏感字段加密与脱敏(P6+)落实员工银行卡/身份证等敏感字段的可逆加密与脱敏输出,并对查看/变更写审计对外响应仅脱敏;解密仅限特权权限并写 audit;不在日志/错误中泄露明文manual: 创建员工并查看返回脱敏;用特权接口取明文并在 audit 检索记录manualTODOTODOTODOserver/src/routes/users.js | server/src/services/crypto/* | server/src/routes/audit.js["F1"]优先用成熟库(libsodium/crypto),并明确密钥轮换策略
30F26部门API(departments)补齐部门树/列表与管理接口:GET /api/departments(默认隐藏归档,可 query 开启);POST/PATCH;POST /:id/archive(无子部门/无在职员工约束);写 audit_logs部门树可用且过滤正确;归档约束正确;system.users 才可写;审计可追踪manual: 启动 server;以 [email protected]/AdminPassword1234 登录拿 accessToken;curl -sS -H 'authorization: Bearer <TOKEN>' 'http://127.0.0.1:3000/api/departments' | jq;curl -sS -X POST -H 'authorization: Bearer <TOKEN>' -H 'content-type: application/json' 'http://127.0.0.1:3000/api/departments' -d '{name:...}';curl -sS -X PATCH -H 'authorization: Bearer <TOKEN>' -H 'content-type: application/json' 'http://127.0.0.1:3000/api/departments/<ID>' -d '{name:...}';curl -sS -X POST -H 'authorization: Bearer <TOKEN>' 'http://127.0.0.1:3000/api/departments/<ID>/archive';可选 curl -sS -H 'authorization: Bearer <TOKEN>' 'http://127.0.0.1:3000/api/audit-logs?action=DEPARTMENT_*' | jqmanualDONEDONEDONEserver/src/routes/departments.js | server/src/app.js | server/README.md["F1"]单机试运行优先;树构造按 parent_id 组装
31F27员工API对齐(新增别名 /api/employees)对齐规格书:在保留 /api/users 的同时新增 /api/employees 别名路由;补齐 GET详情/PATCH更新/POST archive;并保证本人可读自己的详情/api/employees 与 /api/users 行为一致;system.users 可增改归档;本人可 GET 自己;审计完整manual: 启动 server;以 [email protected]/AdminPassword1234 登录拿 accessToken;curl -sS -H 'authorization: Bearer <TOKEN>' 'http://127.0.0.1:3000/api/employees?page=1&pageSize=1' | jq;取 employeeId 后 curl -sS -H 'authorization: Bearer <TOKEN>' 'http://127.0.0.1:3000/api/employees/<ID>' | jq;再用普通 employee 登录拿 <EMP_TOKEN> 验证仅可 GET 自己且 GET 他人返回 403 PERM_001manualDONEDONEDONEserver/src/routes/users.js | server/src/routes/employees.js | server/src/app.js | server/README.md["F26"]优先复用既有 usersRoutes 实现,避免重复逻辑
32F28票据人工修正与手工归档(invoice-pool patch/archive)补齐 PATCH /api/invoice-pool/:id(remarks/人工修正关键字段,允许 ocr_failed -> available);补齐 POST /api/invoice-pool/:id/archive(manual,未绑定才允许);写 audit_logs(INVOICE_POOL_EDITED/INVOICE_POOL_ARCHIVED)服务端鉴权正确(owner/uploader/invoice.manage);人工修正后可参与 bind/判重;手工归档后不影响历史判重口径;审计可检索cd server && ./scripts/regression-audit.shmanualTODOTODOTODOserver/src/routes/invoicePool.js | server/scripts/regression-audit.sh | server/README.md["F1"]extra.changes 仅记录必要字段的前后快照(避免敏感/大字段)
33F29配置只读API(approval-rules/document-sequences)补齐只读配置接口:GET /api/approval-rules?enabled=true(登录即可);GET /api/document-sequences/reimbursement(system.settings 可选)两接口返回结构稳定且不暴露敏感;不影响现有 submit 生成单号逻辑manual: 启动 server;任意登录拿 accessToken;curl -sS -H 'authorization: Bearer <TOKEN>' 'http://127.0.0.1:3000/api/approval-rules?enabled=true' | jq;以 admin 登录拿 <ADMIN_TOKEN>;curl -sS -H 'authorization: Bearer <ADMIN_TOKEN>' 'http://127.0.0.1:3000/api/document-sequences/reimbursement' | jqmanualDONEDONEDONEserver/src/routes/configRead.js | server/src/app.js | server/README.md["F1"]仅只读;写接口与更复杂可视化后置
34F30通知触发集成(workflow/pay/auth)把关键事件写入 notifications 并可选触发邮件:新待办/审批结果/付款完成/密码重置等;失败降级不阻塞主流程提交后审批人收到通知;审批后 owner/submitter 收到结果;付款后收到通知;EMAIL_ENABLED=false 时仅站内通知;审计/日志可追踪manual: 走一条 submit->approve->pay 链路并验证 notifications 与(可选)邮件manualTODOTODOTODOserver/src/routes/workflow.js | server/src/routes/reimbursements.js | server/src/services/notifications/* | server/src/services/email/*["F14"]先做站内通知,邮件作为可选增强(复用 nodemailer)
35F31Delegation Grants API对齐(新增别名/增强响应)新增 /api/delegation-grants 别名路由并增强现有 delegation API:响应内嵌 principal/delegate 员工摘要;system.users 可代维护 principal;delegate 资格校验:scope=reimbursement_submit 需 expense.proxy_submit(administration);scope=all 需 expense.approve;支持 includeInactive/api/delegation-grants 与 /api/delegations 兼容;返回包含员工摘要;无权限阻断;代维护审计完整manual: 启动 server;以 [email protected]/AdminPassword1234 登录拿 accessToken;curl -sS -H 'authorization: Bearer <TOKEN>' 'http://127.0.0.1:3000/api/delegation-grants' | jq;curl -sS -X POST -H 'authorization: Bearer <TOKEN>' -H 'content-type: application/json' 'http://127.0.0.1:3000/api/delegation-grants' -d '{delegateEmployeeId:... scope:... validTo:...}';验证 /api/delegations/mine 与 /api/delegation-grants 返回一致且包含 principal/delegate 摘要manualDONEDONEDONEserver/src/routes/delegations.js | server/src/app.js | server/README.md["F27"]不破坏既有 /api/delegations 客户端;新增别名优先
36F32前端组织与员工最小运营补齐前端最小组织能力:部门列表/创建/归档;在用户管理页支持部门选择与直属上级选择(管理员视角)admin 可完成部门增改归档(含约束提示);可创建员工并选择部门与直属上级;typecheck/build 通过cd client && npm run typecheck && npm run buildmanualTODOTODOTODOclient/src/pages/DepartmentsPage.tsx | client/src/pages/UserManagementPage.tsx | client/src/api/departments.ts | client/src/api/employees.ts | client/src/router/index.tsx["F26","F27"]单机试运行优先;部门树可简化为层级列表
37F33前端行政代提交/代上传入口为 administration 增加 owner 选择入口:报销创建可选 owner;票据上传可选 owner;并基于 delegation-grants 限定可选范围有授权时可为指定员工创建/提交/上传;无授权时提示并阻断;typecheck/build/e2e 通过cd client && npm run typecheck && npm run build && npm run test:e2emanualTODOTODOTODOclient/src/pages/ReimbursementsPage.tsx | client/src/pages/InvoicePoolPage.tsx | client/src/api/reimbursements.ts | client/src/api/invoicePool.ts | client/src/api/delegations.ts | client/src/api/employees.ts["F7","F8","F31","F27"]为 E2E 增加 data-testid(owner selector / submit/upload)
38F34前端票据中心增强(编辑/归档/解绑/重试/例外)补齐票据中心 UI:人工修正/手工归档/解绑重绑/重试 OCR;finance_mgr 判重例外入口;并补 data-testid上述动作按角色/权限可见;状态与错误码展示清晰;typecheck/build/e2e 通过cd client && npm run typecheck && npm run build && npm run test:e2emanualTODOTODOTODOclient/src/pages/InvoicePoolPage.tsx | client/src/api/invoicePool.ts | client/src/api/errorMessages.ts["F28","F9","F10","F11"]动作按钮必须二次确认并给出不可逆提示(如归档)
39F35前端错误码文案补齐(VALID/AUTH/PERM)补齐新增错误码文案与 details 映射:VALID_004/006/007 等;保证 SYS_001 提示可读且可操作相关错误在页面/Toast 可读;不暴露敏感字段;typecheck/build 通过cd client && npm run typecheck && npm run buildmanualTODOTODOTODOclient/src/api/errorMessages.ts | client/src/api/http.ts | client/src/api/ApiError.ts["F34"]错误文案遵循:可行动/可定位(建议带 requestId)
40F36首次登录强制改密(后端)落实规格书:首次登录必须修改初始密码;新增 must_change_password 标记与改密接口(校验旧密码+密码策略+tokenVersion 强制下线);管理员重置密码后仍要求首次改密首次登录返回 mustChangePassword=true;改密成功后 mustChangePassword=false 且旧会话失效;审计包含改密动作manual: 创建员工使用初始密码登录->提示改密->改密后可进入系统;管理员重置密码后再次触发改密manualDONEDONEDONEserver/src/routes/auth.js | server/src/routes/users.js | server/src/utils/passwordPolicy.js | server/prisma/schema.prisma | server/prisma/migrations/* | server/README.md["F1"]默认策略:允许登录但强制前端在改密前禁止访问业务页(路由守卫)
41F37登录失败锁定与解锁(AUTH_002)落实规格书:15分钟内失败5次锁定30分钟;返回 AUTH_002(423);system.users 可解锁;所有动作写审计锁定窗口/次数/时长按配置生效;锁定期间无法登录;解锁后可登录;审计可检索manual: 连续输错触发锁定->验证423与AUTH_002;管理员解锁->恢复登录manualDONEDONEDONEserver/src/routes/auth.js | server/src/routes/users.js | server/src/config.js | server/prisma/schema.prisma | server/prisma/migrations/* | server/README.md["F1"]优先用 DB 字段记录失败窗口与锁定截止时间;避免引入外部缓存
42F38首次登录改密与锁定提示(前端)适配 mustChangePassword 流程:新增改密页面/强制守卫;对 AUTH_002 锁定提示与倒计时文案;保持现有刷新/401 自动续期逻辑不变首次登录无法进入业务页直到改密;AUTH_002 提示清晰且不暴露敏感;typecheck/build/e2e 通过cd client && npm run typecheck && npm run build && npm run test:e2emanualTODOTODOTODOclient/src/pages/LoginPage.tsx | client/src/pages/ChangePasswordPage.tsx | client/src/router/* | client/src/api/auth.ts | client/src/api/errorMessages.ts["F36","F35"]data-testid: change-password-old/new/submit;确保退出登录后守卫生效
43F39弱密码库拦截(Top 10k)落实规格书:新增弱密码库拦截(Top 10k)并纳入 validatePassword;优先复用成熟库或公开词表;可配置开关弱密码被拒绝并返回 VALID_001.details.password;正常密码不受影响;不显著增加接口延迟manual: 用弱密码与强密码分别走创建用户/重置密码/改密流程验证manualDONEDONEDONEserver/src/utils/passwordPolicy.js | server/package.json | server/README.md["F36"]选型:[email protected];替代:owasp-password-strength-test;回滚:WEAK_PASSWORD_CHECK_ENABLED=false 或移除依赖回退 passwordPolicy
44F40组织/配置回归脚本(org+settings)新增 server/scripts/regression-org-settings.sh:覆盖费用类型/部门/员工别名/配置只读/委派别名等关键权限与返回结构,并可选挂入 regression-all.sh脚本可重复执行且全绿;覆盖关键正负例;失败输出可定位cd server && ./scripts/regression-org-settings.shmanualDONEDONEDONEserver/scripts/regression-org-settings.sh | server/scripts/regression-all.sh | server/README.md["F3","F29","F31"]将上述 manual 验收逐步收敛为可回归门禁
45F41认证安全回归脚本(auth security)新增 server/scripts/regression-auth-security.sh:覆盖首次登录改密 must_change_password 流程、登录失败锁定 AUTH_002 及弱密码拦截等核心负例脚本可重复执行且全绿;可通过环境变量缩短锁定窗口以加速回归;失败输出可定位cd server && ./scripts/regression-auth-security.shmanualDONEDONEDONEserver/scripts/regression-auth-security.sh | server/scripts/regression-all.sh | server/README.md["F37","F39"]建议脚本支持用 env 覆盖锁定窗口与阈值以加速测试