@blamejs/core 0.8.42 → 0.8.49

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 (222) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/README.md +10 -10
  3. package/index.js +52 -0
  4. package/lib/a2a.js +159 -34
  5. package/lib/acme.js +762 -0
  6. package/lib/ai-pref.js +166 -43
  7. package/lib/api-key.js +108 -47
  8. package/lib/api-snapshot.js +157 -40
  9. package/lib/app-shutdown.js +113 -77
  10. package/lib/archive.js +337 -40
  11. package/lib/arg-parser.js +697 -0
  12. package/lib/asyncapi.js +99 -55
  13. package/lib/atomic-file.js +465 -104
  14. package/lib/audit-chain.js +123 -34
  15. package/lib/audit-daily-review.js +389 -0
  16. package/lib/audit-sign.js +302 -56
  17. package/lib/audit-tools.js +412 -63
  18. package/lib/audit.js +656 -35
  19. package/lib/auth/jwt-external.js +17 -0
  20. package/lib/auth/oauth.js +7 -0
  21. package/lib/auth-bot-challenge.js +505 -0
  22. package/lib/auth-header.js +92 -25
  23. package/lib/backup/bundle.js +26 -0
  24. package/lib/backup/index.js +512 -89
  25. package/lib/backup/manifest.js +168 -7
  26. package/lib/break-glass.js +415 -39
  27. package/lib/budr.js +103 -30
  28. package/lib/bundler.js +86 -66
  29. package/lib/cache.js +192 -72
  30. package/lib/chain-writer.js +65 -40
  31. package/lib/circuit-breaker.js +56 -33
  32. package/lib/cli-helpers.js +106 -75
  33. package/lib/cli.js +6 -30
  34. package/lib/cloud-events.js +99 -32
  35. package/lib/cluster-storage.js +162 -37
  36. package/lib/cluster.js +340 -49
  37. package/lib/codepoint-class.js +66 -0
  38. package/lib/compliance.js +424 -24
  39. package/lib/config-drift.js +111 -46
  40. package/lib/config.js +94 -40
  41. package/lib/consent.js +165 -18
  42. package/lib/constants.js +1 -0
  43. package/lib/content-credentials.js +153 -48
  44. package/lib/cookies.js +154 -62
  45. package/lib/credential-hash.js +133 -61
  46. package/lib/crypto-field.js +702 -18
  47. package/lib/crypto-hpke.js +256 -0
  48. package/lib/crypto.js +744 -22
  49. package/lib/csv.js +178 -35
  50. package/lib/daemon.js +456 -0
  51. package/lib/dark-patterns.js +186 -55
  52. package/lib/db-query.js +79 -2
  53. package/lib/db.js +1431 -60
  54. package/lib/ddl-change-control.js +523 -0
  55. package/lib/deprecate.js +195 -40
  56. package/lib/dev.js +82 -39
  57. package/lib/dora.js +67 -48
  58. package/lib/dr-runbook.js +368 -0
  59. package/lib/dsr.js +142 -11
  60. package/lib/dual-control.js +91 -56
  61. package/lib/events.js +120 -41
  62. package/lib/external-db-migrate.js +192 -2
  63. package/lib/external-db.js +795 -50
  64. package/lib/fapi2.js +122 -1
  65. package/lib/fda-21cfr11.js +395 -0
  66. package/lib/fdx.js +132 -2
  67. package/lib/file-type.js +87 -0
  68. package/lib/file-upload.js +93 -0
  69. package/lib/flag.js +82 -20
  70. package/lib/forms.js +132 -29
  71. package/lib/framework-error.js +169 -0
  72. package/lib/framework-schema.js +163 -35
  73. package/lib/gate-contract.js +849 -175
  74. package/lib/graphql-federation.js +68 -7
  75. package/lib/guard-all.js +172 -55
  76. package/lib/guard-archive.js +286 -124
  77. package/lib/guard-auth.js +194 -21
  78. package/lib/guard-cidr.js +190 -28
  79. package/lib/guard-csv.js +397 -51
  80. package/lib/guard-domain.js +213 -91
  81. package/lib/guard-email.js +236 -29
  82. package/lib/guard-filename.js +307 -75
  83. package/lib/guard-graphql.js +263 -30
  84. package/lib/guard-html.js +310 -116
  85. package/lib/guard-image.js +243 -30
  86. package/lib/guard-json.js +260 -54
  87. package/lib/guard-jsonpath.js +235 -23
  88. package/lib/guard-jwt.js +284 -30
  89. package/lib/guard-markdown.js +204 -22
  90. package/lib/guard-mime.js +190 -26
  91. package/lib/guard-oauth.js +277 -28
  92. package/lib/guard-pdf.js +251 -27
  93. package/lib/guard-regex.js +226 -18
  94. package/lib/guard-shell.js +229 -26
  95. package/lib/guard-svg.js +177 -10
  96. package/lib/guard-template.js +232 -21
  97. package/lib/guard-time.js +195 -29
  98. package/lib/guard-uuid.js +189 -30
  99. package/lib/guard-xml.js +259 -36
  100. package/lib/guard-yaml.js +241 -44
  101. package/lib/honeytoken.js +63 -27
  102. package/lib/html-balance.js +83 -0
  103. package/lib/http-client.js +486 -59
  104. package/lib/http-message-signature.js +582 -0
  105. package/lib/i18n.js +102 -49
  106. package/lib/iab-mspa.js +112 -32
  107. package/lib/iab-tcf.js +107 -2
  108. package/lib/inbox.js +90 -52
  109. package/lib/keychain.js +865 -0
  110. package/lib/legal-hold.js +374 -0
  111. package/lib/local-db-thin.js +320 -0
  112. package/lib/log-stream.js +281 -51
  113. package/lib/log.js +184 -86
  114. package/lib/mail-bounce.js +107 -62
  115. package/lib/mail.js +295 -58
  116. package/lib/mcp.js +108 -27
  117. package/lib/metrics.js +98 -89
  118. package/lib/middleware/age-gate.js +36 -0
  119. package/lib/middleware/ai-act-disclosure.js +37 -0
  120. package/lib/middleware/api-encrypt.js +45 -0
  121. package/lib/middleware/assetlinks.js +40 -0
  122. package/lib/middleware/asyncapi-serve.js +35 -0
  123. package/lib/middleware/attach-user.js +40 -0
  124. package/lib/middleware/bearer-auth.js +40 -0
  125. package/lib/middleware/body-parser.js +230 -0
  126. package/lib/middleware/bot-disclose.js +34 -0
  127. package/lib/middleware/bot-guard.js +39 -0
  128. package/lib/middleware/compression.js +37 -0
  129. package/lib/middleware/cookies.js +32 -0
  130. package/lib/middleware/cors.js +40 -0
  131. package/lib/middleware/csp-nonce.js +40 -0
  132. package/lib/middleware/csp-report.js +34 -0
  133. package/lib/middleware/csrf-protect.js +43 -0
  134. package/lib/middleware/daily-byte-quota.js +53 -85
  135. package/lib/middleware/db-role-for.js +40 -0
  136. package/lib/middleware/dpop.js +40 -0
  137. package/lib/middleware/error-handler.js +37 -14
  138. package/lib/middleware/fetch-metadata.js +39 -0
  139. package/lib/middleware/flag-context.js +34 -0
  140. package/lib/middleware/gpc.js +33 -0
  141. package/lib/middleware/headers.js +35 -0
  142. package/lib/middleware/health.js +46 -0
  143. package/lib/middleware/host-allowlist.js +30 -0
  144. package/lib/middleware/network-allowlist.js +38 -0
  145. package/lib/middleware/openapi-serve.js +34 -0
  146. package/lib/middleware/rate-limit.js +160 -18
  147. package/lib/middleware/request-id.js +36 -18
  148. package/lib/middleware/request-log.js +37 -0
  149. package/lib/middleware/require-aal.js +29 -0
  150. package/lib/middleware/require-auth.js +32 -0
  151. package/lib/middleware/require-bound-key.js +41 -0
  152. package/lib/middleware/require-content-type.js +32 -0
  153. package/lib/middleware/require-methods.js +27 -0
  154. package/lib/middleware/require-mtls.js +33 -0
  155. package/lib/middleware/require-step-up.js +37 -0
  156. package/lib/middleware/security-headers.js +44 -0
  157. package/lib/middleware/security-txt.js +38 -0
  158. package/lib/middleware/span-http-server.js +37 -0
  159. package/lib/middleware/sse.js +36 -0
  160. package/lib/middleware/trace-log-correlation.js +33 -0
  161. package/lib/middleware/trace-propagate.js +32 -0
  162. package/lib/middleware/tus-upload.js +90 -0
  163. package/lib/middleware/web-app-manifest.js +53 -0
  164. package/lib/mtls-ca.js +100 -70
  165. package/lib/network-byte-quota.js +308 -0
  166. package/lib/network-heartbeat.js +135 -0
  167. package/lib/network-tls.js +534 -4
  168. package/lib/network.js +103 -0
  169. package/lib/notify.js +114 -43
  170. package/lib/ntp-check.js +192 -51
  171. package/lib/observability.js +145 -47
  172. package/lib/openapi.js +90 -44
  173. package/lib/outbox.js +99 -1
  174. package/lib/pagination.js +168 -86
  175. package/lib/parsers/index.js +16 -5
  176. package/lib/permissions.js +93 -40
  177. package/lib/pqc-agent.js +84 -8
  178. package/lib/pqc-software.js +94 -60
  179. package/lib/process-spawn.js +95 -21
  180. package/lib/pubsub.js +96 -66
  181. package/lib/queue.js +375 -54
  182. package/lib/redact.js +793 -21
  183. package/lib/render.js +139 -47
  184. package/lib/request-helpers.js +485 -121
  185. package/lib/restore-bundle.js +142 -39
  186. package/lib/restore-rollback.js +136 -45
  187. package/lib/retention.js +178 -50
  188. package/lib/retry.js +116 -33
  189. package/lib/router.js +475 -23
  190. package/lib/safe-async.js +543 -94
  191. package/lib/safe-buffer.js +337 -41
  192. package/lib/safe-json.js +467 -62
  193. package/lib/safe-jsonpath.js +285 -0
  194. package/lib/safe-schema.js +631 -87
  195. package/lib/safe-sql.js +221 -59
  196. package/lib/safe-url.js +278 -46
  197. package/lib/sandbox-worker.js +135 -0
  198. package/lib/sandbox.js +358 -0
  199. package/lib/scheduler.js +135 -70
  200. package/lib/self-update.js +647 -0
  201. package/lib/session-device-binding.js +431 -0
  202. package/lib/session.js +259 -49
  203. package/lib/slug.js +138 -26
  204. package/lib/ssrf-guard.js +316 -56
  205. package/lib/storage.js +433 -70
  206. package/lib/subject.js +405 -23
  207. package/lib/template.js +148 -8
  208. package/lib/tenant-quota.js +545 -0
  209. package/lib/testing.js +440 -53
  210. package/lib/time.js +291 -23
  211. package/lib/tls-exporter.js +239 -0
  212. package/lib/tracing.js +90 -74
  213. package/lib/uuid.js +97 -22
  214. package/lib/vault/index.js +284 -22
  215. package/lib/vault/seal-pem-file.js +66 -0
  216. package/lib/watcher.js +368 -0
  217. package/lib/webhook.js +196 -63
  218. package/lib/websocket.js +393 -68
  219. package/lib/wiki-concepts.js +338 -0
  220. package/lib/worker-pool.js +464 -0
  221. package/package.json +3 -3
  222. package/sbom.cyclonedx.json +7 -7
