@blamejs/core 0.9.12 → 0.9.15

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 (119) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/lib/a2a.js +11 -11
  3. package/lib/acme.js +5 -5
  4. package/lib/ai-input.js +2 -2
  5. package/lib/api-key.js +4 -4
  6. package/lib/api-snapshot.js +10 -7
  7. package/lib/app-shutdown.js +2 -2
  8. package/lib/app.js +5 -5
  9. package/lib/archive.js +8 -8
  10. package/lib/argon2-builtin.js +2 -2
  11. package/lib/atomic-file.js +53 -53
  12. package/lib/audit-sign.js +8 -8
  13. package/lib/audit-tools.js +22 -22
  14. package/lib/audit.js +29 -17
  15. package/lib/auth/dpop.js +3 -3
  16. package/lib/auth/sd-jwt-vc.js +2 -2
  17. package/lib/backup/bundle.js +17 -17
  18. package/lib/backup/index.js +36 -36
  19. package/lib/budr.js +3 -3
  20. package/lib/bundler.js +20 -20
  21. package/lib/circuit-breaker.js +24 -9
  22. package/lib/cli.js +25 -26
  23. package/lib/cluster.js +2 -2
  24. package/lib/compliance-sanctions.js +2 -2
  25. package/lib/config-drift.js +15 -15
  26. package/lib/content-credentials.js +4 -4
  27. package/lib/credential-hash.js +3 -3
  28. package/lib/crypto.js +145 -0
  29. package/lib/daemon.js +19 -19
  30. package/lib/db-file-lifecycle.js +24 -24
  31. package/lib/db-schema.js +2 -2
  32. package/lib/db.js +35 -35
  33. package/lib/dev.js +10 -10
  34. package/lib/dr-runbook.js +5 -5
  35. package/lib/dsr.js +22 -15
  36. package/lib/dual-control.js +2 -2
  37. package/lib/external-db-migrate.js +2 -2
  38. package/lib/external-db.js +2 -2
  39. package/lib/fdx.js +2 -2
  40. package/lib/file-upload.js +30 -30
  41. package/lib/flag-providers.js +4 -4
  42. package/lib/gate-contract.js +5 -5
  43. package/lib/graphql-federation.js +4 -7
  44. package/lib/honeytoken.js +6 -6
  45. package/lib/http-client-cookie-jar.js +6 -6
  46. package/lib/http-client.js +18 -18
  47. package/lib/i18n.js +5 -5
  48. package/lib/inbox.js +21 -15
  49. package/lib/keychain.js +9 -9
  50. package/lib/legal-hold.js +2 -2
  51. package/lib/local-db-thin.js +9 -9
  52. package/lib/log-stream-local.js +17 -17
  53. package/lib/log-stream-syslog.js +2 -2
  54. package/lib/log-stream.js +3 -3
  55. package/lib/mail-bounce.js +2 -2
  56. package/lib/mail-mdn.js +2 -2
  57. package/lib/mail-srs.js +2 -2
  58. package/lib/mail.js +4 -4
  59. package/lib/mcp.js +2 -2
  60. package/lib/metrics.js +249 -2
  61. package/lib/middleware/api-encrypt.js +16 -16
  62. package/lib/middleware/body-parser.js +16 -16
  63. package/lib/middleware/compression.js +3 -3
  64. package/lib/middleware/csp-nonce.js +4 -4
  65. package/lib/middleware/health.js +7 -7
  66. package/lib/middleware/idempotency-key.js +250 -0
  67. package/lib/migrations.js +3 -3
  68. package/lib/mtls-ca.js +26 -26
  69. package/lib/mtls-engine-default.js +5 -5
  70. package/lib/network-dns.js +2 -2
  71. package/lib/network-nts.js +2 -2
  72. package/lib/network-proxy.js +3 -3
  73. package/lib/network-smtp-policy.js +2 -2
  74. package/lib/network-tls.js +17 -17
  75. package/lib/network.js +13 -13
  76. package/lib/notify.js +3 -3
  77. package/lib/object-store/gcs-bucket-ops.js +2 -2
  78. package/lib/object-store/gcs.js +5 -5
  79. package/lib/object-store/index.js +6 -6
  80. package/lib/object-store/local.js +19 -19
  81. package/lib/object-store/sigv4.js +3 -3
  82. package/lib/observability-tracer.js +4 -4
  83. package/lib/otel-export.js +3 -3
  84. package/lib/pagination.js +5 -5
  85. package/lib/parsers/safe-xml.js +3 -3
  86. package/lib/pqc-agent.js +116 -26
  87. package/lib/pqc-gate.js +5 -5
  88. package/lib/pubsub-redis.js +2 -2
  89. package/lib/queue-local.js +3 -3
  90. package/lib/queue.js +2 -2
  91. package/lib/redis-client.js +4 -4
  92. package/lib/restore-bundle.js +18 -18
  93. package/lib/restore-rollback.js +34 -34
  94. package/lib/restore.js +16 -16
  95. package/lib/retry.js +50 -0
  96. package/lib/router.js +13 -13
  97. package/lib/sandbox.js +8 -8
  98. package/lib/sec-cyber.js +3 -3
  99. package/lib/security-assert.js +2 -2
  100. package/lib/seeders.js +4 -4
  101. package/lib/self-update-standalone-verifier.js +280 -0
  102. package/lib/self-update.js +32 -26
  103. package/lib/session-device-binding.js +2 -2
  104. package/lib/static.js +22 -22
  105. package/lib/template.js +19 -19
  106. package/lib/testing.js +7 -7
  107. package/lib/tls-exporter.js +5 -5
  108. package/lib/tracing.js +3 -3
  109. package/lib/vault/index.js +11 -11
  110. package/lib/vault/passphrase-ops.js +37 -37
  111. package/lib/vault/passphrase-source.js +2 -2
  112. package/lib/vault/rotate.js +70 -66
  113. package/lib/vault/seal-pem-file.js +26 -26
  114. package/lib/watcher.js +23 -23
  115. package/lib/webhook.js +10 -10
  116. package/lib/worker-pool.js +6 -6
  117. package/lib/ws-client.js +4 -4
  118. package/package.json +1 -1
  119. package/sbom.cdx.json +6 -6
