文件
hyb-oa/.trellis/tasks/08-10-production-employee-smoke-break-glass-reset/implement.md
T
wangsli ec68256588
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s
实现(08-10-production-employee-smoke-break-glass-reset): 增加员工Smoke受控重置工具
2026-08-10 21:01:59 +08:00

8.8 KiB
原始文件 Blame 文件历史

生产员工 Smoke Break-glass 重置:执行计划

当前状态:RELEASE APPROVED / PRE-COMMIT。用户已批准提交、推送/provenance、生产只读 preflight、正常候选发布和运行脚本 SHA-256 比对;尚未批准生产账号写入、登录或强制改密。

1. 规划事实与决策

  • 目标是专用 OA-only smoke employee,不是真人员工;08-08 已只读证明唯一资格目标,登录 attempts=0。
  • 已完整审阅 repair-oa-only-smoke-accounts.js:它不重置密码;apply 可恢复状态、清登录锁、token +1、补缺失角色并写 lifecycle event,但不删除额外角色、不撤销 session/challenge。
  • 现有 helper 只作为一次 dry-run 对照,禁止 apply;若 action 非空即停止。
  • 不扩展管理员脚本目标面;新增员工 smoke 专用脚本,角色/权限只断言、不写入。
  • 新脚本不在生产镜像,必须经正常候选发布;禁止单文件复制、inline code 或手写 SQL。
  • 生产写后重新验证 roles == ['employee'] 和四项管理权限全 false,未通过前禁止登录。

2. 启动门禁

  • 用户完成本规划只读复核并明确批准 task.py start;该批准只覆盖本地实现与测试。
  • 读取 trellis-before-dev、backend 与 hyb-oa 相关 spec,再编辑 server 脚本/测试。
  • 确认工作区仅含本 task 规划及其实现改动;未混入 08-08 或其他任务改动。

3. Phase A:先实现最窄工具

  • 新增 server/src/scripts/reset-employee-smoke-password.js,复用现有 smoke 判据、管理员 stdin 密码校验和应用同源 crypto/password policy,未扩展管理员目标面。
  • 实现不接收/不输出 identifier 的唯一目标发现;精确角色与独立权限断言必须同时成立。
  • 实现默认/--dry-run/--preflight、--verify、--verify-password-changed 和精确 apply 确认串;本地最小范围未加入非必要企微诊断。
  • apply 使用 Serializable 事务,先锁 Employee、再锁其角色行并重新核对 id/token/status/smoke/role/permission;只写目标认证字段、目标 session/challenge 和专用 audit。
  • 未知异常脱敏;稳定输出不含账号、identifier、id、路径、hash、payload,privacy 口径沿用现有 helper 且更窄。

4. Phase B:再补覆盖与只读 review

  • 新增 server/tests/unit/scripts/reset-employee-smoke-password.test.js,23 条用例覆盖零/多目标、非 smoke、identifier/status/employment/archive/锁/must-change、额外角色、四个禁用权限、事务内 role/token 漂移、确认串、目标限定写入、verify 与最终改密 verify。
  • apply 的 Employee update 键集合被精确断言;无 role/status/identifier/企微/业务写入,session/challenge where 精确限定 target id。
  • reset-active-admin-password.test.js 6/6 PASS,管理员脚本目标面未扩大。
  • repair-oa-only-smoke-accounts.test.js 5/5 PASS,并新增完整副作用合同:只补角色、不删额外角色、不重置密码、不写 session/challenge。
  • node check、focused 34/34、Prisma validate、client typecheck/build/PWA 生成全部 PASS;build 仅有既有 Browserslist 数据陈旧提示。
  • 用户只读 reviewer 复核 diff 后结论 PASS:确认唯一 Employee update 仅为认证字段,角色路径纯读,默认 dry-run/精确确认串 fail-closed,两个 verify 均重算精确角色与四项权限;reviewer 未修改代码。
  • reviewer 额外确认事务以 Serializable 隔离级别先锁 Employee、再锁角色行,并在写入前重验目标/token/角色/权限;候选到写入之间的前提漂移会中止事务。

