docs: 补齐财务身份验收窗口规约(09-05-error-explainability-payment-readiness)
这个提交包含在:
@@ -2807,6 +2807,9 @@ helper dry-run -> actions=[] and safe target
|
||||
- Required evidence fields: `stage`, `loginAttempts`, `loginHttpStatus`,
|
||||
`sampleCategory`, `sampleCount`, `businessMutationCount`, and the relevant
|
||||
endpoint-specific request count such as `terminatePostCount`.
|
||||
- A finance smoke window additionally records `authorizationRef`, `accountAlias`,
|
||||
`observedRoleCodes`, `disableReason`, `disableAuditRef` and `postDisableStatus`.
|
||||
Use aliases and redacted references, never credentials or full identifiers.
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
@@ -2834,10 +2837,60 @@ helper dry-run -> actions=[] and safe target
|
||||
- Recheck any state-based rollback window before and after the browser run.
|
||||
Missing samples and a still-open window remain independent facts.
|
||||
|
||||
#### Finance-role acceptance checklist
|
||||
|
||||
1. Resolve exactly one configured OA-only finance smoke in the isolated test
|
||||
department. Before login, read its `status`, `employment_status`,
|
||||
`archived_at`, `last_working_date`, lock state and effective role grants.
|
||||
Require exactly `employee + finance`, with no extra roles or wildcard grant.
|
||||
The database uses `status=archived` for disabled accounts; employees have no
|
||||
`left_at` field. A disabled account is a blocked acceptance prerequisite,
|
||||
not permission to weaken the login guard.
|
||||
2. Obtain explicit authorization for the complete enable -> acceptance ->
|
||||
disable window before any account write. Record the operator alias, purpose,
|
||||
deadline and abort/cleanup responsibility. Re-read status and role grants
|
||||
after enabling. Neither an earlier window nor an unexpectedly active account
|
||||
grants permission for a new window or permanent activation.
|
||||
3. Run the approved checks as that finance actor. Administrator results prove
|
||||
only administrator behavior: wildcard privileges cannot establish finance
|
||||
visibility, projections or action boundaries. A different read-only actor
|
||||
likewise cannot replace exact finance-role acceptance. Stop at the precise
|
||||
failed stage; do not replace the actor and mark the finance criterion PASS.
|
||||
4. Immediately disable the smoke through the approved account-management path
|
||||
when checks finish or abort. Read back `status=archived`, non-null
|
||||
`archived_at` and target session revocation, and link the disable audit event.
|
||||
A failed cleanup or missing verification leaves the window unclosed and must
|
||||
be handed off explicitly; it is not a successful closeout. Do not submit an
|
||||
extra login merely to prove that disabling worked.
|
||||
|
||||
- Record a concrete disable reason, such as `finance_acceptance_complete` or
|
||||
`finance_acceptance_aborted`, linked to the authorization and disable event.
|
||||
Current `server/src/routes/users.js` writes `SYSTEM_USER_DISABLED` with
|
||||
`extra: {}`: audit-native reason persistence is **not implemented**. Until a
|
||||
separately approved code change adds it, retain the reason in controlled
|
||||
acceptance evidence linked to the audit reference, operator alias and event
|
||||
time. Do not claim the audit row contains a reason, invent historical reasons,
|
||||
or directly patch audit rows to satisfy this checklist.
|
||||
- Do not treat a permanently active read-only finance account as an account-only
|
||||
shortcut. Current grants are fixed by `RoleCode`/`EmployeeRole` and
|
||||
`resolvePermissionsForRoles`, not arbitrary per-account permission strings;
|
||||
there is no finance-read-only role, and `employee` itself includes writes.
|
||||
Both payment candidates and combination readiness require
|
||||
`payment.batch.manage`; `expense.view_all` alone cannot cover them. A future
|
||||
read/write permission split needs separate approval and projection/denial
|
||||
verification. Read-only access still exposes confidential financial data and
|
||||
is not a zero-risk standing identity.
|
||||
|
||||
### 4. Validation & Error Matrix
|
||||
|
||||
- Login fails once -> stop with the authentication stage and re-read lock/failure
|
||||
state; no second login.
|
||||
- Finance smoke is disabled -> record the prerequisite as
|
||||
`PAUSED(finance_account_disabled)`; finance-role acceptance remains unverified.
|
||||
If login was attempted, distinguish `403/AUTH_003` at `/api/auth/login` from
|
||||
`403/PERM_001` at a later protected endpoint; never infer the layer from 403 alone.
|
||||
- Disable reason, linked audit reference or post-disable state proof is missing
|
||||
-> acceptance-window closeout is incomplete, even when all UI checks passed.
|
||||
- Login succeeds but the required sample count is zero -> authentication PASS,
|
||||
sample-dependent UI checks `PAUSED`, mutation counters must remain zero.
|
||||
- Runner label differs from the current shared product mapping -> runner
|
||||
@@ -2875,6 +2928,9 @@ helper dry-run -> actions=[] and safe target
|
||||
and mutation listeners installed before the first application navigation.
|
||||
- Evidence review must reconcile login attempts with session/audit changes and
|
||||
reconcile every unexecuted UI assertion with its sample count and stage.
|
||||
- For a finance window, verify the unique actor and exact grants before login,
|
||||
and the reason/audit linkage, disabled state and session revocation afterward.
|
||||
Administrator or alternative-role checks must not satisfy finance-role criteria.
|
||||
- Production execution still requires explicit approval, pre/post rollback
|
||||
window snapshots, sensitive-content scanning and a read-only reviewer.
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户