109 行
10 KiB
Markdown
109 行
10 KiB
Markdown
# 生产员工 Smoke Break-glass 重置:执行计划
|
||
|
||
> 当前状态:RESET COMPLETE / REVIEW PASS / HANDOFF COMPLETE。候选发布、唯一账号写入、一次登录、一次强制改密、最终验证、敏感材料清理和生产只读复核均已完成;员工凭据可用与负向前提未变已交接给 `08-08-production-authenticated-readiness`。
|
||
|
||
## 1. 规划事实与决策
|
||
|
||
- [x] 目标是专用 OA-only smoke employee,不是真人员工;`08-08` 已只读证明唯一资格目标,登录 attempts=0。
|
||
- [x] 已完整审阅 `repair-oa-only-smoke-accounts.js`:它不重置密码;apply 可恢复状态、清登录锁、token +1、补缺失角色并写 lifecycle event,但不删除额外角色、不撤销 session/challenge。
|
||
- [x] 现有 helper 只作为一次 dry-run 对照,禁止 apply;若 action 非空即停止。
|
||
- [x] 不扩展管理员脚本目标面;新增员工 smoke 专用脚本,角色/权限只断言、不写入。
|
||
- [x] 新脚本不在生产镜像,必须经正常候选发布;禁止单文件复制、inline code 或手写 SQL。
|
||
- [x] 生产写后重新验证 `roles == ['employee']` 和四项管理权限全 false,未通过前禁止登录。
|
||
|
||
## 2. 启动门禁
|
||
|
||
- [x] 用户完成本规划只读复核并明确批准 `task.py start`;该批准只覆盖本地实现与测试。
|
||
- [x] 读取 `trellis-before-dev`、backend 与 hyb-oa 相关 spec,再编辑 server 脚本/测试。
|
||
- [x] 确认工作区仅含本 task 规划及其实现改动;未混入 08-08 或其他任务改动。
|
||
|
||
## 3. Phase A:先实现最窄工具
|
||
|
||
- [x] 新增 `server/src/scripts/reset-employee-smoke-password.js`,复用现有 smoke 判据、管理员 stdin 密码校验和应用同源 crypto/password policy,未扩展管理员目标面。
|
||
- [x] 实现不接收/不输出 identifier 的唯一目标发现;精确角色与独立权限断言必须同时成立。
|
||
- [x] 实现默认/`--dry-run`/`--preflight`、`--verify`、`--verify-password-changed` 和精确 apply 确认串;本地最小范围未加入非必要企微诊断。
|
||
- [x] apply 使用 Serializable 事务,先锁 Employee、再锁其角色行并重新核对 id/token/status/smoke/role/permission;只写目标认证字段、目标 session/challenge 和专用 audit。
|
||
- [x] 未知异常脱敏;稳定输出不含账号、identifier、id、路径、hash、payload,privacy 口径沿用现有 helper 且更窄。
|
||
|
||
## 4. Phase B:再补覆盖与只读 review
|
||
|
||
- [x] 新增 `server/tests/unit/scripts/reset-employee-smoke-password.test.js`,23 条用例覆盖零/多目标、非 smoke、identifier/status/employment/archive/锁/must-change、额外角色、四个禁用权限、事务内 role/token 漂移、确认串、目标限定写入、verify 与最终改密 verify。
|
||
- [x] apply 的 Employee update 键集合被精确断言;无 role/status/identifier/企微/业务写入,session/challenge where 精确限定 target id。
|
||
- [x] `reset-active-admin-password.test.js` 6/6 PASS,管理员脚本目标面未扩大。
|
||
- [x] `repair-oa-only-smoke-accounts.test.js` 5/5 PASS,并新增完整副作用合同:只补角色、不删额外角色、不重置密码、不写 session/challenge。
|
||
- [x] node check、focused 34/34、Prisma validate、client typecheck/build/PWA 生成全部 PASS;build 仅有既有 Browserslist 数据陈旧提示。
|
||
- [x] 用户只读 reviewer 复核 diff 后结论 PASS:确认唯一 Employee update 仅为认证字段,角色路径纯读,默认 dry-run/精确确认串 fail-closed,两个 verify 均重算精确角色与四项权限;reviewer 未修改代码。
|
||
- [x] reviewer 额外确认事务以 Serializable 隔离级别先锁 Employee、再锁角色行,并在写入前重验目标/token/角色/权限;候选到写入之间的前提漂移会中止事务。
|
||
|
||
## 5. STOP A:发布审批
|
||
|
||
- [x] 本地实现、测试和 reviewer PASS 后提交中文 commit `ec68256`,引用 `08-10-production-employee-smoke-break-glass-reset`。
|
||
- [x] 已向用户报告精确 diff、测试、脚本完整写集/不写集与发布必要性;用户只读审查通过,当前进入发布审批门,未取得明确发布批准前不 commit/push/deploy。
|
||
- [x] 用户已明确批准五步发布范围:commit、push/provenance、发布前只读 preflight、`deploy-existing.sh` 正常发布、发布后运行脚本 SHA-256 比对;批准不包含员工账号 apply、登录或强制改密。
|
||
- [x] push 后 provenance 为 published/remoteVerified=true;候选无 migration、无产品运行路径改动。
|
||
|
||
## 6. Phase C:正常发布与运行脚本身份
|
||
|
||
- [x] 运行生产 identity/read-only preflight:聚合体检 13/13、identity PASS、migration pending=none、rollback window OPEN/0。
|
||
- [x] 仅在独立发布批准下通过既有入口使用 `deploy-existing.sh` 发布候选;三个持久化阶段日志均 PASS。
|
||
- [x] 发布后 ready/runtime/public build marker、runtime smoke、public bundle 和 migration 均 PASS;运行镜像新脚本与候选 `scriptShaMatch=true`。
|
||
- [x] 未执行 `docker cp`、SSH 单文件同步、工作区脚本覆盖或 inline 写入代码。
|
||
|
||
## 7. Phase D:生产只读前置
|
||
|
||
- [x] 取得独立生产账号写入及后续一次登录/强制改密批准;批准不包含角色、企微或业务写入。
|
||
- [x] rollback window PRE 为 OPEN/0。
|
||
- [x] helper 最终 dry-run:唯一目标 safe、status=OK、actions=[]、rolesExact=true、passwordReset=false、helperApplyCount=0。
|
||
- [x] 新脚本 `--preflight`:targetMatches=1、exactTarget/rolesExact/identifierReady/locksCleared=true,四项管理权限 false。
|
||
- [x] 独立 `BEGIN READ ONLY` 查询复核相同角色/权限基线;break-glass audit 写前计数为 0。
|
||
- [ ] 可选写前企微诊断只记录稳定布尔/计数,不修改绑定。
|
||
- [x] 准备 `0700/0600` 旧 hash 有限恢复材料、互不相同的临时/最终密码和 apply attempt 哨兵;任何敏感值未回显。
|
||
|
||
## 8. Phase E:唯一账号写入
|
||
|
||
- [x] 从 stdin 执行且仅执行一次 `--apply EMPLOYEE_SMOKE_BREAK_GLASS`;`applyExecutionCount=1`。
|
||
- [x] apply 返回完整 PASS 后立即 `--verify`;未进入 `APPLY_UNCERTAIN`,不存在第二次 apply。
|
||
- [x] verify 对 must-change、locks、session/challenge、token/audit 和目标/角色/权限全部 PASS。
|
||
- [x] 独立 `BEGIN READ ONLY` 再次确认 targetMatches=1、`roles == ['employee']`、四项管理权限 false;审计从 0 增至 1,增量恰好 +1。
|
||
- [x] 写后权限不变量全部通过后才进入登录;未修改角色或权限。
|
||
|
||
## 9. Phase F:一次登录与强制改密
|
||
|
||
- [x] 仅在 Phase E 全 PASS 后,原子更新仓库外 employee smoke secret 为正确 identifier + 临时密码,权限 `0600`。
|
||
- [x] 单 browser/context、workers=1、retries=0 登录一次,HTTP 200 并进入 `/change-password`。
|
||
- [x] 使用已准备的最终密码提交一次,HTTP 200 后自然落到 `/portal` 并立即停止;主动业务导航 0、非认证 mutation 0,登录/改密 POST 各 1;`/portal` 过渡期被动只读请求 4。
|
||
- [x] `--verify-password-changed` 与最终独立权限快照 PASS;最终 secret 原子更新且 `0600`。
|
||
- [ ] 写后企微诊断(若启用)证明绑定状态未变;不得做企微登录/绑定写入。
|
||
|
||
## 10. Phase G:清理、review 与交接
|
||
|
||
- [x] 销毁临时凭据、最终密码暂存、浏览器状态、attempt 控制状态和旧 hash;`temporaryCredentialDestroyed/browserStateCleared/recoveryMaterialDestroyed=true`。
|
||
- [x] 最终生产 read-only preflight 为 13/13,migration pending=none,rollback window POST=OPEN/0;本任务脚本和浏览器未进入合同或其他业务功能。
|
||
- [x] 只读 reviewer 核对运行脚本 SHA、apply 次数、审计 +1、目标限定副作用、写后精确角色/权限、零业务写入和清理证据,结论 PASS;reviewer 未修改代码或生产状态。
|
||
- [x] 更新本 task 稳定证据并运行 task/process/governance/sensitive/diff 门禁,全部 PASS、0 findings。
|
||
- [x] 只向 `08-08-production-authenticated-readiness` 交接最终员工凭据可用与负向权限前提未变;交接记录明确凭据来自本 task 的 break-glass 恢复而非原始 secret,未交接任何凭据值。
|
||
|
||
## 11. 验证命令
|
||
|
||
```bash
|
||
node --check server/src/scripts/reset-employee-smoke-password.js
|
||
cd server && npm test -- tests/unit/scripts/reset-employee-smoke-password.test.js tests/unit/scripts/reset-active-admin-password.test.js tests/unit/scripts/repair-oa-only-smoke-accounts.test.js
|
||
cd server && npm run prisma:validate
|
||
cd client && npm run typecheck && npm run build
|
||
python3 ./.trellis/scripts/task.py validate 08-10-production-employee-smoke-break-glass-reset
|
||
node scripts/qa/check-process-contract.mjs --baseline --json
|
||
node scripts/qa/check-trellis-governance.mjs --json
|
||
node scripts/qa/check-sensitive-content.mjs
|
||
git diff --check
|
||
```
|
||
|
||
## 12. 当前结论
|
||
|
||
本地实现、发布、生产 reset 生命周期与最终只读复核均已完成。候选 `ec68256` clean/published/remoteVerified,运行脚本 SHA 匹配;唯一 apply、登录和强制改密次数均为 1,零 retry。`--verify-password-changed` 与独立快照最终证明 must-change=false、activeSessions=1、`rolesExact=true`、四项管理权限全 false、break-glass audit=1 且改密审计晚于 break-glass。最终 secret 为 `0600`,敏感材料已销毁;最终生产门禁 13/13、migration pending=none、rollback window OPEN/0。只读 reviewer 复核源码写集、34/34 focused tests、生产终态和清理状态后结论 PASS;当前只差向 `08-08` 交接员工凭据可用与负向前提未变。
|
||
|
||
## 13. 执行观察与遗留项
|
||
|
||
- 首次 helper dry-run 按仓库历史默认测试员工解析时未命中本任务唯一目标,fail-closed 且 helper apply=0;改由独立只读查询在生产现场内存解析当前唯一目标后,helper dry-run 才得到 actions=[]。这证明 helper 内置默认目标已与当前生产漂移,后续任何 apply 讨论仍必须以 dry-run 和现场目标解析为先决条件;本任务不修改该 helper。
|
||
- 首次 apply 编排命令因本地执行策略拒绝临时文件删除写法,在 shell 启动前终止;只读复核确认 attempt 哨兵仍为 0。改成全内存捕获后才发出唯一 apply,审计增量 +1 进一步证明没有重复写入。
|
||
- 运行脚本 SHA 比对的首版 shell 格式断言也曾在只读阶段自我阻断,修正为原生正则后 `scriptShaMatch=true`;该比较器的 harness 覆盖与 helper 默认目标漂移均留作后续独立工具改进,不在认证恢复链路中顺手修复。
|