@@ -1,42 +1,30 @@
1
1
  "use strict";
2
2
  /**
3
- * Framework-state SQL dispatch — runs against local SQLite in single-
4
- * node mode and against external-db in cluster mode.
5
- *
6
- * audit / consent / sessions / queue / subject all read and write the
7
- * framework's own tables (audit_log, consent_log, …). In single-node
8
- * mode those tables live in the framework's own SQLite (lib/db.js).
9
- * In cluster mode they live in the operator-supplied external-db with
10
- * a `_blamejs_` prefix to avoid colliding with app tables.
11
- *
12
- * This module is the dispatch primitive. Callers write SQL once using
13
- * unprefixed table names + `?` placeholders; the dispatcher translates
14
- * to the active backend's flavor:
15
- *
16
- * single-node local SQLite via db().prepare(sql).run/get/all(...)
17
- * cluster (sqlite) externalDb.query(sql, params) ? placeholders
18
- * cluster (postgres) externalDb.query(translated, params) $1, $2,
19
- *
20
- * Tables are translated through frameworkSchema.tableName so callers
21
- * use logical names (audit_log) and the resolved name is automatically
22
- * prefixed in cluster mode (_blamejs_audit_log).
23
- *
24
- * The dispatcher is async-only the operator's external-db driver
25
- * is async, and even local-SQLite calls return a resolved Promise to
26
- * keep the call shape uniform. Callers `await` this module's methods;
27
- * audit / consent / queue / session / subject all thread `async` /
28
- * `await` through their own surfaces to match.
29
- *
30
- * Public API:
31
- * await execute(sql, params?) { rows, rowCount }
32
- * tableName(local) external-db prefixed name (or unchanged
33
- * in single-node mode)
34
- * placeholderize(sql, dialect) `?` to `$N` for postgres; passthrough
35
- * for sqlite
36
- * resolveTables(sql) rewrites bare unprefixed table names
37
- * in cluster mode (only the framework's
38
- * known tables are rewritten — operator
39
- * app-data SQL is unaffected)
3
+ * @module b.clusterStorage
4
+ * @nav Production
5
+ * @title Cluster Storage
6
+ *
7
+ * @intro
8
+ * Cluster-aware framework-state SQL dispatch runs against the
9
+ * framework's local SQLite in single-node mode and against the
10
+ * operator-supplied external DB in cluster mode. Distributed shared
11
+ * state for audit, consent, sessions, queue, and subject tables;
12
+ * write paths carry the cluster's fencing token so a stale leader
13
+ * cannot extend a chain after losing its lease.
14
+ *
15
+ * Callers write SQL once using unprefixed logical table names
16
+ * (`audit_log`, `consent_log`, …) and `?` placeholders. The
17
+ * dispatcher rewrites bare framework tables to their `_blamejs_`-
18
+ * prefixed cluster names and translates `?` to `$N` for Postgres.
19
+ * Unknown identifiers pass through unchanged so operator-written
20
+ * migrations and app-data SQL are never touched.
21
+ *
22
+ * The dispatcher is async-only. Even single-node SQLite calls
23
+ * return a resolved Promise so the call shape stays uniform across
24
+ * deployment topologiescallers `await` every method.
25
+ *
26
+ * @card
27
+ * Cluster-aware framework-state SQL dispatch runs against the framework's local SQLite in single-node mode and against the operator-supplied external DB in cluster mode.
40
28
  */
