@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
package/lib/template.js CHANGED
@@ -1,13 +1,37 @@
1
1
  "use strict";
2
2
  /**
3
- * Server-side HTML template engine — eval-free.
3
+ * @module b.template
4
+ * @nav HTTP
5
+ * @title Template
6
+ *
7
+ * @intro
8
+ * Server-side HTML template engine. Handlebars-flavoured tag
9
+ * syntax (`{{ expr }}` HTML-escaped, `{{{ expr }}}` raw, `{{> name }}`
10
+ * partials, `{% extends "layout" %}` / `{% block name %}` inheritance,
11
+ * `{% if %}` / `{% for %}` directives) parsed into a small AST and
12
+ * walked at render time against an operator-supplied data scope.
13
+ *
14
+ * No `eval`, no dynamic Function constructor, no `vm.runInThisContext`
15
+ * — the expression grammar is a fixed recursive-descent Pratt parser
16
+ * and member access is restricted to own properties (the parser
17
+ * refuses `foo.constructor` / `foo.__proto__` walks out of the data
18
+ * scope). Custom helpers are operator-provided functions in the data
19
+ * scope (e.g. `{{ helpers.formatDate(d) }}`); when `opts.sandbox ===
20
+ * true` each helper source string is wrapped through `b.sandbox.run`
21
+ * so helper code runs in a worker-thread isolate with timeout + byte
22
+ * cap.
23
+ *
24
+ * `precompileAll()` walks `viewsDir` at boot, parsing every `.html`
25
+ * file so template syntax errors fail the deploy rather than the
26
+ * first user request. Compiled ASTs are cached unless `cache: false`
27
+ * is set on the engine — operators turn caching off for live-reload
28
+ * workflows.
4
29
  *
5
- * No `new Function()`, no `eval`, no `vm.runInThisContext`. Templates
6
- * are tokenized + parsed into a small AST and walked at render time
7
- * against a data scope. The trade-off vs an eval-based engine is
8
- * 5–50× slower per render and a restricted expression grammar; the
9
- * win is "an operator who renders req.query.template (or worse) can't
10
- * RCE the framework, period."
30
+ * @card
31
+ * Server-side HTML template engine.
32
+ */
33
+ /**
34
+ * Server-side HTML template engine eval-free.
11
35
  *
12
36
  * Tag syntax:
13
37
  *
@@ -67,8 +91,14 @@
67
91
  */
68
92
  var fs = require("fs");
69
93
  var path = require("path");
94
+ var lazyRequire = require("./lazy-require");
70
95
  var validateOpts = require("./validate-opts");
71
96
 
97
+ // Lazy because b.template can be loaded before b.sandbox (which pulls
98
+ // in node:worker_threads). Operators not opting into sandboxed helpers
99
+ // shouldn't pay the worker_threads boot.
100
+ var sandboxModule = lazyRequire(function () { return require("./sandbox"); });
101
+
72
102
  // Maximum nesting depth for layout {% extends %} chains and partial
73
103
  // {{> ... }} recursion. Hex form so the byte-literal lint doesn't trip
74
104
  // on the multiple-of-8 cap; high enough that a real template tree
@@ -82,6 +112,26 @@ var MAX_TEMPLATE_DEPTH = 0x10;
82
112
  var ESCAPE_MAP = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#x27;" };
