@blamejs/core 0.7.18 → 0.7.20

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.
Files changed (169) hide show
  1. package/CHANGELOG.md +427 -423
  2. package/README.md +150 -150
  3. package/bin/blamejs.js +0 -0
  4. package/index.js +310 -308
  5. package/lib/api-key.js +660 -660
  6. package/lib/api-snapshot.js +338 -338
  7. package/lib/app-shutdown.js +385 -385
  8. package/lib/app.js +365 -365
  9. package/lib/archive.js +250 -250
  10. package/lib/atomic-file.js +544 -544
  11. package/lib/audit-chain.js +177 -177
  12. package/lib/audit-sign.js +344 -344
  13. package/lib/audit-tools.js +677 -677
  14. package/lib/audit.js +766 -766
  15. package/lib/auth/jwt-external.js +365 -0
  16. package/lib/auth/jwt.js +337 -311
  17. package/lib/auth/lockout.js +436 -436
  18. package/lib/auth/oauth.js +721 -721
  19. package/lib/auth/passkey.js +181 -181
  20. package/lib/auth/password.js +628 -594
  21. package/lib/backup/bundle.js +217 -217
  22. package/lib/backup/crypto.js +176 -176
  23. package/lib/backup/index.js +515 -515
  24. package/lib/backup/manifest.js +282 -282
  25. package/lib/break-glass.js +1338 -1338
  26. package/lib/bundler.js +441 -441
  27. package/lib/cache-redis.js +256 -256
  28. package/lib/cache.js +1206 -1206
  29. package/lib/canonical-json.js +115 -115
  30. package/lib/chain-writer.js +234 -234
  31. package/lib/cli-helpers.js +206 -206
  32. package/lib/cli.js +2334 -2334
  33. package/lib/cluster-provider-db.js +317 -317
  34. package/lib/cluster-storage.js +226 -226
  35. package/lib/cluster.js +703 -703
  36. package/lib/config-drift.js +301 -301
  37. package/lib/consent.js +222 -222
  38. package/lib/constants.js +191 -191
  39. package/lib/cookies.js +350 -315
  40. package/lib/credential-hash.js +322 -322
  41. package/lib/crypto.js +266 -266
  42. package/lib/csv.js +275 -275
  43. package/lib/db-declare-row-policy.js +267 -267
  44. package/lib/db-declare-view.js +420 -420
  45. package/lib/db-query.js +406 -406
  46. package/lib/db-schema.js +319 -319
  47. package/lib/db.js +1288 -1288
  48. package/lib/deprecate.js +222 -222
  49. package/lib/dev.js +335 -335
  50. package/lib/dual-control.js +473 -473
  51. package/lib/error-page.js +420 -420
  52. package/lib/external-db-migrate.js +441 -441
  53. package/lib/external-db.js +1061 -1061
  54. package/lib/file-type.js +273 -273
  55. package/lib/forms.js +422 -422
  56. package/lib/framework-error.js +293 -293
  57. package/lib/framework-schema.js +717 -717
  58. package/lib/handlers.js +350 -350
  59. package/lib/http-client-cookie-jar.js +508 -508
  60. package/lib/http-client.js +1195 -1195
  61. package/lib/i18n.js +878 -878
  62. package/lib/jobs.js +185 -185
  63. package/lib/log-stream-cloudwatch.js +369 -369
  64. package/lib/log-stream-local.js +146 -146
  65. package/lib/log-stream-otlp-grpc.js +410 -410
  66. package/lib/log-stream-otlp.js +286 -286
  67. package/lib/log-stream-syslog.js +302 -302
  68. package/lib/log-stream-webhook.js +199 -199
  69. package/lib/log-stream.js +330 -330
  70. package/lib/log.js +500 -500
  71. package/lib/mail-bounce.js +528 -528
  72. package/lib/mail-dkim.js +369 -369
  73. package/lib/mail.js +981 -981
  74. package/lib/metrics.js +683 -683
  75. package/lib/middleware/api-encrypt.js +936 -936
  76. package/lib/middleware/attach-user.js +157 -157
  77. package/lib/middleware/bearer-auth.js +152 -0
  78. package/lib/middleware/body-parser.js +1170 -1170
  79. package/lib/middleware/bot-guard.js +178 -178
  80. package/lib/middleware/compression.js +452 -452
  81. package/lib/middleware/cors.js +314 -314
  82. package/lib/middleware/csp-nonce.js +348 -348
  83. package/lib/middleware/csrf-protect.js +399 -316
  84. package/lib/middleware/db-role-for.js +264 -264
  85. package/lib/middleware/fetch-metadata.js +129 -0
  86. package/lib/middleware/health.js +392 -392
  87. package/lib/middleware/index.js +85 -79
  88. package/lib/middleware/rate-limit.js +358 -358
  89. package/lib/middleware/request-id.js +61 -61
  90. package/lib/middleware/request-log.js +168 -168
  91. package/lib/middleware/require-auth.js +104 -104
  92. package/lib/middleware/security-headers.js +121 -116
  93. package/lib/middleware/sse.js +166 -166
  94. package/lib/migrations.js +383 -383
  95. package/lib/mtls-ca.js +518 -518
  96. package/lib/mtls-engine-default.js +481 -481
  97. package/lib/network-dns.js +632 -632
  98. package/lib/network-heartbeat.js +290 -290
  99. package/lib/network-nts.js +574 -574
  100. package/lib/network-proxy.js +265 -265
  101. package/lib/network-tls.js +328 -328
  102. package/lib/network.js +233 -233
  103. package/lib/notify.js +612 -612
  104. package/lib/ntp-check.js +229 -229
  105. package/lib/numeric-bounds.js +111 -111
  106. package/lib/object-store/azure-blob-bucket-ops.js +349 -349
  107. package/lib/object-store/azure-blob.js +488 -488
  108. package/lib/object-store/gcs-bucket-ops.js +351 -351
  109. package/lib/object-store/gcs.js +519 -519
  110. package/lib/object-store/http-put.js +153 -153
  111. package/lib/object-store/index.js +197 -197
  112. package/lib/object-store/sigv4-bucket-ops.js +1092 -1092
  113. package/lib/object-store/sigv4.js +903 -903
  114. package/lib/observability.js +151 -151
  115. package/lib/otel-export.js +269 -269
  116. package/lib/pagination.js +464 -464
  117. package/lib/parsers/index.js +80 -80
  118. package/lib/parsers/safe-env.js +642 -642
  119. package/lib/parsers/safe-ini.js +292 -292
  120. package/lib/parsers/safe-toml.js +784 -784
  121. package/lib/parsers/safe-xml.js +390 -390
  122. package/lib/parsers/safe-yaml.js +1015 -1015
  123. package/lib/permissions.js +708 -708
  124. package/lib/pqc-agent.js +87 -87
  125. package/lib/pqc-gate.js +279 -279
  126. package/lib/protobuf-encoder.js +190 -190
  127. package/lib/protocol-dispatcher.js +161 -161
  128. package/lib/pubsub-redis.js +167 -167
  129. package/lib/pubsub.js +429 -429
  130. package/lib/queue-local.js +476 -476
  131. package/lib/queue-redis.js +745 -745
  132. package/lib/queue-sqs.js +319 -319
  133. package/lib/queue.js +695 -695
  134. package/lib/redis-client.js +519 -519
  135. package/lib/request-helpers.js +340 -340
  136. package/lib/restore-bundle.js +237 -237
  137. package/lib/restore-rollback.js +259 -259
  138. package/lib/restore.js +409 -409
  139. package/lib/retry.js +376 -376
  140. package/lib/router.js +748 -748
  141. package/lib/safe-async.js +735 -735
  142. package/lib/safe-buffer.js +237 -237
  143. package/lib/safe-json.js +541 -541
  144. package/lib/safe-schema.js +1266 -1266
  145. package/lib/safe-url.js +159 -159
  146. package/lib/scheduler.js +706 -706
  147. package/lib/security-assert.js +373 -373
  148. package/lib/seeders.js +618 -618
  149. package/lib/session.js +535 -478
  150. package/lib/slug.js +269 -269
  151. package/lib/ssrf-guard.js +401 -401
  152. package/lib/static.js +7 -5
  153. package/lib/storage.js +471 -471
  154. package/lib/subject.js +281 -281
  155. package/lib/template.js +791 -791
  156. package/lib/testing.js +798 -798
  157. package/lib/time.js +310 -310
  158. package/lib/totp.js +302 -302
  159. package/lib/tracing.js +494 -494
  160. package/lib/uuid.js +132 -132
  161. package/lib/validate-opts.js +340 -340
  162. package/lib/vault/index.js +308 -308
  163. package/lib/vault/rotate.js +784 -784
  164. package/lib/vault/wrap.js +296 -296
  165. package/lib/vendor/noble-ciphers.cjs +9 -9
  166. package/lib/webhook.js +595 -595
  167. package/lib/websocket.js +1048 -1048
  168. package/package.json +77 -77
  169. package/sbom.cyclonedx.json +7 -7
