文件
hyb-oa/.trellis/tasks/07-18-small-team-internal-readiness/design.md
T

6.3 KiB
原始文件 Blame 文件历史

五人团队正式内用最小收口设计

实施顺序

  1. 角色与敏感资料:先完成 enum/权限常量、账号与角色边界、员工 DTO、工资/银行/证件/合同授权及矩阵测试。
  2. 付款一致性:在新角色合同稳定后完成候选查询、行锁状态机、取消原因、回单作废、前端选择器及 PostgreSQL 并发验证。
  3. 页面与门禁:完成共享表格、dirty guard、移动路由、权限显隐、路由 manifest 和 local-candidate runner,最后回填旧标题任务。

每阶段先跑聚焦测试再扩展到全量。权限、状态机、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。