fix: 完善动态错误指引与发票日期校验(09-05-error-explainability-payment-readiness)
这个提交包含在:
@@ -18,6 +18,17 @@ QA script patterns over new abstractions.
|
||||
|
||||
## Common Checks
|
||||
|
||||
### Payment Account And Invoice Read Errors
|
||||
|
||||
- Payment-account maintenance and invoice-pool read validation use registered
|
||||
`payment_account.*` and `invoice_pool.*` reasons. Keep HTTP status, top-level
|
||||
error code and legacy detail fields; add `reasonCode` rather than changing
|
||||
permissions, queries or transaction order to make validation pass.
|
||||
- Invalid input and unavailable references must fail before successful writes,
|
||||
audit or notifications. Retain masked-account behavior and never echo input
|
||||
bank accounts in error messages. Reason registry, client mapping and exact
|
||||
message fixtures change together; remove only the migrated AST baseline entries.
|
||||
|
||||
### Receipt OCR Matching Service Boundary
|
||||
|
||||
- Failed evidence persistence is not OCR failure. In a separate bounded transaction,
|
||||
@@ -187,9 +198,30 @@ Wrong: treat a notice count or pending-batch aggregate as the complete finance w
|
||||
domain-scoped `details.reasonCode`; do not infer business identity from a
|
||||
details key alone. The builder rejects unregistered reasons.
|
||||
- **迁移一条遗留原因码 = 服务端注册 + 客户端映射 + 具体内容断言,三项缺一不可。**
|
||||
Dynamic guidance requires an additional payload test containing both reasonCode
|
||||
and its legacy details (missing fields, retry timestamps, failed policy rules).
|
||||
A reason-only fixture cannot prove preservation of actionable details. Project
|
||||
only allowlisted fields for that reason; malformed or cross-domain details must
|
||||
fall back safely instead of bypassing the registered message contract.
|
||||
Fixed expected text lives in `server/tests/unit/fixtures/error-reason-messages.json`
|
||||
and is asserted against both registry and client rendering; do not replace
|
||||
these assertions with broad message regexes or expectations derived at runtime.
|
||||
- Authentication explanations must retain the same `auth.code_invalid_or_expired`
|
||||
reason for missing, inactive, locked and wrong-code accounts; do not introduce
|
||||
account-enumerating recovery messages or include submitted secrets in errors.
|
||||
- Invoice verification availability is distinct from OCR availability. Explain a
|
||||
disabled verification gate without claiming OCR is disabled or enabling either
|
||||
provider. Invalid or duplicate requests must not enqueue work or write records.
|
||||
- Workflow input-error migration preserves parsers, permission order and transaction
|
||||
boundaries. Invalid comments, task identifiers and batch requests must fail before
|
||||
business transactions; changing error metadata does not authorize state-machine edits.
|
||||
- Invoice date-only input must survive UTC date round-trip unchanged. Reject invalid
|
||||
timestamps and calendar overflow (including non-leap February 29) before updates
|
||||
or audits; JavaScript Date construction alone is not calendar validation.
|
||||
- Preserve pre-existing actionable top-level API messages when migrating a reason.
|
||||
Use a fixed registered builder call, retaining legacy details/status and then the
|
||||
original message if necessary; do not bypass the AST gate with direct AppError
|
||||
literals or dynamic, unvalidated reason names.
|
||||
- Legacy entries are versioned AST-shape SHA-256 fingerprints plus relative file/operation,
|
||||
occurrence count, owner, explanation and expiry date (UTC). Whitespace, quotes,
|
||||
indentation, trailing commas and parenthesization must not change identity.
|
||||
|
||||
在新工单中引用
屏蔽一个用户