@onlineapps/error-handler-core 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,26 @@ All notable changes to this package. Follows [Keep a Changelog](https://keepacha
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [3.1.0] — 2026-09-25
8
+
9
+ ### Added — třída `ErrorTypes.DECLINED`: pravidlo práci zakázalo (d.831)
10
+
11
+ Každá dosavadní třída pojmenovává způsob, jakým se práce NEPOVEDLA. `DECLINED` říká,
12
+ že se dělat neměla: doklad už odeslaný byl, položku zdroj neprojednává. Je koncová,
13
+ není to selhání, neopakuje se a nejde do DLQ — `ErrorHandlerCore` pro ni vrací verdikt
14
+ `declined`, který je (stejně jako `dlq`) klasifikací pro volajícího, ne cestou, kterou
15
+ by tenhle balíček sám šel.
16
+
17
+ Deklaruje ji VYHAZUJÍCÍ přes `error.type`; ze stavového kódu se neodvozuje. Tabulka
18
+ kódů zůstává beze změny — každé jiné `409` je dál `BUSINESS`, protože týž stav nese
19
+ oba významy a jen vyhazující ví, který z nich myslel.
20
+
21
+ Rozhodnutí vlastníka:
22
+ `api/docs/governance/confirmations/workflow-failed-status-projection.md` 004
23
+ (odmítnutí bránou komba není selhání běhu). Závažnost logu `info`, protože to není
24
+ incident; mapa kategorií v `UnifiedLogSchema` ji kontroluje při načtení, takže třída
25
+ bez závažnosti balíček neprojde.
26
+
7
27
  ## [3.0.0] — 2026-09-16
8
28
 
9
29
  ### Removed — **BREAKING** `DLQRouter`: dead-lettering má jednu kolej, a není v tomto balíčku
package/README.md CHANGED
@@ -151,6 +151,22 @@ Branch on `error.code`, never on `error.message`: the wording follows
151
151
  `.claude/rules/architecture-principles.md` §5 and may be improved, the code and
152
152
  `details.name` are the contract.
153
153
 
154
+ ## `DECLINED` — a rule forbade the work
155
+
156
+ Every class in `ErrorTypes` names a way the work FAILED, except this one. `DECLINED`
157
+ says the work was refused: the domain rule that was asked says it must not happen —
158
+ a document already sent, an item the source will not discuss. It is terminal, it is
159
+ not a failure, it is not retried and it is not dead-lettered; `ErrorHandlerCore`
160
+ answers it with the verdict `declined`, which — like `dlq` — is a classification
161
+ returned to the caller, not a route this package takes.
162
+
163
+ It is declared by the THROWER, through `error.type`, and never derived from a status:
164
+ every other `409` stays `BUSINESS`, table and all. That is deliberate, because the
165
+ same status carries both meanings and only the thrower knows which one it meant.
166
+
167
+ @see api/docs/governance/confirmations/workflow-failed-status-projection.md — 004
168
+ @see api/docs/biz/70-contracts/error-handling.md — the error classes
169
+
154
170
  ## API Reference
155
171
 
156
172
  See [ERROR_HANDLING.md](/docs/standards/ERROR_HANDLING.md) for the cross-cutting standard (classification table, fail-loudly rules).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/error-handler-core",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "Core error handling functionality for OA Drive microservices - classification, retry, circuit breaker, DLQ routing",
5
5
  "oa": {
6
6
  "category": "connector"
@@ -11,6 +11,13 @@ const ErrorTypes = {
11
11
  VALIDATION: 'VALIDATION', // Input validation - DLQ
12
12
  TIMEOUT: 'TIMEOUT', // Operation timeout - RETRY
13
13
  RATE_LIMIT: 'RATE_LIMIT', // Rate limiting - RETRY with backoff
14
+ // A rule forbade the work. TERMINAL and NOT a failure: the caller asked for
15
+ // something the domain says must not happen — a document already sent, an
16
+ // item the source will not discuss — so there is nothing to retry and nothing
17
+ // to dead-letter. It is declared by the thrower through `error.type`, never
18
+ // derived from a status: every other 409 stays BUSINESS.
19
+ // @see api/docs/governance/confirmations/workflow-failed-status-projection.md 004
20
+ DECLINED: 'DECLINED', // Refused by a rule - TERMINAL, no retry, no DLQ
14
21
  UNKNOWN: 'UNKNOWN' // Unclassified - LOG and THROW
15
22
  };
16
23
 
@@ -316,6 +316,14 @@ class ErrorHandlerCore {
316
316
  case ErrorTypes.FATAL:
317
317
  // Fatal errors, throw immediately
318
318
  return { type: 'throw' };
319
+
320
+ case ErrorTypes.DECLINED:
321
+ // A rule forbade the work: terminal, and neither a retry nor a failure.
322
+ // Its own verdict rather than `dlq`, because dead-lettering says "look at
323
+ // this", and there is nothing to look at — the refusal IS the outcome
324
+ // (conf `workflow-failed-status-projection` 004). Like `dlq`, this is a
325
+ // CLASSIFICATION returned to the caller; this class routes nothing.
326
+ return { type: 'declined' };
319
327
 
320
328
  default:
321
329
  // Unknown errors, log and throw
@@ -25,6 +25,11 @@ const SEVERITY_BY_TYPE = {
25
25
  [ErrorTypes.VALIDATION]: 'warn',
26
26
  [ErrorTypes.TIMEOUT]: 'error',
27
27
  [ErrorTypes.RATE_LIMIT]: 'warn',
28
+ // Not an incident: a rule said no, and the run ended on that. `info` is the
29
+ // severity of a thing that happened as designed — filing it as `error` would
30
+ // put every refused send into the operator's error stream, which is the noise
31
+ // conf `workflow-failed-status-projection` 004 exists to remove.
32
+ [ErrorTypes.DECLINED]: 'info',
28
33
  [ErrorTypes.UNKNOWN]: 'error'
29
34
  };
30
35