@@ -1,293 +1,293 @@
1
- "use strict";
2
- var observability = require("./observability");
3
-
4
- /**
5
- * Framework error base class + cross-module operational error classes.
6
- *
7
- * Two scopes live here:
8
- *
9
- * 1. FrameworkError — base class every framework error class extends.
10
- * Provides a single `instanceof FrameworkError` check (replacing the
11
- * scattered `isXxxError` boolean flags) plus a stable shape: { name,
12
- * code, message, isFrameworkError: true }.
13
- *
14
- * 2. Cross-module operational error classes — errors raised by more
15
- * than one module that share a logical domain (e.g. ObjectStoreError
16
- * raised by the 5 object-store adapters + the umbrella). These can't
17
- * live in the umbrella module because adapters would need a circular
18
- * require to access them. They live here, where every adapter can
19
- * import from the same place.
20
- *
21
- * 3. defineClass(name, opts) — factory that produces a FrameworkError
22
- * subclass with the standard shape. Eliminates the boilerplate that
23
- * every per-domain error class was duplicating across lib/.
24
- *
25
- * Per-domain VALIDATION errors (SafeSqlError, SafeJsonError, SafeBufferError,
26
- * SafeAsyncError, AtomicFileError, ChainWriterError, ClusterStorageError,
27
- * NotLeaderError, FrameworkSchemaError, *SafeError parser families) stay
28
- * co-located with their primitive module — they're single-owner, single-
29
- * domain, and the *-safe filename convention already declares ownership.
30
- * They extend FrameworkError so the unified `instanceof` check works.
31
- *
32
- * Operational error classes here all share:
33
- * { name, code, message, permanent: bool, isFrameworkError: true }
34
- * Adapters that talk over HTTP also carry `statusCode` for retry
35
- * classification.
36
- */
37
-
38
- class FrameworkError extends Error {
39
- constructor(message, code) {
40
- super(message);
41
- this.name = "FrameworkError";
42
- this.code = code || "framework/invalid";
43
- this.isFrameworkError = true;
44
- }
45
- }
46
-
47
- // defineClass — factory for the standard FrameworkError-subclass shape
48
- // every per-domain error followed by hand. Variants the factory covers:
49
- //
50
- // defineClass("MyError")
51
- // constructor: (code, message, permanent)
52
- // fields: name, permanent, isMyError
53
- //
54
- // defineClass("MyError", { withStatusCode: true })
55
- // constructor: (code, message, permanent, statusCode)
56
- // fields: + statusCode (HTTP-shaped operational errors)
57
- //
58
- // defineClass("MyError", { alwaysPermanent: true })
59
- // constructor: (code, message)
60
- // fields: permanent always true (auth failures, validation)
61
- //
62
- // defineClass("MyError", { withCause: true })
63
- // constructor: (code, message, cause)
64
- // fields: + cause (errors that wrap an upstream cause)
65
- //
66
- // Returns the constructor. Operators can attach extra static helpers
67
- // to it after creation if they need to.
68
- function defineClass(name, opts) {
69
- if (typeof name !== "string" || name.length === 0) {
70
- throw new Error("defineClass: name must be a non-empty string");
71
- }
72
- opts = opts || {};
73
- var alwaysPermanent = !!opts.alwaysPermanent;
74
- var withStatusCode = !!opts.withStatusCode;
75
- var withCause = !!opts.withCause;
76
- if (alwaysPermanent && (withStatusCode || withCause)) {
77
- throw new Error("defineClass: alwaysPermanent is mutually exclusive with withStatusCode / withCause");
78
- }
79
- var flagKey = "is" + name;
80
-
81
- // Generated class — uses an anonymous class expression so we can set
82
- // the constructor name explicitly via Object.defineProperty (matters
83
- // for stack traces and instanceof debugging).
84
- var GeneratedError = class extends FrameworkError {
85
- constructor(code, message, arg3, arg4) {
86
- super(message, code);
87
- this.name = name;
88
- this[flagKey] = true;
89
- if (alwaysPermanent) {
90
- this.permanent = true;
91
- } else if (withCause) {
92
- this.cause = arg3;
93
- } else {
94
- this.permanent = !!arg3;
95
- if (withStatusCode) this.statusCode = arg4;
96
- }
97
- // Framework-error class counter — routed into framework_errors_total
98
- // when a metrics registry is active. observability.event is safe to
99
- // call here even during framework-error's own load: observability's
100
- // dependencies on metrics + tracing are themselves lazy-required
101
- // and only resolve at first call (post-load).
102
- observability.safeEvent("error.construct", 1, { class: name });
103
- }
104
- };
105
- Object.defineProperty(GeneratedError, "name", { value: name, configurable: true });
106
- // Per-class factory — collapses the boilerplate every module used to
107
- // write as `function _err(code, msg, perm) { return new XxxError(...); }`.
108
- // Now: `var _err = XxxError.factory;` (one line, same call shape).
109
- GeneratedError.factory = function (code, message, arg3, arg4) {
110
- return new GeneratedError(code, message, arg3, arg4);
111
- };
112
- return GeneratedError;
113
- }
114
-
115
- // ---- Cross-module operational classes (defined via the factory) ----
116
-
117
- var ObjectStoreError = defineClass("ObjectStoreError", { withStatusCode: true });
118
- var LogStreamError = defineClass("LogStreamError", { withStatusCode: true });
119
- var QueueError = defineClass("QueueError");
120
- // RedisError covers transport (CONNECT/CONNECT_TIMEOUT/SOCKET/WRITE),
121
- // protocol parsing (PROTOCOL/BAD_URL/BAD_OPTS), command-level
122
- // (REDIS_REPLY/COMMAND_TIMEOUT), and lifecycle (CLOSED/RECONNECT_GAVE_UP).
123
- // Transient by default — operators wrap calls in retry/breaker. Bad-opts
124
- // and bad-URL paths surface as alwaysPermanent code names so retry sees
125
- // them and skips immediately rather than hammering a misconfig.
126
- var RedisError = defineClass("RedisError");
127
- var ExternalDbError = defineClass("ExternalDbError");
128
- var ClusterError = defineClass("ClusterError");
129
- var ClusterProviderError = defineClass("ClusterProviderError");
130
- var HandlerError = defineClass("HandlerError", { withCause: true });
131
- var StorageError = defineClass("StorageError");
132
- // AuthError covers password / passkey / TOTP failures at the framework
133
- // layer (lib/auth/*). Always permanent — auth failures are not transient
134
- // ("retry might work"); they're "this credential doesn't match" or
135
- // "this input was malformed".
136
- var AuthError = defineClass("AuthError", { alwaysPermanent: true });
137
- var JobsError = defineClass("JobsError");
138
- var SchedulerError = defineClass("SchedulerError");
139
- var SessionError = defineClass("SessionError");
140
- var SlugError = defineClass("SlugError", { alwaysPermanent: true });
141
- var WebhookError = defineClass("WebhookError", { alwaysPermanent: true });
142
- var ApiKeyError = defineClass("ApiKeyError", { alwaysPermanent: true });
143
- var PermissionsError = defineClass("PermissionsError", { alwaysPermanent: true });
144
- // CacheError is alwaysPermanent: bad opts / missing key / closed-state
145
- // errors are programming bugs, not transient. Backend-level transient
146
- // failures (cluster DB unavailable mid-fetch) become observability +
147
- // audit signals; they don't escape as exceptions to the caller.
148
- var CacheError = defineClass("CacheError", { alwaysPermanent: true });
149
- // SeederError is alwaysPermanent: load failures, bad-shape seed files,
150
- // missing deps, and cycle errors are programming bugs. Per-seed runtime
151
- // failures get wrapped in this class with the seed name in the message
152
- // — operators see "seeders/run-failed: 0042-x.js: <cause>" not a raw
153
- // driver exception.
154
- var SeederError = defineClass("SeederError", { alwaysPermanent: true });
155
- // I18nError is alwaysPermanent: bad locale tags, malformed translation
156
- // trees, missing-key in throw mode, and bad input to formatters are
157
- // programming bugs. Missing keys in default ("return-key") mode return
158
- // the key without throwing — runtime hot-path semantics, not error.
159
- var I18nError = defineClass("I18nError", { alwaysPermanent: true });
160
- // NotifyError is alwaysPermanent: bad opts, unknown channels, transport
161
- // contract violations are programming bugs. Per-send transient failures
162
- // (the kind retry can recover) are surfaced from the underlying transport
163
- // with their own shape; only after retry exhaustion does notify wrap
164
- // them into NotifyError SEND_FAILED — at that point they ARE permanent.
165
- var NotifyError = defineClass("NotifyError", { alwaysPermanent: true });
166
- // TestingError is alwaysPermanent: bad inputs to test helpers
167
- // (NaN clock, non-fn predicate, path-traversal tempDir prefix) and
168
- // waitFor timeouts are programming bugs at test-write time.
169
- var TestingError = defineClass("TestingError", { alwaysPermanent: true });
170
- // LockoutError is alwaysPermanent: misconfig at create() and bad keys at
171
- // recordFailure/recordSuccess/check/unlock are programming bugs. The
172
- // "account is currently locked" condition is NOT an error — recordFailure
173
- // returns { locked: true, lockedUntil } so the caller decides the response.
174
- var LockoutError = defineClass("LockoutError", { alwaysPermanent: true });
175
- // FileUploadError is alwaysPermanent: chunk-hash mismatch / oversized
176
- // chunk / oversized total file / manifest verification failure are all
177
- // caller-shape errors that won't succeed on retry. Operators wrap the
178
- // route handler with their own retry policy if they want client-side
179
- // resumability.
180
- var FileUploadError = defineClass("FileUploadError", { alwaysPermanent: true });
181
- // StaticServeError covers the download-side surface of staticServe.create.
182
- // withStatusCode: true so the framework can translate to operator-meaningful
183
- // HTTP responses (403 permission_denied, 404 not_found, 412 precondition_failed,
184
- // 416 range_not_satisfiable, 429 quota_exceeded, 451 retention_blocked).
185
- var StaticServeError = defineClass("StaticServeError", { withStatusCode: true });
186
- // GateContractError covers gate-contract violations (operator-supplied
187
- // gate is malformed / hook threw / runtime exceeded). alwaysPermanent
188
- // because these are programming-bug-shaped, not transient.
189
- var GateContractError = defineClass("GateContractError", { alwaysPermanent: true });
190
- // GuardCsvError covers csv-shape violations on the serialize / sanitize /
191
- // validate paths. alwaysPermanent — chunk-shape errors / formula-injection
192
- // attempts / schema drift are all caller-shape errors.
193
- var GuardCsvError = defineClass("GuardCsvError", { alwaysPermanent: true });
194
- // GuardAllError covers parity-check failures, exceptFor opt validation, and
195
- // override opt validation in the b.guardAll registry. alwaysPermanent — every
196
- // case is a config-time programming bug, not a transient runtime condition.
197
- var GuardAllError = defineClass("GuardAllError", { alwaysPermanent: true });
198
- // GuardHtmlError covers html-shape violations on validate / sanitize / escape
199
- // paths. alwaysPermanent — XSS attempts / dangerous-tag detections / DOM
200
- // clobbering are all caller-shape errors.
201
- var GuardHtmlError = defineClass("GuardHtmlError", { alwaysPermanent: true });
202
- // GuardSvgError covers svg-shape violations: dangerous tags (script /
203
- // foreignObject / use cross-origin / handler), DOCTYPE entity expansion
204
- // (billion laughs / XXE), animation-element attributeName targeting href,
205
- // SVGZ compressed payloads, SSRF-shape href references. alwaysPermanent.
206
- var GuardSvgError = defineClass("GuardSvgError", { alwaysPermanent: true });
207
- // GuardFilenameError covers filename-shape violations: path traversal,
208
- // null-byte truncation, Windows reserved names (CON / PRN / AUX / ...),
209
- // NTFS alternate data streams, leading/trailing whitespace + trailing dots
210
- // (Windows strips them silently), unicode bidi/RTLO file-name spoofing,
211
- // overlong UTF-8 encoding, length caps. alwaysPermanent.
212
- var GuardFilenameError = defineClass("GuardFilenameError", { alwaysPermanent: true });
213
- // GuardArchiveError covers archive-shape violations: zip-slip path
214
- // traversal, symlink + hardlink escape, decompression-ratio bombs,
215
- // nested-archive depth, file-count + total-size + per-entry-size caps,
216
- // magic-byte / format-claim mismatch, duplicate entries, encryption-
217
- // claim mismatch. alwaysPermanent.
218
- var GuardArchiveError = defineClass("GuardArchiveError", { alwaysPermanent: true });
219
- // GuardJsonError covers json-shape violations: prototype pollution
220
- // (__proto__/constructor/prototype), depth + breadth + key-count bombs,
221
- // duplicate keys, NaN/Infinity/comments (JSON5 extensions), bidi/null
222
- // in string values, numeric precision loss, total-size cap.
223
- // alwaysPermanent.
224
- var GuardJsonError = defineClass("GuardJsonError", { alwaysPermanent: true });
225
- // GuardYamlError covers yaml-shape violations: deserialization-tag
226
- // injection (!!python/object / !!java.util.HashMap / custom !Class),
227
- // anchor recursion (billion laughs), Norway-problem implicit booleans,
228
- // leading-zero octals, duplicate keys, multi-document streams, depth +
229
- // node-count + size caps. alwaysPermanent.
230
- var GuardYamlError = defineClass("GuardYamlError", { alwaysPermanent: true });
231
- // GuardXmlError covers xml-shape violations: XXE, billion-laughs entity
232
- // expansion, parameter entities, external DTD subset, XInclude, schema-
233
- // fetch (xsi:schemaLocation), processing instructions, CDATA, depth +
234
- // element-count + attribute-count caps. alwaysPermanent.
235
- var GuardXmlError = defineClass("GuardXmlError", { alwaysPermanent: true });
236
- // GuardMarkdownError covers markdown-shape violations: raw-HTML smuggling
237
- // (including the CVE-2026-30838 whitespace-in-tag-name bypass), dangerous
238
- // link / image / autolink / reference-link URL schemes (javascript: / data:
239
- // text/html / vbscript: / file: / jar:), entity-encoded scheme bypass,
240
- // front-matter payloads, ReDoS-prone emphasis / nesting / autolink mass,
241
- // HTML-comment smuggling, code-fence language injection, depth + link
242
- // count + image count + line count + size caps. alwaysPermanent.
243
- var GuardMarkdownError = defineClass("GuardMarkdownError", { alwaysPermanent: true });
244
- // GuardEmailError covers email-shape violations: SMTP smuggling (bare
245
- // CR/LF in body, embedded SMTP verbs), CRLF header injection, RFC 5321
246
- // /5322 local-part / domain / total-length caps, multi-@ violations,
247
- // IDN homograph spoofing (mixed-script confusable codepoints), display-
248
- // name vs envelope mismatch, bare IP literal addresses, comment syntax
249
- // in addresses, bidi/null/control chars in headers + addresses, header-
250
- // folding smuggling, BOM injection. alwaysPermanent.
251
- var GuardEmailError = defineClass("GuardEmailError", { alwaysPermanent: true });
252
-
253
- module.exports = {
254
- FrameworkError: FrameworkError,
255
- defineClass: defineClass,
256
- ObjectStoreError: ObjectStoreError,
257
- LogStreamError: LogStreamError,
258
- QueueError: QueueError,
259
- RedisError: RedisError,
260
- ExternalDbError: ExternalDbError,
261
- ClusterError: ClusterError,
262
- ClusterProviderError: ClusterProviderError,
263
- HandlerError: HandlerError,
264
- StorageError: StorageError,
265
- AuthError: AuthError,
266
- JobsError: JobsError,
267
- SchedulerError: SchedulerError,
268
- SessionError: SessionError,
269
- SlugError: SlugError,
270
- WebhookError: WebhookError,
271
- ApiKeyError: ApiKeyError,
272
- PermissionsError: PermissionsError,
273
- CacheError: CacheError,
274
- SeederError: SeederError,
275
- I18nError: I18nError,
276
- NotifyError: NotifyError,
277
- TestingError: TestingError,
278
- LockoutError: LockoutError,
279
- FileUploadError: FileUploadError,
280
- StaticServeError: StaticServeError,
281
- GateContractError: GateContractError,
282
- GuardCsvError: GuardCsvError,
283
- GuardAllError: GuardAllError,
284
- GuardHtmlError: GuardHtmlError,
285
- GuardSvgError: GuardSvgError,
286
- GuardFilenameError: GuardFilenameError,
287
- GuardArchiveError: GuardArchiveError,
288
- GuardJsonError: GuardJsonError,
289
- GuardYamlError: GuardYamlError,
290
- GuardXmlError: GuardXmlError,
291
- GuardMarkdownError: GuardMarkdownError,
292
- GuardEmailError: GuardEmailError,
293
- };
1
+ "use strict";
2
+ var observability = require("./observability");
3
+
4
+ /**
5
+ * Framework error base class + cross-module operational error classes.
6
+ *
7
+ * Two scopes live here:
8
+ *
9
+ * 1. FrameworkError — base class every framework error class extends.
10
+ * Provides a single `instanceof FrameworkError` check (replacing the
11
+ * scattered `isXxxError` boolean flags) plus a stable shape: { name,
12
+ * code, message, isFrameworkError: true }.
13
+ *
14
+ * 2. Cross-module operational error classes — errors raised by more
15
+ * than one module that share a logical domain (e.g. ObjectStoreError
16
+ * raised by the 5 object-store adapters + the umbrella). These can't
17
+ * live in the umbrella module because adapters would need a circular
18
+ * require to access them. They live here, where every adapter can
19
+ * import from the same place.
20
+ *
21
+ * 3. defineClass(name, opts) — factory that produces a FrameworkError
22
+ * subclass with the standard shape. Eliminates the boilerplate that
23
+ * every per-domain error class was duplicating across lib/.
24
+ *
25
+ * Per-domain VALIDATION errors (SafeSqlError, SafeJsonError, SafeBufferError,
26
+ * SafeAsyncError, AtomicFileError, ChainWriterError, ClusterStorageError,
27
+ * NotLeaderError, FrameworkSchemaError, *SafeError parser families) stay
28
+ * co-located with their primitive module — they're single-owner, single-
29
+ * domain, and the *-safe filename convention already declares ownership.
30
+ * They extend FrameworkError so the unified `instanceof` check works.
31
+ *
32
+ * Operational error classes here all share:
33
+ * { name, code, message, permanent: bool, isFrameworkError: true }
34
+ * Adapters that talk over HTTP also carry `statusCode` for retry
35
+ * classification.
36
+ */
37
+
38
+ class FrameworkError extends Error {
39
+ constructor(message, code) {
40
+ super(message);
41
+ this.name = "FrameworkError";
42
+ this.code = code || "framework/invalid";
43
+ this.isFrameworkError = true;
44
+ }
45
+ }
46
+
47
+ // defineClass — factory for the standard FrameworkError-subclass shape
48
+ // every per-domain error followed by hand. Variants the factory covers:
49
+ //
50
+ // defineClass("MyError")
51
+ // constructor: (code, message, permanent)
52
+ // fields: name, permanent, isMyError
53
+ //
54
+ // defineClass("MyError", { withStatusCode: true })
55
+ // constructor: (code, message, permanent, statusCode)
56
+ // fields: + statusCode (HTTP-shaped operational errors)
57
+ //
58
+ // defineClass("MyError", { alwaysPermanent: true })
59
+ // constructor: (code, message)
60
+ // fields: permanent always true (auth failures, validation)
61
+ //
62
+ // defineClass("MyError", { withCause: true })
63
+ // constructor: (code, message, cause)
64
+ // fields: + cause (errors that wrap an upstream cause)
65
+ //
66
+ // Returns the constructor. Operators can attach extra static helpers
67
+ // to it after creation if they need to.
68
+ function defineClass(name, opts) {
69
+ if (typeof name !== "string" || name.length === 0) {
70
+ throw new Error("defineClass: name must be a non-empty string");
71
+ }
72
+ opts = opts || {};
73
+ var alwaysPermanent = !!opts.alwaysPermanent;
74
+ var withStatusCode = !!opts.withStatusCode;
75
+ var withCause = !!opts.withCause;
76
+ if (alwaysPermanent && (withStatusCode || withCause)) {
77
+ throw new Error("defineClass: alwaysPermanent is mutually exclusive with withStatusCode / withCause");
78
+ }
79
+ var flagKey = "is" + name;
80
+
81
+ // Generated class — uses an anonymous class expression so we can set
82
+ // the constructor name explicitly via Object.defineProperty (matters
83
+ // for stack traces and instanceof debugging).
84
+ var GeneratedError = class extends FrameworkError {
85
+ constructor(code, message, arg3, arg4) {
86
+ super(message, code);
87
+ this.name = name;
88
+ this[flagKey] = true;
89
+ if (alwaysPermanent) {
90
+ this.permanent = true;
91
+ } else if (withCause) {
92
+ this.cause = arg3;
93
+ } else {
94
+ this.permanent = !!arg3;
95
+ if (withStatusCode) this.statusCode = arg4;
96
+ }
97
+ // Framework-error class counter — routed into framework_errors_total
98
+ // when a metrics registry is active. observability.event is safe to
99
+ // call here even during framework-error's own load: observability's
100
+ // dependencies on metrics + tracing are themselves lazy-required
101
+ // and only resolve at first call (post-load).
102
+ observability.safeEvent("error.construct", 1, { class: name });
103
+ }
104
+ };
105
+ Object.defineProperty(GeneratedError, "name", { value: name, configurable: true });
106
+ // Per-class factory — collapses the boilerplate every module used to
107
+ // write as `function _err(code, msg, perm) { return new XxxError(...); }`.
108
+ // Now: `var _err = XxxError.factory;` (one line, same call shape).
109
+ GeneratedError.factory = function (code, message, arg3, arg4) {
110
+ return new GeneratedError(code, message, arg3, arg4);
111
+ };
112
+ return GeneratedError;
113
+ }
114
+
115
+ // ---- Cross-module operational classes (defined via the factory) ----
116
+
117
+ var ObjectStoreError = defineClass("ObjectStoreError", { withStatusCode: true });
118
+ var LogStreamError = defineClass("LogStreamError", { withStatusCode: true });
119
+ var QueueError = defineClass("QueueError");
120
+ // RedisError covers transport (CONNECT/CONNECT_TIMEOUT/SOCKET/WRITE),
121
+ // protocol parsing (PROTOCOL/BAD_URL/BAD_OPTS), command-level
122
+ // (REDIS_REPLY/COMMAND_TIMEOUT), and lifecycle (CLOSED/RECONNECT_GAVE_UP).
123
+ // Transient by default — operators wrap calls in retry/breaker. Bad-opts
124
+ // and bad-URL paths surface as alwaysPermanent code names so retry sees
125
+ // them and skips immediately rather than hammering a misconfig.
126
+ var RedisError = defineClass("RedisError");
127
+ var ExternalDbError = defineClass("ExternalDbError");
128
+ var ClusterError = defineClass("ClusterError");
129
+ var ClusterProviderError = defineClass("ClusterProviderError");
130
+ var HandlerError = defineClass("HandlerError", { withCause: true });
131
+ var StorageError = defineClass("StorageError");
132
+ // AuthError covers password / passkey / TOTP failures at the framework
133
+ // layer (lib/auth/*). Always permanent — auth failures are not transient
134
+ // ("retry might work"); they're "this credential doesn't match" or
135
+ // "this input was malformed".
136
+ var AuthError = defineClass("AuthError", { alwaysPermanent: true });
137
+ var JobsError = defineClass("JobsError");
138
+ var SchedulerError = defineClass("SchedulerError");
139
+ var SessionError = defineClass("SessionError");
140
+ var SlugError = defineClass("SlugError", { alwaysPermanent: true });
141
+ var WebhookError = defineClass("WebhookError", { alwaysPermanent: true });
142
+ var ApiKeyError = defineClass("ApiKeyError", { alwaysPermanent: true });
143
+ var PermissionsError = defineClass("PermissionsError", { alwaysPermanent: true });
144
+ // CacheError is alwaysPermanent: bad opts / missing key / closed-state
145
+ // errors are programming bugs, not transient. Backend-level transient
146
+ // failures (cluster DB unavailable mid-fetch) become observability +
147
+ // audit signals; they don't escape as exceptions to the caller.
148
+ var CacheError = defineClass("CacheError", { alwaysPermanent: true });
149
+ // SeederError is alwaysPermanent: load failures, bad-shape seed files,
150
+ // missing deps, and cycle errors are programming bugs. Per-seed runtime
151
+ // failures get wrapped in this class with the seed name in the message
152
+ // — operators see "seeders/run-failed: 0042-x.js: <cause>" not a raw
153
+ // driver exception.
154
+ var SeederError = defineClass("SeederError", { alwaysPermanent: true });
155
+ // I18nError is alwaysPermanent: bad locale tags, malformed translation
156
+ // trees, missing-key in throw mode, and bad input to formatters are
157
+ // programming bugs. Missing keys in default ("return-key") mode return
158
+ // the key without throwing — runtime hot-path semantics, not error.
159
+ var I18nError = defineClass("I18nError", { alwaysPermanent: true });
160
+ // NotifyError is alwaysPermanent: bad opts, unknown channels, transport
161
+ // contract violations are programming bugs. Per-send transient failures
162
+ // (the kind retry can recover) are surfaced from the underlying transport
163
+ // with their own shape; only after retry exhaustion does notify wrap
164
+ // them into NotifyError SEND_FAILED — at that point they ARE permanent.
165
+ var NotifyError = defineClass("NotifyError", { alwaysPermanent: true });
166
+ // TestingError is alwaysPermanent: bad inputs to test helpers
167
+ // (NaN clock, non-fn predicate, path-traversal tempDir prefix) and
168
+ // waitFor timeouts are programming bugs at test-write time.
169
+ var TestingError = defineClass("TestingError", { alwaysPermanent: true });
170
+ // LockoutError is alwaysPermanent: misconfig at create() and bad keys at
171
+ // recordFailure/recordSuccess/check/unlock are programming bugs. The
172
+ // "account is currently locked" condition is NOT an error — recordFailure
173
+ // returns { locked: true, lockedUntil } so the caller decides the response.
174
+ var LockoutError = defineClass("LockoutError", { alwaysPermanent: true });
175
+ // FileUploadError is alwaysPermanent: chunk-hash mismatch / oversized
176
+ // chunk / oversized total file / manifest verification failure are all
177
+ // caller-shape errors that won't succeed on retry. Operators wrap the
178
+ // route handler with their own retry policy if they want client-side
179
+ // resumability.
180
+ var FileUploadError = defineClass("FileUploadError", { alwaysPermanent: true });
181
+ // StaticServeError covers the download-side surface of staticServe.create.
182
+ // withStatusCode: true so the framework can translate to operator-meaningful
183
+ // HTTP responses (403 permission_denied, 404 not_found, 412 precondition_failed,
184
+ // 416 range_not_satisfiable, 429 quota_exceeded, 451 retention_blocked).
185
+ var StaticServeError = defineClass("StaticServeError", { withStatusCode: true });
186
+ // GateContractError covers gate-contract violations (operator-supplied
187
+ // gate is malformed / hook threw / runtime exceeded). alwaysPermanent
188
+ // because these are programming-bug-shaped, not transient.
189
+ var GateContractError = defineClass("GateContractError", { alwaysPermanent: true });
190
+ // GuardCsvError covers csv-shape violations on the serialize / sanitize /
191
+ // validate paths. alwaysPermanent — chunk-shape errors / formula-injection
192
+ // attempts / schema drift are all caller-shape errors.
193
+ var GuardCsvError = defineClass("GuardCsvError", { alwaysPermanent: true });
194
+ // GuardAllError covers parity-check failures, exceptFor opt validation, and
195
+ // override opt validation in the b.guardAll registry. alwaysPermanent — every
196
+ // case is a config-time programming bug, not a transient runtime condition.
197
+ var GuardAllError = defineClass("GuardAllError", { alwaysPermanent: true });
198
+ // GuardHtmlError covers html-shape violations on validate / sanitize / escape
199
+ // paths. alwaysPermanent — XSS attempts / dangerous-tag detections / DOM
200
+ // clobbering are all caller-shape errors.
201
+ var GuardHtmlError = defineClass("GuardHtmlError", { alwaysPermanent: true });
202
+ // GuardSvgError covers svg-shape violations: dangerous tags (script /
203
+ // foreignObject / use cross-origin / handler), DOCTYPE entity expansion
204
+ // (billion laughs / XXE), animation-element attributeName targeting href,
205
+ // SVGZ compressed payloads, SSRF-shape href references. alwaysPermanent.
206
+ var GuardSvgError = defineClass("GuardSvgError", { alwaysPermanent: true });
207
+ // GuardFilenameError covers filename-shape violations: path traversal,
208
+ // null-byte truncation, Windows reserved names (CON / PRN / AUX / ...),
209
+ // NTFS alternate data streams, leading/trailing whitespace + trailing dots
210
+ // (Windows strips them silently), unicode bidi/RTLO file-name spoofing,
211
+ // overlong UTF-8 encoding, length caps. alwaysPermanent.
212
+ var GuardFilenameError = defineClass("GuardFilenameError", { alwaysPermanent: true });
213
+ // GuardArchiveError covers archive-shape violations: zip-slip path
214
+ // traversal, symlink + hardlink escape, decompression-ratio bombs,
215
+ // nested-archive depth, file-count + total-size + per-entry-size caps,
216
+ // magic-byte / format-claim mismatch, duplicate entries, encryption-
217
+ // claim mismatch. alwaysPermanent.
218
+ var GuardArchiveError = defineClass("GuardArchiveError", { alwaysPermanent: true });
219
+ // GuardJsonError covers json-shape violations: prototype pollution
220
+ // (__proto__/constructor/prototype), depth + breadth + key-count bombs,
221
+ // duplicate keys, NaN/Infinity/comments (JSON5 extensions), bidi/null
222
+ // in string values, numeric precision loss, total-size cap.
223
+ // alwaysPermanent.
224
+ var GuardJsonError = defineClass("GuardJsonError", { alwaysPermanent: true });
225
+ // GuardYamlError covers yaml-shape violations: deserialization-tag
226
+ // injection (!!python/object / !!java.util.HashMap / custom !Class),
227
+ // anchor recursion (billion laughs), Norway-problem implicit booleans,
228
+ // leading-zero octals, duplicate keys, multi-document streams, depth +
229
+ // node-count + size caps. alwaysPermanent.
230
+ var GuardYamlError = defineClass("GuardYamlError", { alwaysPermanent: true });
231
+ // GuardXmlError covers xml-shape violations: XXE, billion-laughs entity
232
+ // expansion, parameter entities, external DTD subset, XInclude, schema-
233
+ // fetch (xsi:schemaLocation), processing instructions, CDATA, depth +
234
+ // element-count + attribute-count caps. alwaysPermanent.
235
+ var GuardXmlError = defineClass("GuardXmlError", { alwaysPermanent: true });
236
+ // GuardMarkdownError covers markdown-shape violations: raw-HTML smuggling
237
+ // (including the CVE-2026-30838 whitespace-in-tag-name bypass), dangerous
238
+ // link / image / autolink / reference-link URL schemes (javascript: / data:
239
+ // text/html / vbscript: / file: / jar:), entity-encoded scheme bypass,
240
+ // front-matter payloads, ReDoS-prone emphasis / nesting / autolink mass,
241
+ // HTML-comment smuggling, code-fence language injection, depth + link
242
+ // count + image count + line count + size caps. alwaysPermanent.
243
+ var GuardMarkdownError = defineClass("GuardMarkdownError", { alwaysPermanent: true });
244
+ // GuardEmailError covers email-shape violations: SMTP smuggling (bare
245
+ // CR/LF in body, embedded SMTP verbs), CRLF header injection, RFC 5321
246
+ // /5322 local-part / domain / total-length caps, multi-@ violations,
247
+ // IDN homograph spoofing (mixed-script confusable codepoints), display-
248
+ // name vs envelope mismatch, bare IP literal addresses, comment syntax
249
+ // in addresses, bidi/null/control chars in headers + addresses, header-
250
+ // folding smuggling, BOM injection. alwaysPermanent.
251
+ var GuardEmailError = defineClass("GuardEmailError", { alwaysPermanent: true });
252
+
253
+ module.exports = {
254
+ FrameworkError: FrameworkError,
255
+ defineClass: defineClass,
256
+ ObjectStoreError: ObjectStoreError,
257
+ LogStreamError: LogStreamError,
258
+ QueueError: QueueError,
259
+ RedisError: RedisError,
260
+ ExternalDbError: ExternalDbError,
261
+ ClusterError: ClusterError,
262
+ ClusterProviderError: ClusterProviderError,
263
+ HandlerError: HandlerError,
264
+ StorageError: StorageError,
265
+ AuthError: AuthError,
266
+ JobsError: JobsError,
267
+ SchedulerError: SchedulerError,
268
+ SessionError: SessionError,
269
+ SlugError: SlugError,
270
+ WebhookError: WebhookError,
271
+ ApiKeyError: ApiKeyError,
272
+ PermissionsError: PermissionsError,
273
+ CacheError: CacheError,
274
+ SeederError: SeederError,
275
+ I18nError: I18nError,
276
+ NotifyError: NotifyError,
277
+ TestingError: TestingError,
278
+ LockoutError: LockoutError,
279
+ FileUploadError: FileUploadError,
280
+ StaticServeError: StaticServeError,
281
+ GateContractError: GateContractError,
282
+ GuardCsvError: GuardCsvError,
283
+ GuardAllError: GuardAllError,
284
+ GuardHtmlError: GuardHtmlError,
285
+ GuardSvgError: GuardSvgError,
286
+ GuardFilenameError: GuardFilenameError,
287
+ GuardArchiveError: GuardArchiveError,
288
+ GuardJsonError: GuardJsonError,
289
+ GuardYamlError: GuardYamlError,
290
+ GuardXmlError: GuardXmlError,
291
+ GuardMarkdownError: GuardMarkdownError,
292
+ GuardEmailError: GuardEmailError,
293
+ };