@blamejs/core 0.7.18 → 0.7.19

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 (167) hide show
  1. package/CHANGELOG.md +425 -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 +315 -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 +316 -316
  84. package/lib/middleware/db-role-for.js +264 -264
  85. package/lib/middleware/health.js +392 -392
  86. package/lib/middleware/index.js +82 -79
  87. package/lib/middleware/rate-limit.js +358 -358
  88. package/lib/middleware/request-id.js +61 -61
  89. package/lib/middleware/request-log.js +168 -168
  90. package/lib/middleware/require-auth.js +104 -104
  91. package/lib/middleware/security-headers.js +116 -116
  92. package/lib/middleware/sse.js +166 -166
  93. package/lib/migrations.js +383 -383
  94. package/lib/mtls-ca.js +518 -518
  95. package/lib/mtls-engine-default.js +481 -481
  96. package/lib/network-dns.js +632 -632
  97. package/lib/network-heartbeat.js +290 -290
  98. package/lib/network-nts.js +574 -574
  99. package/lib/network-proxy.js +265 -265
  100. package/lib/network-tls.js +328 -328
  101. package/lib/network.js +233 -233
  102. package/lib/notify.js +612 -612
  103. package/lib/ntp-check.js +229 -229
  104. package/lib/numeric-bounds.js +111 -111
  105. package/lib/object-store/azure-blob-bucket-ops.js +349 -349
  106. package/lib/object-store/azure-blob.js +488 -488
  107. package/lib/object-store/gcs-bucket-ops.js +351 -351
  108. package/lib/object-store/gcs.js +519 -519
  109. package/lib/object-store/http-put.js +153 -153
  110. package/lib/object-store/index.js +197 -197
  111. package/lib/object-store/sigv4-bucket-ops.js +1092 -1092
  112. package/lib/object-store/sigv4.js +903 -903
  113. package/lib/observability.js +151 -151
  114. package/lib/otel-export.js +269 -269
  115. package/lib/pagination.js +464 -464
  116. package/lib/parsers/index.js +80 -80
  117. package/lib/parsers/safe-env.js +642 -642
  118. package/lib/parsers/safe-ini.js +292 -292
  119. package/lib/parsers/safe-toml.js +784 -784
  120. package/lib/parsers/safe-xml.js +390 -390
  121. package/lib/parsers/safe-yaml.js +1015 -1015
  122. package/lib/permissions.js +708 -708
  123. package/lib/pqc-agent.js +87 -87
  124. package/lib/pqc-gate.js +279 -279
  125. package/lib/protobuf-encoder.js +190 -190
  126. package/lib/protocol-dispatcher.js +161 -161
  127. package/lib/pubsub-redis.js +167 -167
  128. package/lib/pubsub.js +429 -429
  129. package/lib/queue-local.js +476 -476
  130. package/lib/queue-redis.js +745 -745
  131. package/lib/queue-sqs.js +319 -319
  132. package/lib/queue.js +695 -695
  133. package/lib/redis-client.js +519 -519
  134. package/lib/request-helpers.js +340 -340
  135. package/lib/restore-bundle.js +237 -237
  136. package/lib/restore-rollback.js +259 -259
  137. package/lib/restore.js +409 -409
  138. package/lib/retry.js +376 -376
  139. package/lib/router.js +748 -748
  140. package/lib/safe-async.js +735 -735
  141. package/lib/safe-buffer.js +237 -237
  142. package/lib/safe-json.js +541 -541
  143. package/lib/safe-schema.js +1266 -1266
  144. package/lib/safe-url.js +159 -159
  145. package/lib/scheduler.js +706 -706
  146. package/lib/security-assert.js +373 -373
  147. package/lib/seeders.js +618 -618
  148. package/lib/session.js +535 -478
  149. package/lib/slug.js +269 -269
  150. package/lib/ssrf-guard.js +401 -401
  151. package/lib/storage.js +471 -471
  152. package/lib/subject.js +281 -281
  153. package/lib/template.js +791 -791
  154. package/lib/testing.js +798 -798
  155. package/lib/time.js +310 -310
  156. package/lib/totp.js +302 -302
  157. package/lib/tracing.js +494 -494
  158. package/lib/uuid.js +132 -132
  159. package/lib/validate-opts.js +340 -340
  160. package/lib/vault/index.js +308 -308
  161. package/lib/vault/rotate.js +784 -784
  162. package/lib/vault/wrap.js +296 -296
  163. package/lib/vendor/noble-ciphers.cjs +9 -9
  164. package/lib/webhook.js +595 -595
  165. package/lib/websocket.js +1048 -1048
  166. package/package.json +77 -77
  167. 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
+ };