package/lib/metrics.js CHANGED
@@ -39,9 +39,12 @@
39
39
 
40
40
  var C = require("./constants");
41
41
  var canonicalJson = require("./canonical-json");
42
+ var nodeFs = require("node:fs");
43
+ var atomicFile = require("./atomic-file");
44
+ var safeJson = require("./safe-json");
42
45
  var { defineClass } = require("./framework-error");
43
46
  var { boot } = require("./log");
44
- var nb = require("./numeric-bounds");
47
+ var numericBounds = require("./numeric-bounds");
45
48
  var { resolveRoute, captureResponseStatus, HTTP_STATUS } = require("./request-helpers");
46
49
  var validateOpts = require("./validate-opts");
47
50
 
@@ -276,7 +279,7 @@ function create(opts) {
276
279
  ], "b.metrics");
277
280
  var namespace = opts.namespace || "";
278
281
  var defaultLabels = opts.defaultLabels || {};
279
- nb.requirePositiveFiniteIntIfPresent(opts.labelCardinalityCap,
282
+ numericBounds.requirePositiveFiniteIntIfPresent(opts.labelCardinalityCap,
280
283
  "labelCardinalityCap", MetricsError, "metrics/bad-opt");
281
284
  var cardinalityCap = opts.labelCardinalityCap || DEFAULT_CARDINALITY_CAP;
282
285
 
@@ -678,9 +681,253 @@ function _resetForTest() {
678
681
  _activeTap = null;
679
682
  }
680
683
 
684
+ // ---- Snapshot writer/reader ----
685
+ //
686
+ // Out-of-process metrics export pattern for long-running daemons:
687
+ // the daemon writes a JSON snapshot atomically every N seconds; a
688
+ // separate CLI process reads + renders. Bypasses the HTTP-port +
689
+ // Unix-socket coupling that the regular Prometheus exposition
690
+ // handler requires. Useful for systemd daemons that don't want to
691
+ // bind a stats port at all (operator runs `daemon stats` and the
692
+ // CLI just reads the file).
693
+ //
694
+ // The writer is atomic — every write goes through atomic-file's
695
+ // writeSync (temp-file + rename + fsync) so a reader that lands
696
+ // between rename and fsync sees the previous complete snapshot
697
+ // rather than a partially-written one.
698
+ //
699
+ // Surface:
700
+ //
701
+ // var stop = b.metrics.snapshot.startWriter({
702
+ // path: "/run/blamejs-daemon/metrics.json",
703
+ // intervalMs: 5000,
704
+ // fields: function () { return { uptimeMs: ..., counters: {...} }; },
705
+ // });
706
+ // // ...later:
707
+ // stop(); // clears timer; runs one final fields() flush before returning
708
+ //
709
+ // var snap = b.metrics.snapshot.read("/run/blamejs-daemon/metrics.json");
710
+ // process.stdout.write(b.metrics.snapshot.render(snap, { format: "text" }));
711
+
712
+ /**
713
+ * @primitive b.metrics.snapshot.startWriter
714
+ * @signature b.metrics.snapshot.startWriter(opts)
715
+ * @since 0.9.13
716
+ * @status stable
717
+ * @related b.metrics.snapshot.read, b.metrics.snapshot.render
718
+ *
719
+ * Start a periodic writer that calls `opts.fields()` every
720
+ * `opts.intervalMs` and writes the returned object as JSON to
721
+ * `opts.path` atomically. Returns a `stop()` function that clears
722
+ * the timer + performs one final flush before resolving.
723
+ *
724
+ * @opts
725
+ * path: string, // absolute path to write the snapshot
726
+ * intervalMs: number, // milliseconds between flushes (>=100)
727
+ * fields: Function, // returns an object — written as JSON
728
+ *
729
+ * @example
730
+ * var stop = b.metrics.snapshot.startWriter({
731
+ * path: "/run/blamejs/metrics.json",
732
+ * intervalMs: 5000,
733
+ * fields: function () {
734
+ * return {
735
+ * uptimeMs: process.uptime() * 1000,
736
+ * queueDepth: myQueue.size,
737
+ * lastSyncAt: lastSyncAt,
738
+ * };
739
+ * },
740
+ * });
741
+ * // ... on SIGTERM:
742
+ * stop();
743
+ */
744
+ function snapshotStartWriter(opts) {
745
+ opts = opts || {};
746
+ validateOpts.requireNonEmptyString(opts.path,
747
+ "metrics.snapshot.startWriter: opts.path",
748
+ MetricsError, "metrics-snapshot/bad-path");
749
+ if (typeof opts.intervalMs !== "number" || !isFinite(opts.intervalMs) || opts.intervalMs < 100) {
750
+ throw new MetricsError("metrics-snapshot/bad-interval",
751
+ "metrics.snapshot.startWriter: opts.intervalMs must be a finite number >= 100, got " + opts.intervalMs);
752
+ }
753
+ if (typeof opts.fields !== "function") {
754
+ throw new MetricsError("metrics-snapshot/bad-fields",
755
+ "metrics.snapshot.startWriter: opts.fields must be a function returning the snapshot object");
756
+ }
757
+ var p = opts.path;
758
+ var fieldsFn = opts.fields;
759
+ var intervalMs = opts.intervalMs;
760
+
761
+ var doFlush = function () {
762
+ var snap;
763
+ try {
764
+ snap = fieldsFn();
765
+ } catch (e) {
766
+ log("snapshot.fields() threw: " + (e && e.message ? e.message : String(e)));
767
+ return;
768
+ }
769
+ if (!snap || typeof snap !== "object") {
770
+ log("snapshot.fields() returned non-object; skipping flush");
771
+ return;
772
+ }
773
+ var payload = {
774
+ writtenAt: new Date().toISOString(),
775
+ fields: snap,
776
+ };
777
+ try {
778
+ atomicFile.writeSync(p, JSON.stringify(payload) + "\n", { fileMode: 0o644 });
779
+ } catch (e) {
780
+ log("snapshot.writeSync failed: " + (e && e.message ? e.message : String(e)));
781
+ }
782
+ };
783
+
784
+ // First flush is synchronous so the file exists by the time
785
+ // startWriter returns. Subsequent flushes run on the interval.
786
+ doFlush();
787
+ var timer = setInterval(doFlush, intervalMs);
788
+ if (typeof timer.unref === "function") timer.unref();
789
+
790
+ return function stop() {
791
+ clearInterval(timer);
792
+ doFlush(); // final flush captures last state before the daemon exits
793
+ };
794
+ }
795
+
796
+ /**
797
+ * @primitive b.metrics.snapshot.read
798
+ * @signature b.metrics.snapshot.read(path)
799
+ * @since 0.9.13
800
+ * @status stable
801
+ * @related b.metrics.snapshot.startWriter, b.metrics.snapshot.render
802
+ *
803
+ * Read + parse a snapshot file written by `startWriter`. Returns
804
+ * `{ writtenAt, fields }`. Throws `MetricsError` with code
805
+ * `metrics-snapshot/...` on missing file, parse failure, or
806
+ * shape mismatch.
807
+ *
808
+ * @example
809
+ * var snap = b.metrics.snapshot.read("/run/blamejs/metrics.json");
810
+ * console.log("uptime:", snap.fields.uptimeMs);
811
+ * console.log("written at:", snap.writtenAt);
812
+ */
813
+ function snapshotRead(p) {
814
+ validateOpts.requireNonEmptyString(p,
815
+ "metrics.snapshot.read: path",
816
+ MetricsError, "metrics-snapshot/bad-path");
817
+ var raw;
818
+ try {
819
+ raw = nodeFs.readFileSync(p, "utf8");
820
+ } catch (e) {
821
+ throw new MetricsError("metrics-snapshot/not-found",
822
+ "metrics.snapshot.read: " + p + " — " + (e && e.message ? e.message : String(e)));
823
+ }
824
+ var parsed;
825
+ // safeJson.parse with bounded maxBytes — the snapshot file is read
826
+ // by a separate CLI / sidecar process from where it's written, and a
827
+ // hostile actor with write access to the snapshot path could replace
828
+ // it with a multi-GB file that would OOM the reader. 4 MiB ceiling
829
+ // is well above the framework's expected snapshot size (~5-50 KiB)
830
+ // and the safeJson absolute cap stays within reach.
831
+ try {
832
+ parsed = safeJson.parse(raw, { maxBytes: 4 * 1024 * 1024 }); // allow:raw-byte-literal — 4 MiB snapshot-file ceiling
833
+ } catch (e) {
834
+ throw new MetricsError("metrics-snapshot/bad-json",
835
+ "metrics.snapshot.read: " + p + " contains invalid JSON: " + (e && e.message ? e.message : String(e)));
836
+ }
837
+ if (!parsed || typeof parsed !== "object" ||
838
+ typeof parsed.writtenAt !== "string" || !parsed.fields ||
839
+ typeof parsed.fields !== "object") {
840
+ throw new MetricsError("metrics-snapshot/bad-shape",
841
+ "metrics.snapshot.read: " + p + " is not a startWriter-produced snapshot (missing writtenAt or fields)");
842
+ }
843
+ return parsed;
844
+ }
845
+
846
+ /**
847
+ * @primitive b.metrics.snapshot.render
848
+ * @signature b.metrics.snapshot.render(snap, opts)
849
+ * @since 0.9.13
850
+ * @status stable
851
+ * @related b.metrics.snapshot.read
852
+ *
853
+ * Format a snapshot object for human or machine consumption.
854
+ *
855
+ * format: "text" — operator-readable lines, one field per row (default)
856
+ * format: "prometheus" — Prometheus 0.0.4 text format, gauge metrics
857
+ * named with a configurable prefix; only top-level
858
+ * numeric fields under `snap.fields` are emitted
859
+ *
860
+ * @opts
861
+ * format: "text" | "prometheus", // default: "text"
862
+ * prefix: string, // prometheus-only; default: "blamejs"
863
+ *
864
+ * @example
865
+ * var snap = b.metrics.snapshot.read("/run/blamejs/metrics.json");
866
+ * process.stdout.write(b.metrics.snapshot.render(snap));
867
+ * // or for Prometheus scraping:
868
+ * res.setHeader("Content-Type", "text/plain; version=0.0.4");
869
+ * res.end(b.metrics.snapshot.render(snap, { format: "prometheus", prefix: "myapp" }));
870
+ */
871
+ function snapshotRender(snap, opts) {
872
+ opts = opts || {};
873
+ var format = opts.format || "text";
874
+ if (!snap || typeof snap !== "object" || !snap.fields) {
875
+ throw new MetricsError("metrics-snapshot/bad-snap",
876
+ "metrics.snapshot.render: snap must be a startWriter-produced object (got " + typeof snap + ")");
877
+ }
878
+ var fields = snap.fields;
879
+ if (format === "text") {
880
+ var lines = ["snapshot written-at: " + snap.writtenAt];
881
+ // allow:bare-canonicalize-walk — sort is for stable human-readable
882
+ // output ordering, not canonicalize-for-hashing
883
+ var keys = Object.keys(fields).sort();
884
+ for (var i = 0; i < keys.length; i++) {
885
+ var k = keys[i];
886
+ var v = fields[k];
887
+ var s;
888
+ if (typeof v === "number") s = String(v);
889
+ else if (typeof v === "string") s = v;
890
+ else if (typeof v === "boolean") s = v ? "true" : "false";
891
+ else s = JSON.stringify(v);
892
+ lines.push(" " + k + ": " + s);
893
+ }
894
+ return lines.join("\n") + "\n";
895
+ }
896
+ if (format === "prometheus") {
897
+ var prefix = opts.prefix || "blamejs";
898
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(prefix)) {
899
+ throw new MetricsError("metrics-snapshot/bad-prefix",
900
+ "metrics.snapshot.render: prometheus prefix must match [a-zA-Z_][a-zA-Z0-9_]*, got '" + prefix + "'");
901
+ }
902
+ var out = [];
903
+ // allow:bare-canonicalize-walk — sort is for stable Prometheus
904
+ // exposition output ordering, not canonicalize-for-hashing
905
+ var keys2 = Object.keys(fields).sort();
906
+ for (var j = 0; j < keys2.length; j++) {
907
+ var k2 = keys2[j];
908
+ var v2 = fields[k2];
909
+ if (typeof v2 !== "number" || !isFinite(v2)) continue; // only numeric scalars
910
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(k2)) continue; // skip prom-incompatible names
911
+ var metric = prefix + "_" + k2;
912
+ out.push("# TYPE " + metric + " gauge");
913
+ out.push(metric + " " + v2);
914
+ }
915
+ return out.join("\n") + "\n";
916
+ }
917
+ throw new MetricsError("metrics-snapshot/bad-format",
918
+ "metrics.snapshot.render: format must be 'text' or 'prometheus', got '" + format + "'");
919
+ }
920
+
921
+ var snapshot = {
922
+ startWriter: snapshotStartWriter,
923
+ read: snapshotRead,
924
+ render: snapshotRender,
925
+ };
926
+
681
927
  module.exports = {
682
928
  create: create,
683
929
  tap: tap,
930
+ snapshot: snapshot,
684
931
  MetricsError: MetricsError,
685
932
  DEFAULT_HTTP_BUCKETS: DEFAULT_HTTP_BUCKETS,
686
933
  DEFAULT_CARDINALITY_CAP: DEFAULT_CARDINALITY_CAP,
@@ -96,7 +96,7 @@
96
96
  * public/private routes can debug their wiring.
97
97
  */
98
98
 
99
- var crypto = require("../crypto");
99
+ var bCrypto = require("../crypto");
100
100
  var C = require("../constants");
101
101
  var lazyRequire = require("../lazy-require");
102
102
  var nonceStoreLib = require("../nonce-store");
@@ -449,7 +449,7 @@ function create(opts) {
449
449
  res.json = function (data) {
450
450
  try {
451
451
  var ptBuf = Buffer.from(JSON.stringify(data), "utf8");
452
- var ctBuf = crypto.encryptPacked(ptBuf, sessionKey);
452
+ var ctBuf = bCrypto.encryptPacked(ptBuf, sessionKey);
453
453
  var encrypted = { _ct: ctBuf.toString("base64") };
454
454
  if (sessionCtx) {
455
455
  encrypted._sid = sessionCtx.sid;
@@ -480,7 +480,7 @@ function create(opts) {
480
480
  function _decryptEkToSessionKey(ek) {
481
481
  for (var ki = 0; ki < keypairs.length; ki++) {
482
482
  try {
483
- var sessionKeyB64 = crypto.decrypt(ek, keypairs[ki]);
483
+ var sessionKeyB64 = bCrypto.decrypt(ek, keypairs[ki]);
484
484
  var candidate = Buffer.from(sessionKeyB64, "base64");
485
485
  if (candidate.length === SESSION_KEY_BYTES) return candidate;
486
486
  } catch (_e) { /* try next keypair */ }
@@ -518,7 +518,7 @@ function create(opts) {
518
518
 
519
519
  if (typeof ek === "string" && typeof nonce === "string") {
520
520
  // ---- Bootstrap path (per-request mode OR first request of session) ----
521
- var nonceHash = crypto.sha3Hash(nonce, "hex");
521
+ var nonceHash = bCrypto.sha3Hash(nonce, "hex");
522
522
  var expireAt = now + replayWindowMs;
523
523
  var freshNonce;
524
524
  try { freshNonce = await nonceStore.checkAndInsert(nonceHash, expireAt); }
@@ -655,7 +655,7 @@ function create(opts) {
655
655
  var clearObj;
656
656
  try {
657
657
  var ctBuf = Buffer.from(ct, "base64");
658
- var ptBuf = crypto.decryptPacked(ctBuf, sessionKey);
658
+ var ptBuf = bCrypto.decryptPacked(ctBuf, sessionKey);
659
659
  clearObj = safeJson.parse(ptBuf.toString("utf8"), { maxBytes: maxDecryptedBytes });
660
660
  } catch (_e) {
661
661
  _emitFailure(req, "tag");
@@ -751,7 +751,7 @@ function client(opts) {
751
751
  var perSessionLastResCtr = 0;
752
752
 
753
753
  function _resetSession() {
754
- perSessionKey = crypto.generateBytes(SESSION_KEY_BYTES);
754
+ perSessionKey = bCrypto.generateBytes(SESSION_KEY_BYTES);
755
755
  perSessionSid = _generateUuidV4();
756
756
  perSessionReqCtr = 0;
757
757
  perSessionLastResCtr = 0;
@@ -774,7 +774,7 @@ function client(opts) {
774
774
  }
775
775
  perSessionLastResCtr = responseBody._ctr;
776
776
  var resCtBuf = Buffer.from(responseBody._ct, "base64");
777
- var resPtBuf = crypto.decryptPacked(resCtBuf, perSessionKey);
777
+ var resPtBuf = bCrypto.decryptPacked(resCtBuf, perSessionKey);
778
778
  return safeJson.parse(resPtBuf.toString("utf8"), { maxBytes: maxDecryptedBytes });
779
779
  }
780
780
 
@@ -783,13 +783,13 @@ function client(opts) {
783
783
  if (!perSessionKey) _resetSession();
784
784
  var ts = Date.now();
785
785
  var ptBuf = Buffer.from(JSON.stringify(payload), "utf8");
786
- var ctBuf = crypto.encryptPacked(ptBuf, perSessionKey);
786
+ var ctBuf = bCrypto.encryptPacked(ptBuf, perSessionKey);
787
787
  perSessionReqCtr += 1;
788
788
  var body;
789
789
  if (perSessionReqCtr === 1) {
790
790
  // Bootstrap envelope — full _ek + _nonce; server stores sid → sessionKey.
791
- var ek = crypto.encrypt(perSessionKey.toString("base64"), pubkey);
792
- var nonce = crypto.generateBytes(REQUEST_NONCE_BYTES).toString("hex");
791
+ var ek = bCrypto.encrypt(perSessionKey.toString("base64"), pubkey);
792
+ var nonce = bCrypto.generateBytes(REQUEST_NONCE_BYTES).toString("hex");
793
793
  body = {
794
794
  _ek: ek,
795
795
  _ct: ctBuf.toString("base64"),
@@ -812,11 +812,11 @@ function client(opts) {
812
812
 
813
813
  function _encryptPerRequest(payload) {
814
814
  if (payload === undefined) payload = null;
815
- var sessionKey = crypto.generateBytes(SESSION_KEY_BYTES);
816
- var ek = crypto.encrypt(sessionKey.toString("base64"), pubkey);
815
+ var sessionKey = bCrypto.generateBytes(SESSION_KEY_BYTES);
816
+ var ek = bCrypto.encrypt(sessionKey.toString("base64"), pubkey);
817
817
  var ptBuf = Buffer.from(JSON.stringify(payload), "utf8");
818
- var ctBuf = crypto.encryptPacked(ptBuf, sessionKey);
819
- var requestNonce = crypto.generateBytes(REQUEST_NONCE_BYTES).toString("hex");
818
+ var ctBuf = bCrypto.encryptPacked(ptBuf, sessionKey);
819
+ var requestNonce = bCrypto.generateBytes(REQUEST_NONCE_BYTES).toString("hex");
820
820
  var ts = Date.now();
821
821
  return {
822
822
  body: {
@@ -832,7 +832,7 @@ function client(opts) {
832
832
  "apiEncrypt.client: response missing _ct field");
833
833
  }
834
834
  var resCtBuf = Buffer.from(responseBody._ct, "base64");
835
- var resPtBuf = crypto.decryptPacked(resCtBuf, sessionKey);
835
+ var resPtBuf = bCrypto.decryptPacked(resCtBuf, sessionKey);
836
836
  return safeJson.parse(resPtBuf.toString("utf8"), { maxBytes: maxDecryptedBytes });
837
837
  },
838
838
  };
@@ -857,7 +857,7 @@ function client(opts) {
857
857
  // Slice offsets are RFC 4122 UUID hex-byte boundaries (`xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx`)
858
858
  // — protocol-fixed values, not byte sizes. allow:raw-byte-literal
859
859
  function _generateUuidV4() {
860
- var b = crypto.generateBytes(16); // allow:raw-byte-literal — UUID is exactly 16 bytes
860
+ var b = bCrypto.generateBytes(16); // allow:raw-byte-literal — UUID is exactly 16 bytes
861
861
  // Set version (4) and variant (10x) bits per RFC 4122.
862
862
  b[6] = (b[6] & 0x0f) | 0x40;
863
863
  b[8] = (b[8] & 0x3f) | 0x80;
@@ -100,7 +100,7 @@
100
100
  * dots collapsed, control characters stripped, length capped at 255.
101
101
  * Tmp file path is generated by the framework, never derived from
102
102
  * the operator-supplied filename — so a malicious filename can't
103
- * collide with a sensitive path.
103
+ * collide with a sensitive nodePath.
104
104
  * - Multipart parser refuses fields whose `name` is in POISONED_KEYS
105
105
  * (consistent with the JSON path).
106
106
  * - Tmp files set with mode 0o600, parent dir created with 0o700.
@@ -108,12 +108,12 @@
108
108
  * error) so a crashing handler doesn't leak files.
109
109
  */
110
110
 
111
- var fs = require("fs");
111
+ var nodeFs = require("fs");
112
112
  var os = require("os");
113
- var path = require("path");
113
+ var nodePath = require("path");
114
114
  var nodeCrypto = require("node:crypto");
115
115
  var atomicFile = require("../atomic-file");
116
- var crypto = require("../crypto");
116
+ var bCrypto = require("../crypto");
117
117
  var lazyRequire = require("../lazy-require");
118
118
  var requestHelpers = require("../request-helpers");
119
119
  var safeBuffer = require("../safe-buffer");
@@ -682,7 +682,7 @@ async function _parseMultipart(req, opts, ctParams) {
682
682
  }
683
683
  // Resolve tmpDir per-request so directory-creation failure surfaces as a
684
684
  // structured error rather than a deferred fs throw.
685
- var tmpDir = opts.tmpDir || path.join(os.tmpdir(), "blamejs-uploads");
685
+ var tmpDir = opts.tmpDir || nodePath.join(os.tmpdir(), "blamejs-uploads");
686
686
  try { atomicFile.ensureDir(tmpDir, 0o700); }
687
687
  catch (e) {
688
688
  throw new BodyParserError(
@@ -733,7 +733,7 @@ async function _parseMultipart(req, opts, ctParams) {
733
733
  currentFilename = null;
734
734
  currentMime = null;
735
735
  currentTmpPath = null;
736
- if (currentFd !== null) { try { fs.closeSync(currentFd); } catch (_e) { /* fd already closed */ } currentFd = null; }
736
+ if (currentFd !== null) { try { nodeFs.closeSync(currentFd); } catch (_e) { /* fd already closed */ } currentFd = null; }
737
737
  currentSize = 0;
738
738
  currentHash = null;
739
739
  currentBuf = null;
@@ -762,10 +762,10 @@ async function _parseMultipart(req, opts, ctParams) {
762
762
  }
763
763
 
764
764
  function _cleanup() {
765
- if (currentFd !== null) { try { fs.closeSync(currentFd); } catch (_e) { /* fd already closed */ } currentFd = null; }
766
- if (currentTmpPath) { try { fs.unlinkSync(currentTmpPath); } catch (_e) { /* tmp file already removed */ } }
765
+ if (currentFd !== null) { try { nodeFs.closeSync(currentFd); } catch (_e) { /* fd already closed */ } currentFd = null; }
766
+ if (currentTmpPath) { try { nodeFs.unlinkSync(currentTmpPath); } catch (_e) { /* tmp file already removed */ } }
767
767
  for (var i = 0; i < files.length; i++) {
768
- try { fs.unlinkSync(files[i].path); } catch (_e) { /* tmp file already removed */ }
768
+ try { nodeFs.unlinkSync(files[i].path); } catch (_e) { /* tmp file already removed */ }
769
769
  }
770
770
  }
771
771
 
@@ -945,10 +945,10 @@ async function _parseMultipart(req, opts, ctParams) {
945
945
 
946
946
  // Generate the tmp path — never derived from the
947
947
  // operator-supplied filename.
948
- var unique = crypto.generateToken(C.BYTES.bytes(16));
949
- currentTmpPath = path.join(tmpDir, "blamejs-up-" + unique);
948
+ var unique = bCrypto.generateToken(C.BYTES.bytes(16));
949
+ currentTmpPath = nodePath.join(tmpDir, "blamejs-up-" + unique);
950
950
  try {
951
- currentFd = fs.openSync(currentTmpPath, "wx", 0o600);
951
+ currentFd = nodeFs.openSync(currentTmpPath, "wx", 0o600);
952
952
  } catch (e) {
953
953
  done(new BodyParserError("body-parser/multipart-tmp-open",
954
954
  "could not open multipart tmp file: " + ((e && e.message) || String(e)),
@@ -1027,7 +1027,7 @@ async function _parseMultipart(req, opts, ctParams) {
1027
1027
  try {
1028
1028
  var written = 0;
1029
1029
  while (written < bodyChunk.length) {
1030
- written += fs.writeSync(currentFd, bodyChunk, written, bodyChunk.length - written);
1030
+ written += nodeFs.writeSync(currentFd, bodyChunk, written, bodyChunk.length - written);
1031
1031
  }
1032
1032
  } catch (e) {
1033
1033
  done(new BodyParserError("body-parser/multipart-tmp-write",
@@ -1068,7 +1068,7 @@ async function _parseMultipart(req, opts, ctParams) {
1068
1068
  // fileFilter rejected — already recorded in filesRejected; no
1069
1069
  // tmp file was opened, nothing to clean up here.
1070
1070
  } else if (currentFd !== null) {
1071
- try { fs.closeSync(currentFd); } catch (_e) { /* fd already closed */ }
1071
+ try { nodeFs.closeSync(currentFd); } catch (_e) { /* fd already closed */ }
1072
1072
  currentFd = null;
1073
1073
  files.push({
1074
1074
  field: currentField,
@@ -1247,7 +1247,7 @@ function create(opts) {
1247
1247
  if (cleanedUp) return;
1248
1248
  cleanedUp = true;
1249
1249
  for (var i = 0; i < mpResult.files.length; i++) {
1250
- try { fs.unlinkSync(mpResult.files[i].path); } catch (_e) { /* tmp file already removed */ }
1250
+ try { nodeFs.unlinkSync(mpResult.files[i].path); } catch (_e) { /* tmp file already removed */ }
1251
1251
  }
1252
1252
  }
1253
1253
  res.on("finish", cleanup);
@@ -1500,7 +1500,7 @@ module.exports = {
1500
1500
  BodyParserError: BodyParserError,
1501
1501
  // Standalone async helpers — surfaced via b.parsers.{json,multipart}.
1502
1502
  // The middleware composes these so the request-handling pipeline and
1503
- // the operator-callable surface share one parsing path.
1503
+ // the operator-callable surface share one parsing nodePath.
1504
1504
  parseJson: parseJsonStandalone,
1505
1505
  parseMultipart: parseMultipartStandalone,
1506
1506
  // Internal helpers exposed for tests + the csrf-protect refactor.
@@ -90,7 +90,7 @@
90
90
 
91
91
  var zlib = require("node:zlib");
92
92
  var C = require("../constants");
93
- var nb = require("../numeric-bounds");
93
+ var numericBounds = require("../numeric-bounds");
94
94
  var requestHelpers = require("../request-helpers");
95
95
  var validateOpts = require("../validate-opts");
96
96
  var { defineClass } = require("../framework-error");
@@ -271,12 +271,12 @@ function create(opts) {
271
271
  var threshold;
272
272
  if (opts.threshold === undefined) {
273
273
  threshold = DEFAULT_OPTS.threshold;
274
- } else if (nb.isNonNegativeFiniteInt(opts.threshold)) {
274
+ } else if (numericBounds.isNonNegativeFiniteInt(opts.threshold)) {
275
275
  threshold = opts.threshold;
276
276
  } else {
277
277
  throw new CompressionError("compression/bad-opt",
278
278
  "middleware.compression: threshold must be a non-negative finite integer; got " +
279
- nb.shape(opts.threshold));
279
+ numericBounds.shape(opts.threshold));
280
280
  }
281
281
  var encodings = Array.isArray(opts.encodings) && opts.encodings.length > 0
282
282
  ? opts.encodings.slice() : DEFAULT_OPTS.encodings.slice();
@@ -113,7 +113,7 @@
113
113
  */
114
114
 
115
115
  var C = require("../constants");
116
- var crypto = require("../crypto");
116
+ var bCrypto = require("../crypto");
117
117
  var numericBounds = require("../numeric-bounds");
118
118
  var validateOpts = require("../validate-opts");
119
119
  var { defineClass } = require("../framework-error");
@@ -283,7 +283,7 @@ function create(opts) {
283
283
  // Pre-fix the typeof-only check accepted Infinity / NaN — both
284
284
  // bypassed the `< MIN_NONCE_BYTES` guard (NaN < N is always false,
285
285
  // Infinity < N is always false), then crashed per-request when
286
- // `crypto.generateBytes(Infinity)` hit ERR_OUT_OF_RANGE. Route through
286
+ // `bCrypto.generateBytes(Infinity)` hit ERR_OUT_OF_RANGE. Route through
287
287
  // shared numeric-bounds (positive finite int) before the lower-bound
288
288
  // check so the typo / coercion is caught at create() time.
289
289
  if (!numericBounds.isPositiveFiniteInt(nonceBytes)) {
@@ -322,7 +322,7 @@ function create(opts) {
322
322
  if (opts.placeholder === undefined) {
323
323
  // OS-RNG → SHAKE256 → hex via the framework random helper.
324
324
  placeholder = PLACEHOLDER_PREFIX +
325
- crypto.generateToken(PLACEHOLDER_RAND_BYTES) +
325
+ bCrypto.generateToken(PLACEHOLDER_RAND_BYTES) +
326
326
  PLACEHOLDER_SUFFIX;
327
327
  } else if (typeof opts.placeholder !== "string" || opts.placeholder.length === 0) {
328
328
  throw new CspNonceError("csp-nonce/bad-placeholder",
@@ -336,7 +336,7 @@ function create(opts) {
336
336
  // Generate the nonce. Cheap (16 bytes from getrandom → SHAKE256 →
337
337
  // base64 encode); do it always for consistency unless `always:
338
338
  // false` was set explicitly.
339
- var nonce = crypto.generateBytes(nonceBytes).toString("base64");
339
+ var nonce = bCrypto.generateBytes(nonceBytes).toString("base64");
340
340
 
341
341
  // Attach to req for handler access.
342
342
  req[property] = nonce;
@@ -100,7 +100,7 @@
100
100
  */
101
101
 
102
102
  var C = require("../constants");
103
- var nb = require("../numeric-bounds");
103
+ var numericBounds = require("../numeric-bounds");
104
104
  var requestHelpers = require("../request-helpers");
105
105
  var safeAsync = require("../safe-async");
106
106
  var validateOpts = require("../validate-opts");
@@ -179,22 +179,22 @@ function create(opts) {
179
179
  var defaultTimeoutMs;
180
180
  if (opts.defaultTimeoutMs === undefined) {
181
181
  defaultTimeoutMs = DEFAULT_TIMEOUT_MS;
182
- } else if (nb.isPositiveFiniteInt(opts.defaultTimeoutMs)) {
182
+ } else if (numericBounds.isPositiveFiniteInt(opts.defaultTimeoutMs)) {
183
183
  defaultTimeoutMs = opts.defaultTimeoutMs;
184
184
  } else {
185
185
  throw new HealthError("health/bad-opt",
186
186
  "defaultTimeoutMs must be a positive finite integer; got " +
187
- nb.shape(opts.defaultTimeoutMs));
187
+ numericBounds.shape(opts.defaultTimeoutMs));
188
188
  }
189
189
  var cacheMs;
190
190
  if (opts.cacheMs === undefined) {
191
191
  cacheMs = 0;
192
- } else if (nb.isNonNegativeFiniteInt(opts.cacheMs)) {
192
+ } else if (numericBounds.isNonNegativeFiniteInt(opts.cacheMs)) {
193
193
  cacheMs = opts.cacheMs;
194
194
  } else {
195
195
  throw new HealthError("health/bad-opt",
196
196
  "cacheMs must be a non-negative finite integer; got " +
197
- nb.shape(opts.cacheMs));
197
+ numericBounds.shape(opts.cacheMs));
198
198
  }
199
199
  var includeMeta = opts.includeMeta !== false;
200
200
  var version = opts.version || null;
@@ -237,12 +237,12 @@ function create(opts) {
237
237
  var timeoutMs;
238
238
  if (copts.timeoutMs === undefined) {
239
239
  timeoutMs = defaultTimeoutMs;
240
- } else if (nb.isPositiveFiniteInt(copts.timeoutMs)) {
240
+ } else if (numericBounds.isPositiveFiniteInt(copts.timeoutMs)) {
241
241
  timeoutMs = copts.timeoutMs;
242
242
  } else {
243
243
  throw new HealthError("health/bad-opt",
244
244
  "registerCheck: timeoutMs must be a positive finite integer; got " +
245
- nb.shape(copts.timeoutMs));
245
+ numericBounds.shape(copts.timeoutMs));
246
246
  }
247
247
  checks.push({
248
248
  name: name,