6.3 KiB
6.3 KiB
五人团队正式内用最小收口设计
实施顺序
- 角色与敏感资料:先完成 enum/权限常量、账号与角色边界、员工 DTO、工资/银行/证件/合同授权及矩阵测试。
- 付款一致性:在新角色合同稳定后完成候选查询、行锁状态机、取消原因、回单作废、前端选择器及 PostgreSQL 并发验证。
- 页面与门禁:完成共享表格、dirty guard、移动路由、权限显隐、路由 manifest 和
local-candidaterunner,最后回填旧标题任务。
每阶段先跑聚焦测试再扩展到全量。权限、状态机、workflow 和迁移在实现后由只读 reviewer 复核,不让 reviewer 修改代码。
角色与权限设计
角色模型
employee是所有日常账号基础角色。manager、ceo、finance、system_admin是可兼任职责。finance_mgr、hr、administration保留兼容,不自动迁移。admin仍映射*,仅现有超级管理员/初始化流程可用;普通创建和普通角色编辑不提供该选项。
system_admin 授权
允许:账号创建/启停/凭据重置、为其他用户分配普通业务角色、系统设置、集成、通知渠道、脱敏审计查看。
拒绝:修改自身角色、授予或撤销 admin/system_admin、人员完整档案、工资、银行/证件、员工合同、业务审批、付款制单/执行/复核。
普通角色修改继续使用既有 endpoint,但服务端按操作者角色和目标用户实施额外约束;UI 限制只做体验,不作为安全边界。角色变更审计只记录操作者、目标用户 ID、前后角色代码和结果,不记录凭据或员工敏感字段。
敏感资料数据流
角色/对象判断 -> 选择最小 Prisma select -> DTO 字段省略 -> 前端按权限渲染
-> 脱敏审计(成功访问/写入)
- 业务员工目录固定字段:
id / employeeNo / name / title / department / avatar / status。 - 完整 profile:本人或人员资料管理权限。
- 银行资料:finance 只读;admin/明确管理权限可写。
- 证件、员工合同:仅明确管理权限;内部路径、原始正文和不必要文件名不进入 DTO/审计。
付款设计
状态机
draft -> reviewed -> executed
-> failed -> executed(仅失败项)
-> cancelled(仅未执行项)
-> cancelled
executed、cancelled终态;已执行 item 永不回滚。- review 需要
payment.batch.review且角色代码包含manager或ceo;创建者自审返回 409。 - 50000 元阈值只影响警示/确认文案,不增加状态或第三复核人。
锁与并发
- review/execute/cancel/付款元数据更新/回单作废:同一事务内先
SELECT ... FOR UPDATE锁批次。 - create:稳定排序并锁定源报销,复查
approved、未付款且未进入非 cancelled 批次。 - execute:稳定排序锁定开放 item 对应源单,再复查状态、金额和回单门槛。
- 竞争失败统一返回 409 业务码;失败重试按所有 item 最终状态重算汇总。
payment_batch_v1启用时旧直接付款端点返回兼容性 409;关闭 flag 可回滚旧代码路径。
API / 数据
- Prisma 加法迁移:
RoleCode.system_admin;payment_batches.cancelled_reason TEXT NULL。 GET /api/payment-batches/candidates?q=&page=&pageSize=返回业务展示字段,entity ID 仅用于后续提交。- 取消 body:
{ reason };DTO 增cancelledReason。 - 回单作废:
{ reason };复用现有治理/归档字段,不物理删除。 - 旧 DELETE/直接付款仅作为 feature flag 回滚路径;新版开启时不得产生第二写路径。
迁移与回滚
- 只提交加法 migration,不运行 migrate deploy,不修改真实数据。
- 代码回滚时关闭
payment_batch_v1并回退应用提交;enum 和 nullable 列保留,避免破坏已写数据。 - 一旦部署后曾授予
system_admin,回退到不识别该枚举值的旧应用前,必须先在兼容版本中撤销或转换该角色,或保留可识别该值的兼容解析;不得让旧 Prisma client 直接读取未知枚举值。 - 不修改迁移历史,不执行 migrate reset。
页面与门禁设计
- 表格修复优先调整共享容器:表格自身保留最小宽度,容器
overflow-x:auto,document 不横溢;五个代表页做命中和尺寸断言。 - dirty guard 使用共享 hook/provider,统一拦截站内导航、浏览器返回/刷新和记录切换;保存成功或显式放弃后清除 dirty。
/mobile/attendance复用现有响应式考勤页;移动 resolver、首页和通知目标统一使用该路径,避免/attendance -> /mobile自循环。- 移动归档只处理长字段换行/局部 overflow 和底栏安全区,不扩展移动信息架构。
- 路由 manifest 每条注册路由必须显式分类;
core必须有可实际执行的行为 spec,标记visualRequired的路由还必须有视觉 spec;manual/live 文件不计本地候选证据。 local-candidate组合基础门禁、路由/流程可信扫描和核心本地浏览器测试,不读取公网或生产环境变量。
验证矩阵
- 权限:employee / manager / ceo / finance / system_admin / admin 正负矩阵;字段省略;拒绝时零 DB/file side effect;角色自提升负例。
- 付款:候选筛选、POST 权威拒绝、maker-checker、高额单次复核、取消原因、回单作废、审计、失败重试和权限负例。
- PostgreSQL 并发:双 execute、execute vs cancel、双 create 同一报销、direct pay vs batch execute;使用隔离合成数据库并清理。
- 浏览器:375×812 移动考勤/归档;768×1024 与 1024×768 五类表格;四类 dirty form;危险动作 0/0/1 mutation;三处权限按钮 count=0。
- 门禁反例:unclassified、manual-only、core behavior missing、visualRequired missing 均非零退出。
证据与状态
- 截图和临时浏览器产物放
output/playwright/07-18-small-team-internal-readiness/,只保留合成/脱敏内容。 - 原 finding 台账只更新当前修复状态和证据引用,不改发现时严重度;未部署项继续保持部署/外部验证待定。
- 本地完成结论固定为
LOCAL_CANDIDATE_PASS。