收口(08-10-production-employee-smoke-break-glass-reset): 记录生产重置复核
这个提交包含在:
@@ -2079,6 +2079,70 @@ atomic rename -> compare identifier/password in-process -> login once
|
||||
-> change password once -> final verify -> destroy temporary material
|
||||
```
|
||||
|
||||
## Scenario: Dedicated Employee Smoke Break-Glass Reset
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
- Trigger: a dedicated OA-only smoke employee is the approved negative-permission sample, its identifier is uniquely discoverable but its password is unusable, and changing a real employee is not acceptable.
|
||||
- Purpose: restore only that smoke account's authentication state while preserving the exact employee-only role and proving that no contract-management permission is introduced.
|
||||
|
||||
### 2. Signatures
|
||||
|
||||
- Read-only commands on `server/src/scripts/reset-employee-smoke-password.js`: `--preflight`, `--verify`, and `--verify-password-changed`.
|
||||
- Single write command: `node src/scripts/reset-employee-smoke-password.js --apply EMPLOYEE_SMOKE_BREAK_GLASS`, with the temporary password on stdin only.
|
||||
- `server/src/scripts/repair-oa-only-smoke-accounts.js` is a read-only cross-check for this scenario. Its `--apply` path is not a password-reset substitute.
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
- Discover the target from production state; do not accept or emit a complete identifier. The unique target must be active, employed, unarchived, identifier-ready, unlocked, not awaiting a password change, matched by the OA-only smoke predicate, and have roles exactly equal to `["employee"]`.
|
||||
- Resolve permissions independently from the exact role list and require `*`, `project.manage`, `project.view_all`, and `system.settings` all to be absent. Role equality alone is insufficient if the role-permission mapping later expands.
|
||||
- Run the repair helper in dry-run mode before apply and require `actions=[]`, `passwordReset=false`, and a safe smoke target. A stale built-in default target, a non-empty action plan, or an unsafe target is a stop condition; never repair forward to make reset preflight pass.
|
||||
- Use a Serializable transaction that locks the employee and role rows, then rechecks identity version, status, smoke classification, exact roles, and permissions before the sole employee update. Role tables are read-only throughout this script.
|
||||
- The write set is limited to the target's password and authentication counters/locks/token version, target-scoped sessions and challenges, and one dedicated audit event. It must not change roles, status, identifiers, WeCom binding, schema, or business data.
|
||||
- After apply, both script verification and an independent read-only snapshot must recompute exact roles and all four permission booleans before any login is allowed. A successful preflight is not reusable as post-write proof.
|
||||
- Apply-attempt, audit-delta, zero-retry browser, repository-external secret, recovery-material, and redacted-evidence rules are the same as the administrator break-glass scenario.
|
||||
|
||||
### 4. Validation & Error Matrix
|
||||
|
||||
- Target count other than one, role list not exactly employee, any forbidden permission, lock/status/smoke drift, or repair-helper action -> stop before apply.
|
||||
- Unknown CLI arguments or an inexact confirmation tuple -> `explicit_confirmation_required` or the allowlisted unsupported-arguments error; default behavior remains read-only.
|
||||
- Transaction-time employee/token/role/permission drift -> rollback with zero writes; do not broaden selection or modify roles.
|
||||
- Apply channel/result uncertain -> run `--verify` only and never apply a second password.
|
||||
- Post-write role/permission mismatch -> do not log in; permission repair requires a separate production-write decision.
|
||||
- Login or forced password change fails -> zero retry and no second apply; preserve the known credential state for a new decision.
|
||||
|
||||
### 5. Good/Base/Bad Cases
|
||||
|
||||
- Good: helper dry-run has no actions, preflight finds one exact employee-only smoke target, audit baseline increases by one after one apply, post-write permission snapshots agree, one login/forced change succeeds, and sensitive material is destroyed.
|
||||
- Base: target-scoped session or challenge update counts are zero because no active rows existed; exact `where.employee_id` scoping is still asserted.
|
||||
- Bad: use the repair helper because its name says repair, accept an employee role as merely present among extra roles, reuse the preflight permission result after apply, or select an arbitrary non-admin employee when target discovery is ambiguous.
|
||||
|
||||
### 6. Tests Required
|
||||
|
||||
- Unit tests cover zero/multiple targets; non-smoke, identifier, status, employment, archive, lock and must-change rejection; extra/missing roles; each forbidden permission; transaction-time token/role drift; confirmation parsing; apply write keys; target-scoped sessions/challenges; and both verify modes.
|
||||
- Regression tests freeze the repair helper's actual contract: it can restore lifecycle state, clear a login lock and add missing roles, but does not reset a password, delete extra roles, or revoke sessions/challenges.
|
||||
- Source review requires one employee-update block, no role write path, Serializable isolation, role-row locking, and target-scoped authentication writes.
|
||||
- Production evidence requires runtime-script SHA match, `applyExecutionCount=1`, audit delta exactly one, exact-role and four-permission booleans at every checkpoint, login/change counts 1/1, zero non-authentication mutation, and cleanup booleans.
|
||||
|
||||
### 7. Wrong vs Correct
|
||||
|
||||
#### Wrong
|
||||
|
||||
```text
|
||||
repair helper default target looks familiar -> apply helper
|
||||
roles include employee -> reset password -> assume permissions stayed safe
|
||||
apply output missing -> retry with another temporary password
|
||||
```
|
||||
|
||||
#### Correct
|
||||
|
||||
```text
|
||||
helper dry-run -> actions=[] and safe target
|
||||
-> employee reset preflight -> exact roles + permission booleans
|
||||
-> apply once -> verify + independent read-only permission snapshot
|
||||
-> login/change once -> final verify -> destroy sensitive material
|
||||
```
|
||||
|
||||
## Scenario: Zero-Retry Production Authenticated Readiness
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
在新工单中引用
屏蔽一个用户