5. STOP A:发布审批

  • 本地实现、测试和 reviewer PASS 后提交中文 commit,引用 08-10-production-employee-smoke-break-glass-reset。
  • 已向用户报告精确 diff、测试、脚本完整写集/不写集与发布必要性;用户只读审查通过,当前进入发布审批门,未取得明确发布批准前不 commit/push/deploy。
  • 用户已明确批准五步发布范围:commit、push/provenance、发布前只读 preflight、deploy-existing.sh 正常发布、发布后运行脚本 SHA-256 比对;批准不包含员工账号 apply、登录或强制改密。
  • 获批后 push 并验证 provenance remoteVerified;再次确认候选无 migration、无意外产品改动。

6. Phase C:正常发布与运行脚本身份

  • 运行生产 identity/read-only preflight:身份、65 migration、pending、运行/公网 SHA、rollback window 全部按部署合同通过。
  • 仅在独立发布批准下使用 deploy-existing.sh 发布候选;失败立即停止,不进入账号阶段。
  • 发布后复核 ready/public SHA、匿名鉴权和 migration;比较运行镜像新脚本 SHA 与候选基线,要求 scriptShaMatch=true。
  • 不执行 docker cp、SSH 单文件同步、工作区脚本覆盖或 inline 写入代码。

7. Phase D:生产只读前置

  • 取得独立生产账号写入批准;确认批准包含脚本声明的完整认证副作用与一次强制改密,不包含角色或业务写入。
  • rollback window PRE。
  • 运行现有 helper 一次 dry-run:目标 safe、status=OK、actions=[]、passwordReset=false;记录 helperApplyCount=0。
  • 运行新脚本 --preflight:targetMatches=1、exactTarget/rolesExact/identifierReady/locksClear=true,四项管理权限 false。
  • 用独立 BEGIN READ ONLY 查询复核相同角色/权限基线;读取 break-glass audit 写前计数。
  • 可选写前企微诊断只记录稳定布尔/计数,不修改绑定。
  • 准备 0700/0600 旧 hash 有限恢复材料、互不相同的临时/最终密码和 apply attempt 哨兵;任何敏感值不回显。

8. Phase E:唯一账号写入

  • 从 stdin 执行且仅执行一次 --apply EMPLOYEE_SMOKE_BREAK_GLASS;applyExecutionCount=1。
  • 完整 PASS 后立即 --verify;若结果不确定,进入 APPLY_UNCERTAIN,只允许 --verify 定性,禁止第二次 apply。
  • verify 要求 must-change、locks、session/challenge、token/audit 和目标/角色/权限全部 PASS。
  • 独立 BEGIN READ ONLY 再次确认 targetMatches=1、roles == ['employee']、四项管理权限 false;审计计数较写前恰好 +1。
  • 任一写后权限不变量失败,停止且不登录;不得在本任务修角色或权限。

9. Phase F:一次登录与强制改密

  • 仅在 Phase E 全 PASS 后,原子更新仓库外 employee smoke secret 为正确 identifier + 临时密码,权限 0600。
  • 单 browser/context、workers=1、retries=0 登录一次,必须进入 /change-password。
  • 使用已准备的最终密码提交一次;到 /portal 后立即停止,业务 API 实际发送数为 0。
  • --verify-password-changed 与最终独立权限快照 PASS;最终 secret 原子更新且 0600。
  • 写后企微诊断(若启用)证明绑定状态未变;不得做企微登录/绑定写入。

10. Phase G:清理、review 与交接

  • 销毁临时 secret、浏览器状态、attempt 哨兵和旧 hash;记录 temporaryCredentialDestroyed/browserStateCleared/recoveryMaterialDestroyed=true。
  • 最终生产 read-only preflight、migration 和 rollback window POST;合同/schema/权限/其他账号写入计数为 0。
  • 只读 reviewer 核对运行脚本 SHA、apply 次数、审计 +1、目标限定副作用、写后精确角色/权限、零业务写入和清理证据。
  • 更新本 task 稳定证据并运行 task/process/governance/sensitive/diff 门禁。
  • 只向 08-08-production-authenticated-readiness 交接最终员工凭据可用与负向权限前提未变;回原 task 执行员工合同权限负向。

11. 验证命令

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. 当前结论

本地实现、自检与用户只读审查均已完成,结论 PASS。新脚本默认只读 preflight,只有精确确认串进入写入;角色路径只有读取、锁定与精确断言。--verify 和 --verify-password-changed 均重新输出实际 must-change、rolesExact 及四项管理权限布尔。用户已批准五步候选发布,当前进入提交前检查;账号写入、登录和强制改密仍需发布成功后的独立批准。