100 行
6.3 KiB
Markdown
100 行
6.3 KiB
Markdown
# 五人团队正式内用最小收口设计
|
||
|
||
## 实施顺序
|
||
|
||
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、前后角色代码和结果,不记录凭据或员工敏感字段。
|
||
|
||
### 敏感资料数据流
|
||
|
||
```text
|
||
角色/对象判断 -> 选择最小 Prisma select -> DTO 字段省略 -> 前端按权限渲染
|
||
-> 脱敏审计(成功访问/写入)
|
||
```
|
||
|
||
- 业务员工目录固定字段:`id / employeeNo / name / title / department / avatar / status`。
|
||
- 完整 profile:本人或人员资料管理权限。
|
||
- 银行资料:finance 只读;admin/明确管理权限可写。
|
||
- 证件、员工合同:仅明确管理权限;内部路径、原始正文和不必要文件名不进入 DTO/审计。
|
||
|
||
## 付款设计
|
||
|
||
### 状态机
|
||
|
||
```text
|
||
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`。
|