83
113
  var ESCAPE_RE = /[&<>"']/g;
84
114
 
115
+ /**
116
+ * @primitive b.template.escapeHtml
117
+ * @signature b.template.escapeHtml(value)
118
+ * @since 0.1.0
119
+ * @related b.template.create, b.template.render
120
+ *
121
+ * HTML-entity escapes the five attack-relevant characters (`&`, `<`,
122
+ * `>`, `"`, `'`). Non-string inputs are coerced via `String(value)`;
123
+ * `null` and `undefined` become the empty string. Used internally by
124
+ * `{{ expr }}` interpolation; exported because operators occasionally
125
+ * reach for the same escape from non-template paths (form-error
126
+ * rendering, CSV-cell-as-HTML pre-escape).
127
+ *
128
+ * @example
129
+ * b.template.escapeHtml("<script>alert(1)</script>");
130
+ * // → "&lt;script&gt;alert(1)&lt;/script&gt;"
131
+ *
132
+ * b.template.escapeHtml(null); // → ""
133
+ * b.template.escapeHtml(42); // → "42"
134
+ */
85
135
  function escapeHtml(value) {
86
136
  if (value === null || value === undefined) return "";
87
137
  var s = typeof value === "string" ? value : String(value);
@@ -683,9 +733,41 @@ function _evalBlock(nodes, scopes, escFn) {
683
733
  // Engine instance
684
734
  // ============================================================
685
735
 
736
+ /**
737
+ * @primitive b.template.create
738
+ * @signature b.template.create(opts)
739
+ * @since 0.1.0
740
+ * @related b.template.render, b.template.escapeHtml
741
+ *
742
+ * Builds an engine instance bound to `opts.viewsDir`. The returned
743
+ * object exposes `render(viewName, data?)` for one-shot rendering,
744
+ * `compile(viewName)` for AST-only access (caches under viewName),
745
+ * `precompileAll()` for boot-time validation of every `.html` file
746
+ * under `viewsDir`, and `reset()` to drop the AST cache (useful in
747
+ * live-reload workflows).
748
+ *
749
+ * View names are resolved against `viewsDir`; names containing `..`
750
+ * or NUL are refused, and resolved paths outside `viewsDir` throw.
751
+ * Layout-extends and partial-inclusion recursion are bounded at
752
+ * depth 16 to defend against accidental cycles.
753
+ *
754
+ * @opts
755
+ * viewsDir: string, // required — absolute or cwd-relative directory of .html templates
756
+ * cache: boolean, // default true; set false for live-reload
757
+ * escapeHtml: function (value) → string, // override the default 5-character HTML escape
758
+ * sandbox: boolean, // when true, sandboxHelpers run through b.sandbox.run
759
+ * sandboxHelpers: Object<string, string>, // map of helperName → JS source executed inside the sandbox
760
+ * sandboxOpts: { timeoutMs, maxBytes, allowed },
761
+ *
762
+ * @example
763
+ * var engine = b.template.create({ viewsDir: "./views" });
764
+ * engine.precompileAll(); // fail boot on syntax errors
765
+ * var html = engine.render("dashboard", { user: { name: "Ada" } });
766
+ * // → "<h1>Hello Ada</h1>"
767
+ */
686
768
  function create(opts) {
687
769
  opts = opts || {};
688
- validateOpts(opts, ["viewsDir", "cache", "escapeHtml"], "b.template");
770
+ validateOpts(opts, ["viewsDir", "cache", "escapeHtml", "sandbox", "sandboxHelpers", "sandboxOpts"], "b.template");
689
771
  if (!opts.viewsDir) {
690
772
  throw new Error("template.create({ viewsDir }) is required");
691
773
  }
@@ -697,6 +779,47 @@ function create(opts) {
697
779
  var customEscape = typeof opts.escapeHtml === "function" ? opts.escapeHtml : escapeHtml;
698
780
  var astCache = {};
699
781
 
782
+ // Sandbox integration. When opts.sandbox === true, every operator-
783
+ // supplied helper in opts.sandboxHelpers (a { name -> source-string }
784
+ // map) is wrapped into an async-shaped callable that delegates to
785
+ // b.sandbox.run with the operator's per-engine sandboxOpts (timeoutMs,
786
+ // maxBytes, allowed). The helper signature is `helperFn(input)` which
787
+ // returns a Promise; templates can pre-compute helper results in the
788
+ // route handler and pass the resolved values into the data scope.
789
+ // The template engine itself stays synchronous + eval-free.
790
+ var sandboxedHelpers = null;
791
+ if (opts.sandbox === true) {
792
+ var sbHelpers = opts.sandboxHelpers || {};
793
+ if (typeof sbHelpers !== "object" || Array.isArray(sbHelpers)) {
794
+ throw new Error("template.create: opts.sandboxHelpers must be a { name -> source } object");
795
+ }
796
+ var sbOpts = opts.sandboxOpts || {};
797
+ if (typeof sbOpts !== "object" || Array.isArray(sbOpts)) {
798
+ throw new Error("template.create: opts.sandboxOpts must be an object");
799
+ }
800
+ var sandbox = sandboxModule();
801
+ sandboxedHelpers = {};
802
+ var helperNames = Object.keys(sbHelpers);
803
+ for (var hi = 0; hi < helperNames.length; hi += 1) {
804
+ var hname = helperNames[hi];
805
+ var hsource = sbHelpers[hname];
806
+ if (typeof hsource !== "string" || hsource.length === 0) {
807
+ throw new Error("template.create: opts.sandboxHelpers[" + JSON.stringify(hname) + "] must be a non-empty string");
808
+ }
809
+ sandboxedHelpers[hname] = (function (capturedSource) {
810
+ return function (helperInput) {
811
+ return sandbox.run({
812
+ source: capturedSource,
813
+ input: helperInput,
814
+ timeoutMs: sbOpts.timeoutMs,
815
+ maxBytes: sbOpts.maxBytes,
816
+ allowed: sbOpts.allowed,
817
+ }).then(function (r) { return r.result; });
818
+ };
819
+ }(hsource));
820
+ }
821
+ }
822
+
700
823
  function compile(viewName) {
701
824
  if (cacheOn && astCache[viewName]) return astCache[viewName];
702
825
  var viewPath = _resolveViewPath(viewsDir, viewName);
@@ -777,6 +900,23 @@ function _ensureDefault() {
777
900
  return _default;
778
901
  }
779
902
 
903
+ /**
904
+ * @primitive b.template.render
905
+ * @signature b.template.render(viewName, data?)
906
+ * @since 0.1.0
907
+ * @related b.template.create
908
+ *
909
+ * Convenience renderer that lazily binds a default engine instance
910
+ * to `<cwd>/views` on first call, then dispatches to its `render()`.
911
+ * Operators with custom view directories (multi-tenant apps,
912
+ * non-cwd-rooted deploys) call `b.template.create({ viewsDir })`
913
+ * instead and keep the engine in their app scope.
914
+ *
915
+ * @example
916
+ * // Project layout: ./views/welcome.html
917
+ * var html = b.template.render("welcome", { name: "Ada" });
918
+ * // → "<h1>Welcome, Ada</h1>"
919
+ */
780
920
  function render(viewName, data) {
781
921
  return _ensureDefault().render(viewName, data);
782
922
  }