41
29
 
42
30
  var cluster = require("./cluster");
@@ -59,6 +47,28 @@ var _localDb = lazyRequire(function () { return require("./db"); });
59
47
 
60
48
  // ---- Table-name resolution ----
61
49
 
50
+ /**
51
+ * @primitive b.clusterStorage.tableName
52
+ * @signature b.clusterStorage.tableName(local)
53
+ * @since 0.1.9
54
+ * @status stable
55
+ * @related b.clusterStorage.resolveTables, b.cluster.isClusterMode
56
+ *
57
+ * Resolve a logical framework table name to the active backend's
58
+ * concrete name. In single-node mode returns the input unchanged; in
59
+ * cluster mode returns the `_blamejs_`-prefixed name from the
60
+ * framework-schema mapping (e.g. `audit_log` to `_blamejs_audit_log`).
61
+ * Use this when composing SQL by hand against framework tables — the
62
+ * `execute` family rewrites bare names automatically, but ad-hoc DDL
63
+ * or admin queries that reference a specific table need the resolved
64
+ * name explicitly.
65
+ *
66
+ * @example
67
+ * var b = require("@blamejs/core");
68
+ * var name = b.clusterStorage.tableName("audit_log");
69
+ * // → "audit_log" (single-node)
70
+ * // → "_blamejs_audit_log" (cluster mode)
71
+ */
62
72
  function tableName(local) {
63
73
  if (cluster.isClusterMode()) return frameworkSchema.tableName(local);
64
74
  return local;
@@ -137,6 +147,30 @@ var _REWRITE_TABLE = (function () {
137
147
  // (audit_log, consent_log, …) — anything else passes through unchanged
138
148
  // so app-data SQL composed via this dispatcher (or operator-written
139
149
  // migrations) isn't rewritten by accident.
150
+ /**
151
+ * @primitive b.clusterStorage.resolveTables
152
+ * @signature b.clusterStorage.resolveTables(sql)
153
+ * @since 0.1.9
154
+ * @status stable
155
+ * @related b.clusterStorage.tableName, b.clusterStorage.execute
156
+ *
157
+ * Rewrite bare framework table names in a SQL string to their
158
+ * cluster-mode `_blamejs_`-prefixed equivalents. Word-boundary scan;
159
+ * only exact identifier matches are rewritten — substrings,
160
+ * column-qualified names, and operator app tables pass through
161
+ * untouched. In single-node mode the SQL is returned unchanged. The
162
+ * `execute` family calls this internally; callers reach for it
163
+ * directly only when running raw SQL through a different path
164
+ * (admin tooling, migration runners).
165
+ *
166
+ * @example
167
+ * var b = require("@blamejs/core");
168
+ * var sql = b.clusterStorage.resolveTables(
169
+ * "SELECT id FROM audit_log WHERE counter > ?"
170
+ * );
171
+ * // → "SELECT id FROM audit_log WHERE counter > ?" (single-node)
172
+ * // → "SELECT id FROM _blamejs_audit_log WHERE counter > ?" (cluster)
173
+ */
140
174
  function resolveTables(sql) {
141
175
  if (!cluster.isClusterMode()) return sql;
142
176
  var translated = sql;
@@ -154,6 +188,29 @@ function resolveTables(sql) {
154
188
  // time so callers always write `?` and the right thing happens per
155
189
  // dialect.
156
190
 
191
+ /**
192
+ * @primitive b.clusterStorage.placeholderize
193
+ * @signature b.clusterStorage.placeholderize(sql, dialect)
194
+ * @since 0.1.9
195
+ * @status stable
196
+ * @related b.clusterStorage.execute, b.cluster.dialect
197
+ *
198
+ * Translate `?` placeholders to numbered `$1`, `$2`, … form for
199
+ * Postgres backends; passthrough for `"sqlite"` and `"mysql"`. The
200
+ * walker skips question marks inside single-quoted string literals so
201
+ * `WHERE s = '?'` is preserved verbatim. Doubled-quote escapes (`''`)
202
+ * inside strings are recognized. The `execute` family calls this on
203
+ * every cluster-mode dispatch; reach for it directly only when
204
+ * shipping raw SQL through a non-`execute` driver path.
205
+ *
206
+ * @example
207
+ * var b = require("@blamejs/core");
208
+ * var sql = b.clusterStorage.placeholderize(
209
+ * "SELECT id FROM audit_log WHERE counter > ? AND actor = ?",
210
+ * "postgres"
211
+ * );
212
+ * // → "SELECT id FROM audit_log WHERE counter > $1 AND actor = $2"
213
+ */
157
214
  function placeholderize(sql, dialect) {
158
215
  if (dialect !== "postgres") return sql;
159
216
  // Walk the SQL and replace `?` with $1, $2, … but skip ones inside
@@ -177,6 +234,33 @@ function placeholderize(sql, dialect) {
177
234
 
178
235
  // ---- execute() ----
179
236
 
237
+ /**
238
+ * @primitive b.clusterStorage.execute
239
+ * @signature b.clusterStorage.execute(sql, params)
240
+ * @since 0.1.9
241
+ * @status stable
242
+ * @compliance soc2
243
+ * @related b.clusterStorage.executeOne, b.clusterStorage.executeAll, b.cluster.isClusterMode
244
+ *
245
+ * Run framework-state SQL against the active backend. In cluster mode
246
+ * the SQL is routed through `resolveTables` + `placeholderize`, then
247
+ * dispatched to the operator-supplied external DB. In single-node
248
+ * mode it runs against the framework's local SQLite via
249
+ * `db().prepare(...)` — `SELECT` and `RETURNING` queries use `.all()`,
250
+ * everything else uses `.run()`. The shape is uniform either way:
251
+ * resolves to `{ rows, rowCount }` where `rows` is the array of result
252
+ * objects and `rowCount` is `rows.length` for selects or `info.changes`
253
+ * for writes. Throws `ClusterStorageError` (code
254
+ * `cluster-storage/bad-arg`) when `sql` is not a string.
255
+ *
256
+ * @example
257
+ * var b = require("@blamejs/core");
258
+ * var result = await b.clusterStorage.execute(
259
+ * "SELECT counter, row_hash FROM audit_log WHERE counter > ?",
260
+ * [42]
261
+ * );
262
+ * // → { rows: [ { counter: 43, row_hash: "..." } ], rowCount: 1 }
263
+ */
180
264
  async function execute(sql, params) {
181
265
  if (typeof sql !== "string") {
182
266
  throw new ClusterStorageError("sql must be a string", "cluster-storage/bad-arg");
@@ -205,11 +289,52 @@ async function execute(sql, params) {
205
289
  }
206
290
 
207
291
  // Convenience wrappers for the two common patterns.
292
+ /**
293
+ * @primitive b.clusterStorage.executeOne
294
+ * @signature b.clusterStorage.executeOne(sql, params)
295
+ * @since 0.1.9
296
+ * @status stable
297
+ * @related b.clusterStorage.execute, b.clusterStorage.executeAll
298
+ *
299
+ * Convenience over `execute` for queries expected to return at most
300
+ * one row. Returns the first row when the result set is non-empty,
301
+ * `null` otherwise. The same dispatch rules as `execute` apply —
302
+ * cluster mode routes to external DB, single-node hits local SQLite.
303
+ *
304
+ * @example
305
+ * var b = require("@blamejs/core");
306
+ * var row = await b.clusterStorage.executeOne(
307
+ * "SELECT counter, row_hash FROM audit_tip WHERE id = ?",
308
+ * [1]
309
+ * );
310
+ * // → { counter: 128, row_hash: "..." }
311
+ * // → null when no row matches
312
+ */
208
313
  async function executeOne(sql, params) {
209
314
  var result = await execute(sql, params);
210
315
  return result.rows.length > 0 ? result.rows[0] : null;
211
316
  }
212
317
 
318
+ /**
319
+ * @primitive b.clusterStorage.executeAll
320
+ * @signature b.clusterStorage.executeAll(sql, params)
321
+ * @since 0.1.9
322
+ * @status stable
323
+ * @related b.clusterStorage.execute, b.clusterStorage.executeOne
324
+ *
325
+ * Convenience over `execute` for queries expected to return a row
326
+ * array. Returns the `rows` array directly without the surrounding
327
+ * `{ rows, rowCount }` envelope. Empty result sets resolve to `[]`.
328
+ * The same dispatch rules as `execute` apply.
329
+ *
330
+ * @example
331
+ * var b = require("@blamejs/core");
332
+ * var rows = await b.clusterStorage.executeAll(
333
+ * "SELECT id, status FROM queue_jobs WHERE status = ?",
334
+ * ["pending"]
335
+ * );
336
+ * // → [ { id: 1, status: "pending" }, { id: 2, status: "pending" } ]
337
+ */
213
338
  async function executeAll(sql, params) {
214
339
  var result = await execute(sql, params);
215
340
  return result.rows;