@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/network.js CHANGED
@@ -34,8 +34,8 @@ var byteQuota = require("./network-byte-quota");
34
34
  var ntpCheck = require("./ntp-check");
35
35
  var nts = require("./network-nts");
36
36
  var dns = require("./network-dns");
37
- var proxy = require("./network-proxy");
38
- var trust = require("./network-tls");
37
+ var networkProxy = require("./network-proxy");
38
+ var networkTls = require("./network-tls");
39
39
  var heartbeat = require("./network-heartbeat");
40
40
  var smtpPolicy = require("./network-smtp-policy");
41
41
  var ssrfGuard = require("./ssrf-guard");
@@ -223,19 +223,19 @@ function bootFromEnv(opts) {
223
223
 
224
224
  if (env.HTTP_PROXY || env.http_proxy || env.HTTPS_PROXY || env.https_proxy ||
225
225
  env.NO_PROXY || env.no_proxy || env.ALL_PROXY || env.all_proxy) {
226
- applied.proxy = proxy.fromEnv(env);
226
+ applied.proxy = networkProxy.fromEnv(env);
227
227
  }
228
228
 
229
229
  if (env.BLAMEJS_EXTRA_CA_CERTS) {
230
- trust.addCa(env.BLAMEJS_EXTRA_CA_CERTS, { label: "BLAMEJS_EXTRA_CA_CERTS" });
230
+ networkTls.addCa(env.BLAMEJS_EXTRA_CA_CERTS, { label: "BLAMEJS_EXTRA_CA_CERTS" });
231
231
  applied.tls.fileLoaded = env.BLAMEJS_EXTRA_CA_CERTS;
232
232
  }
233
233
  if (env.BLAMEJS_EXTRA_CA_CERTS_DIR) {
234
- trust.addCaBundle(env.BLAMEJS_EXTRA_CA_CERTS_DIR, { label: "BLAMEJS_EXTRA_CA_CERTS_DIR" });
234
+ networkTls.addCaBundle(env.BLAMEJS_EXTRA_CA_CERTS_DIR, { label: "BLAMEJS_EXTRA_CA_CERTS_DIR" });
235
235
  applied.tls.dirLoaded = env.BLAMEJS_EXTRA_CA_CERTS_DIR;
236
236
  }
237
237
  if (env.BLAMEJS_USE_SYSTEM_TRUST === "1" || env.BLAMEJS_USE_SYSTEM_TRUST === "true") {
238
- trust.useSystemTrust(true);
238
+ networkTls.useSystemTrust(true);
239
239
  applied.tls.systemTrust = true;
240
240
  }
241
241
 
@@ -287,10 +287,10 @@ function snapshot() {
287
287
  thresholds: ntpCheck.getThresholds(),
288
288
  },
289
289
  dns: dns._stateForTest(),
290
- proxy: proxy.snapshot(),
290
+ proxy: networkProxy.snapshot(),
291
291
  tls: {
292
- systemTrust: trust.isSystemTrustEnabled(),
293
- caCount: trust.getTrustStore().length,
292
+ systemTrust: networkTls.isSystemTrustEnabled(),
293
+ caCount: networkTls.getTrustStore().length,
294
294
  },
295
295
  heartbeat: heartbeat.statuses(),
296
296
  socket: _socketDefaults(),
@@ -306,8 +306,8 @@ function _resetForTest() {
306
306
  ntpFacade._defaultTimeoutMs = null;
307
307
  if (typeof ntpCheck._resetThresholdsForTest === "function") ntpCheck._resetThresholdsForTest();
308
308
  dns._resetForTest();
309
- proxy._resetForTest();
310
- trust._resetForTest();
309
+ networkProxy._resetForTest();
310
+ networkTls._resetForTest();
311
311
  heartbeat._resetForTest();
312
312
  SOCKET_DEFAULTS.noDelay = true;
313
313
  SOCKET_DEFAULTS.keepAlive = true;
@@ -317,8 +317,8 @@ function _resetForTest() {
317
317
  module.exports = {
318
318
  ntp: ntpFacade,
319
319
  dns: dns,
320
- proxy: proxy,
321
- tls: trust,
320
+ proxy: networkProxy,
321
+ tls: networkTls,
322
322
  heartbeat: heartbeat,
323
323
  smtp: {
324
324
  policy: smtpPolicy,
package/lib/notify.js CHANGED
@@ -41,7 +41,7 @@
41
41
  */
42
42
 
43
43
  var lazyRequire = require("./lazy-require");
44
- var bootLog = require("./log");
44
+ var logModule = require("./log");
45
45
  var numericChecks = require("./numeric-checks");
46
46
  var requestHelpers = require("./request-helpers");
47
47
  var safeAsync = require("./safe-async");
@@ -282,14 +282,14 @@ function httpJson(opts) {
282
282
  // log — fire-and-forget developer logger. Never throws; audit + obs still emit.
283
283
  function logTransport(opts) {
284
284
  opts = opts || {};
285
- // bootLog.boot() returns a callable with .info / .warn / .error
285
+ // logModule.boot() returns a callable with .info / .warn / .error
286
286
  // attached; that shape satisfies the operator-supplied opts.logger
287
287
  // contract directly. No fallback wrapper needed.
288
288
  var logger;
289
289
  if (opts.logger && typeof opts.logger.info === "function") {
290
290
  logger = opts.logger;
291
291
  } else {
292
- logger = bootLog.boot("notify.log");
292
+ logger = logModule.boot("notify.log");
293
293
  }
294
294
  return {
295
295
  name: opts.name || "log",
@@ -23,7 +23,7 @@
23
23
  * Auth: same service-account JSON / RSA-SHA256-signed JWT exchanged
24
24
  * for an OAuth2 access token as `lib/object-store/gcs.js`.
25
25
  */
26
- var fs = require("node:fs");
26
+ var nodeFs = require("node:fs");
27
27
  var gcs = require("./gcs");
28
28
  var authHeader = require("../auth-header");
29
29
  var httpClient = require("../http-client");
@@ -139,7 +139,7 @@ function create(config) {
139
139
  var serviceAccount = config.serviceAccount;
140
140
  if (!serviceAccount && config.serviceAccountFile) {
141
141
  try {
142
- serviceAccount = safeJson.parse(fs.readFileSync(config.serviceAccountFile));
142
+ serviceAccount = safeJson.parse(nodeFs.readFileSync(config.serviceAccountFile));
143
143
  } catch (e) {
144
144
  throw _err("BAD_OPT", "gcs bucketOps: failed to read serviceAccountFile '" +
145
145
  config.serviceAccountFile + "': " + ((e && e.message) || String(e)), true);
@@ -22,12 +22,12 @@
22
22
  * https://cloud.google.com/storage/docs/json_api/v1
23
23
  * https://developers.google.com/identity/protocols/oauth2/service-account
24
24
  */
25
- var fs = require("fs");
25
+ var nodeFs = require("fs");
26
26
  var nodeCrypto = require("crypto");
27
27
  var { Readable } = require("stream");
28
28
  var safeJson = require("../safe-json");
29
29
  var C = require("../constants");
30
- var nb = require("../numeric-bounds");
30
+ var numericBounds = require("../numeric-bounds");
31
31
  var requestHelpers = require("../request-helpers");
32
32
  var { ObjectStoreError } = require("../framework-error");
33
33
  var safeUrl = require("../safe-url");
@@ -125,7 +125,7 @@ function create(config) {
125
125
  var serviceAccount = config.serviceAccount;
126
126
  if (!serviceAccount && config.serviceAccountFile) {
127
127
  try {
128
- serviceAccount = safeJson.parse(fs.readFileSync(config.serviceAccountFile), { schema: SERVICE_ACCOUNT_SCHEMA });
128
+ serviceAccount = safeJson.parse(nodeFs.readFileSync(config.serviceAccountFile), { schema: SERVICE_ACCOUNT_SCHEMA });
129
129
  } catch (e) {
130
130
  throw new Error("gcs: failed to read serviceAccountFile '" + config.serviceAccountFile + "': " + e.message);
131
131
  }
@@ -421,10 +421,10 @@ function create(config) {
421
421
  "POST-form policy enforces body size via the content-length-range condition; " +
422
422
  "use presignedUploadUrl if size enforcement is not needed", true);
423
423
  }
424
- if (opts.minBytes !== undefined && !nb.isNonNegativeFiniteInt(opts.minBytes)) {
424
+ if (opts.minBytes !== undefined && !numericBounds.isNonNegativeFiniteInt(opts.minBytes)) {
425
425
  throw _err("INVALID_MIN_BYTES",
426
426
  "presignedUploadPolicy: minBytes must be a non-negative finite integer; got " +
427
- nb.shape(opts.minBytes), true);
427
+ numericBounds.shape(opts.minBytes), true);
428
428
  }
429
429
  var minBytes = opts.minBytes !== undefined ? opts.minBytes : 0;
430
430
  var expiresIn = opts.expiresIn != null ? opts.expiresIn : PRESIGN_DEFAULT_EXPIRES_SECONDS;
@@ -29,11 +29,11 @@
29
29
  */
30
30
  var localProto = require("./local");
31
31
  var httpPutProto = require("./http-put");
32
- var sigv4Proto = require("./sigv4");
32
+ var sigv4 = require("./sigv4");
33
33
  var sigv4BucketOps = require("./sigv4-bucket-ops");
34
- var gcsProto = require("./gcs");
34
+ var gcs = require("./gcs");
35
35
  var gcsBucketOps = require("./gcs-bucket-ops");
36
- var azureBlobProto = require("./azure-blob");
36
+ var azureBlob = require("./azure-blob");
37
37
  var azureBlobBucketOps = require("./azure-blob-bucket-ops");
38
38
  var retryHelper = require("../retry");
39
39
  var protocolDispatcher = require("../protocol-dispatcher");
@@ -47,9 +47,9 @@ var dispatcher = protocolDispatcher.create({
47
47
  protocols: {
48
48
  "local": localProto,
49
49
  "http-put": httpPutProto,
50
- "sigv4": sigv4Proto,
51
- "gcs": gcsProto,
52
- "azure-blob": azureBlobProto,
50
+ "sigv4": sigv4,
51
+ "gcs": gcs,
52
+ "azure-blob": azureBlob,
53
53
  },
54
54
  deferred: {},
55
55
  fallbackProtocol: "local",
@@ -4,15 +4,15 @@
4
4
  *
5
5
  * Implements the uniform protocol surface (put / get / getStream / delete /
6
6
  * head / list) against a directory tree. Streaming is via Node's native
7
- * fs.createReadStream / createWriteStream — no in-memory buffering of
7
+ * nodeFs.createReadStream / createWriteStream — no in-memory buffering of
8
8
  * full files.
9
9
  *
10
10
  * Path safety: every key resolves under the configured rootDir, with an
11
11
  * alphanumeric + `_-./` charset whitelist and explicit rejection of any
12
12
  * path that escapes rootDir after resolution.
13
13
  */
14
- var fs = require("fs");
15
- var path = require("path");
14
+ var nodeFs = require("fs");
15
+ var nodePath = require("path");
16
16
  var atomicFile = require("../atomic-file");
17
17
  var cluster = require("../cluster");
18
18
  var { ObjectStoreError } = require("../framework-error");
@@ -24,10 +24,10 @@ function _resolveSafe(rootDir, key) {
24
24
  throw _err("INVALID_KEY", "key must be a non-empty string", true);
25
25
  }
26
26
  if (key.includes("\0")) throw _err("INVALID_KEY", "null byte in key", true);
27
- if (path.isAbsolute(key)) throw _err("INVALID_KEY", "absolute key not allowed", true);
27
+ if (nodePath.isAbsolute(key)) throw _err("INVALID_KEY", "absolute key not allowed", true);
28
28
  if (!SAFE_KEY.test(key)) throw _err("INVALID_KEY", "invalid characters in key", true);
29
- var full = path.resolve(rootDir, key);
30
- var withSep = rootDir.endsWith(path.sep) ? rootDir : rootDir + path.sep;
29
+ var full = nodePath.resolve(rootDir, key);
30
+ var withSep = rootDir.endsWith(nodePath.sep) ? rootDir : rootDir + nodePath.sep;
31
31
  if (full !== rootDir && !full.startsWith(withSep)) {
32
32
  throw _err("INVALID_KEY", "key escapes rootDir", true);
33
33
  }
@@ -40,14 +40,14 @@ function create(config) {
40
40
  if (!config || !config.rootDir) {
41
41
  throw new Error("local protocol requires { rootDir }");
42
42
  }
43
- var rootDir = path.resolve(config.rootDir);
44
- if (!fs.existsSync(rootDir)) fs.mkdirSync(rootDir, { recursive: true });
43
+ var rootDir = nodePath.resolve(config.rootDir);
44
+ if (!nodeFs.existsSync(rootDir)) nodeFs.mkdirSync(rootDir, { recursive: true });
45
45
 
46
46
  function put(key, body, _opts) {
47
47
  cluster.requireLeader();
48
48
  var full = _resolveSafe(rootDir, key);
49
- var dir = path.dirname(full);
50
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
49
+ var dir = nodePath.dirname(full);
50
+ if (!nodeFs.existsSync(dir)) nodeFs.mkdirSync(dir, { recursive: true });
51
51
 
52
52
  if (Buffer.isBuffer(body)) {
53
53
  atomicFile.writeSync(full, body);
@@ -56,7 +56,7 @@ function create(config) {
56
56
  if (body && typeof body.pipe === "function") {
57
57
  // Streaming put — pipe directly to disk
58
58
  return new Promise(function (resolve, reject) {
59
- var ws = fs.createWriteStream(full);
59
+ var ws = nodeFs.createWriteStream(full);
60
60
  var bytes = 0;
61
61
  body.on("data", function (chunk) { bytes += chunk.length; });
62
62
  body.pipe(ws);
@@ -75,26 +75,26 @@ function create(config) {
75
75
 
76
76
  function get(key) {
77
77
  var full = _resolveSafe(rootDir, key);
78
- if (!fs.existsSync(full)) {
78
+ if (!nodeFs.existsSync(full)) {
79
79
  return Promise.reject(_err("NOT_FOUND", "key not found: " + key, true));
80
80
  }
81
- return Promise.resolve(fs.readFileSync(full));
81
+ return Promise.resolve(nodeFs.readFileSync(full));
82
82
  }
83
83
 
84
84
  function getStream(key) {
85
85
  var full = _resolveSafe(rootDir, key);
86
- if (!fs.existsSync(full)) {
86
+ if (!nodeFs.existsSync(full)) {
87
87
  throw _err("NOT_FOUND", "key not found: " + key, true);
88
88
  }
89
- return fs.createReadStream(full);
89
+ return nodeFs.createReadStream(full);
90
90
  }
91
91
 
92
92
  function head(key) {
93
93
  var full = _resolveSafe(rootDir, key);
94
- if (!fs.existsSync(full)) {
94
+ if (!nodeFs.existsSync(full)) {
95
95
  return Promise.reject(_err("NOT_FOUND", "key not found: " + key, true));
96
96
  }
97
- var stat = fs.statSync(full);
97
+ var stat = nodeFs.statSync(full);
98
98
  return Promise.resolve({
99
99
  size: stat.size,
100
100
  lastModified: stat.mtimeMs,
@@ -104,8 +104,8 @@ function create(config) {
104
104
  function deleteKey(key) {
105
105
  cluster.requireLeader();
106
106
  var full = _resolveSafe(rootDir, key);
107
- if (!fs.existsSync(full)) return Promise.resolve(false);
108
- fs.unlinkSync(full);
107
+ if (!nodeFs.existsSync(full)) return Promise.resolve(false);
108
+ nodeFs.unlinkSync(full);
109
109
  return Promise.resolve(true);
110
110
  }
111
111
 
@@ -29,7 +29,7 @@ var { Readable } = require("stream");
29
29
  var safeXml = require("../parsers/safe-xml");
30
30
  var sharedRequest = require("./http-request");
31
31
  var C = require("../constants");
32
- var nb = require("../numeric-bounds");
32
+ var numericBounds = require("../numeric-bounds");
33
33
  var requestHelpers = require("../request-helpers");
34
34
  var { ObjectStoreError } = require("../framework-error");
35
35
  var safeUrl = require("../safe-url");
@@ -821,10 +821,10 @@ function create(config) {
821
821
  "POST-form policy enforces body size via the content-length-range condition; " +
822
822
  "use presignedUploadUrl if size enforcement is not needed", true);
823
823
  }
824
- if (opts.minBytes !== undefined && !nb.isNonNegativeFiniteInt(opts.minBytes)) {
824
+ if (opts.minBytes !== undefined && !numericBounds.isNonNegativeFiniteInt(opts.minBytes)) {
825
825
  throw _err("INVALID_MIN_BYTES",
826
826
  "presignedUploadPolicy: minBytes must be a non-negative finite integer; got " +
827
- nb.shape(opts.minBytes), true);
827
+ numericBounds.shape(opts.minBytes), true);
828
828
  }
829
829
  var minBytes = opts.minBytes !== undefined ? opts.minBytes : 0;
830
830
  var expiresIn = opts.expiresIn != null ? opts.expiresIn : PRESIGN_DEFAULT_EXPIRES_SECONDS;
@@ -73,14 +73,14 @@
73
73
  */
74
74
 
75
75
  var bCrypto = require("./crypto");
76
- var constants = require("./constants");
76
+ var C = require("./constants");
77
77
  var lazyRequire = require("./lazy-require");
78
78
  var safeBuffer = require("./safe-buffer");
79
79
  var validateOpts = require("./validate-opts");
80
80
  var { defineClass } = require("./framework-error");
81
81
 
82
- var TRACE_ID_BYTES = constants.BYTES.bytes(16); // W3C §3.2.2.3 — 128-bit trace-id
83
- var SPAN_ID_BYTES = constants.BYTES.bytes(8); // W3C §3.2.2.4 — 64-bit span-id
82
+ var TRACE_ID_BYTES = C.BYTES.bytes(16); // W3C §3.2.2.3 — 128-bit trace-id
83
+ var SPAN_ID_BYTES = C.BYTES.bytes(8); // W3C §3.2.2.4 — 64-bit span-id
84
84
 
85
85
  var TracerError = defineClass("TracerError", { alwaysPermanent: true });
86
86
 
@@ -168,7 +168,7 @@ function create(opts) {
168
168
  var resource = Object.assign({
169
169
  "service.name": opts.service,
170
170
  }, opts.resource || {});
171
- var scope = opts.scope || { name: "blamejs", version: constants.version || null };
171
+ var scope = opts.scope || { name: "blamejs", version: C.version || null };
172
172
  var maxAttributes = opts.maxAttributes || DEFAULT_MAX_ATTRIBUTES;
173
173
  var maxEvents = opts.maxEvents || DEFAULT_MAX_EVENTS;
174
174
  var maxAttrValLen = opts.maxAttributeValueLength || DEFAULT_MAX_ATTR_VALUE_LEN;
@@ -41,7 +41,7 @@
41
41
  */
42
42
  var C = require("./constants");
43
43
  var canonicalJson = require("./canonical-json");
44
- var defaultHttpClient = require("./http-client");
44
+ var httpClient = require("./http-client");
45
45
  var safeAsync = require("./safe-async");
46
46
  var validateOpts = require("./validate-opts");
47
47
  var { defineClass } = require("./framework-error");
@@ -110,7 +110,7 @@ function create(opts) {
110
110
  throw new OtelExportError("otel-export/bad-interval",
111
111
  "create: intervalMs must be a non-negative finite number");
112
112
  }
113
- var httpClient = opts.httpClient || defaultHttpClient;
113
+ var effectiveHttpClient = opts.httpClient || httpClient;
114
114
  var scopeName = (opts.scope && opts.scope.name) || "blamejs";
115
115
  var scopeVersion = (opts.scope && opts.scope.version) || "0.5.x";
116
116
  var resourceAttrs = Object.assign({ "service.name": serviceName },
@@ -220,7 +220,7 @@ function create(opts) {
220
220
  if (!payload) return { sent: false, reason: "no-data" };
221
221
  var body = JSON.stringify(payload);
222
222
  try {
223
- var res = await httpClient.request({
223
+ var res = await effectiveHttpClient.request({
224
224
  method: "POST",
225
225
  url: endpoint,
226
226
  headers: Object.assign({ "Content-Type": "application/json" }, headers),
package/lib/pagination.js CHANGED
@@ -49,8 +49,8 @@
49
49
  var nodeCrypto = require("node:crypto");
50
50
  var C = require("./constants");
51
51
  var canonicalJson = require("./canonical-json");
52
- var crypto = require("./crypto");
53
- var nb = require("./numeric-bounds");
52
+ var bCrypto = require("./crypto");
53
+ var numericBounds = require("./numeric-bounds");
54
54
  var safeJson = require("./safe-json");
55
55
  var safeSql = require("./safe-sql");
56
56
  var { defineClass } = require("./framework-error");
@@ -185,7 +185,7 @@ function decodeCursor(token, secret) {
185
185
  throw new PaginationError("pagination/bad-cursor", "cursor base64 decode failed");
186
186
  }
187
187
  var expected = _tag(sb, json);
188
- if (!crypto.timingSafeEqual(tag, expected)) {
188
+ if (!bCrypto.timingSafeEqual(tag, expected)) {
189
189
  throw new PaginationError("pagination/cursor-tag-mismatch",
190
190
  "cursor HMAC verification failed (tampered or wrong secret)");
191
191
  }
@@ -205,9 +205,9 @@ function decodeCursor(token, secret) {
205
205
  }
206
206
 
207
207
  function _resolveLimit(opts) {
208
- nb.requirePositiveFiniteIntIfPresent(opts.max,
208
+ numericBounds.requirePositiveFiniteIntIfPresent(opts.max,
209
209
  "max", PaginationError, "pagination/bad-opt");
210
- nb.requirePositiveFiniteIntIfPresent(opts.default,
210
+ numericBounds.requirePositiveFiniteIntIfPresent(opts.default,
211
211
  "default", PaginationError, "pagination/bad-opt");
212
212
  var max = opts.max || DEFAULT_MAX_LIMIT;
213
213
  var def = opts.default || DEFAULT_LIMIT;
@@ -40,7 +40,7 @@
40
40
  */
41
41
 
42
42
  var C = require("../constants");
43
- var nb = require("../numeric-bounds");
43
+ var numericBounds = require("../numeric-bounds");
44
44
  var safeBuffer = require("../safe-buffer");
45
45
  var { FrameworkError } = require("../framework-error");
46
46
 
@@ -77,10 +77,10 @@ var BUILT_IN_ENTITIES = { lt: "<", gt: ">", amp: "&", quot: "\"", apos: "'" };
77
77
 
78
78
  function _validateAndCap(name, value, defaultValue, ceiling) {
79
79
  if (value === undefined) return defaultValue;
80
- if (!nb.isPositiveFiniteInt(value)) {
80
+ if (!numericBounds.isPositiveFiniteInt(value)) {
81
81
  throw new SafeXmlError("xml/bad-opt",
82
82
  "xml.parse: " + name + " must be a positive finite integer; got " +
83
- nb.shape(value));
83
+ numericBounds.shape(value));
84
84
  }
85
85
  return Math.min(value, ceiling);
86
86
  }
package/lib/pqc-agent.js CHANGED
@@ -1,31 +1,29 @@
1
1
  "use strict";
2
2
  /**
3
- * pqc-agent — outbound HTTPS agent locked to PQC group preference.
3
+ * @module b.pqcAgent
4
+ * @nav Production
5
+ * @title PQC Agent
6
+ * @order 630
4
7
  *
5
- * The framework's posture is "all outbound TLS is PQC-only". This is
6
- * the single primitive that defines what that means at the agent
7
- * level: TLSv1.3 minimum, ecdhCurve set to the framework's PQC hybrid
8
- * preference (constants.TLS_GROUP_CURVE_STR), keep-alive on.
8
+ * @intro
9
+ * Outbound HTTPS agent locked to the framework's PQC group preference.
10
+ * The framework's posture is "all outbound TLS is PQC-only"; this
11
+ * primitive defines what that means at the agent level — TLSv1.3
12
+ * minimum, `ecdhCurve` set to the framework's PQC hybrid preference
13
+ * (`constants.TLS_GROUP_CURVE_STR`), keep-alive on.
9
14
  *
10
- * Two surfaces:
15
+ * `b.pqcAgent.agent` is a process-wide default agent, lazy-built on
16
+ * first access; `b.pqcAgent.create(opts)` builds a fresh agent with
17
+ * custom pool / timeout opts (ecdhCurve and minVersion cannot be
18
+ * weakened); `b.pqcAgent.reload()` tears down the default agent so
19
+ * the next access rebuilds against current TLS posture.
11
20
  *
12
- * 1. b.pqcAgent.agent a process-wide default agent, lazy-built on
13
- * first access. Use this for one-off outbound calls that go
14
- * through node:https directly:
21
+ * `lib/http-client.js`'s transport cache uses `pqcAgent.create()` under
22
+ * the hood, so the framework's bundled HTTP client and any operator-
23
+ * direct `https.request` calls converge on the same agent posture.
15
24
  *
16
- * https.request(url, { agent: b.pqcAgent.agent }, ...);
17
- *
18
- * 2. b.pqcAgent.create(opts) — build a fresh agent with custom
19
- * pool / timeout opts. ecdhCurve and minVersion CANNOT be
20
- * weakened via opts; operator-supplied values for those are
21
- * ignored and the framework's defaults win. Operators who need
22
- * a non-PQC agent for a deliberate one-off integration with a
23
- * non-PQC server construct their own new https.Agent() directly,
24
- * outside this primitive.
25
- *
26
- * lib/http-client.js's transport cache uses pqcAgent.create() under
27
- * the hood, so the framework's bundled HTTP client and any operator-
28
- * direct https.request calls converge on the same agent posture.
25
+ * @card
26
+ * Outbound HTTPS agent locked to TLSv1.3 + framework PQC hybrid group preference.
29
27
  */
30
28
 
31
29
  var https = require("node:https");
@@ -152,14 +150,63 @@ function _buildAgentOpts(opts) {
152
150
  return merged;
153
151
  }
154
152
 
153
+ /**
154
+ * @primitive b.pqcAgent.create
155
+ * @signature b.pqcAgent.create(opts?)
156
+ * @since 0.5.0
157
+ * @status stable
158
+ * @related b.pqcAgent.reload
159
+ *
160
+ * Build a fresh https.Agent locked to the framework PQC hybrid group
161
+ * preference (TLSv1.3 minimum, ecdhCurve set to
162
+ * `C.TLS_GROUP_CURVE_STR`). Operator-supplied values for ecdhCurve
163
+ * may NARROW the framework default (drop a group) but cannot widen it
164
+ * unless `opts.allowOperatorGroups: true` is set; minVersion is fixed
165
+ * at TLSv1.3 and cannot be weakened.
166
+ *
167
+ * @opts
168
+ * keepAlive?: boolean,
169
+ * keepAliveMsecs?: number,
170
+ * maxSockets?: number,
171
+ * maxFreeSockets?: number,
172
+ * scheduling?: string,
173
+ * ecdhCurve?: string, // colon-separated group names; must subset C.TLS_GROUP_PREFERENCE
174
+ * allowOperatorGroups?: boolean, // default false; opt in to operator-supplied groups outside the framework PQC preference
175
+ *
176
+ * @example
177
+ * var agent = b.pqcAgent.create({ maxSockets: 200 });
178
+ * var req = https.request("https://api.example.com/v1/x", { agent: agent });
179
+ * req.end();
180
+ */
155
181
  function create(opts) {
156
182
  return new https.Agent(_buildAgentOpts(opts));
157
183
  }
158
184
 
159
- // http (cleartext) variant — same pool defaults but obviously no TLS
160
- // posture to enforce. Operator-side, almost no caller wants this; it
161
- // exists so http-client's h1 transport for cleartext origins (h2c
162
- // fixtures, internal services) shares the pool tuning.
185
+ /**
186
+ * @primitive b.pqcAgent.createHttp
187
+ * @signature b.pqcAgent.createHttp(opts?)
188
+ * @since 0.5.0
189
+ * @status stable
190
+ * @related b.pqcAgent.create
191
+ *
192
+ * Build a cleartext `http.Agent` with the same pool defaults as
193
+ * `b.pqcAgent.create` — no TLS posture to enforce. Exists so the
194
+ * framework's HTTP client's h1 transport for cleartext origins (h2c
195
+ * fixtures, internal services on a private network) shares the same
196
+ * pool tuning as the encrypted path.
197
+ *
198
+ * @opts
199
+ * keepAlive?: boolean,
200
+ * keepAliveMsecs?: number,
201
+ * maxSockets?: number,
202
+ * maxFreeSockets?: number,
203
+ * scheduling?: string,
204
+ *
205
+ * @example
206
+ * var agent = b.pqcAgent.createHttp({ maxSockets: 100 });
207
+ * var req = http.request("http://internal.svc/health", { agent: agent });
208
+ * req.end();
209
+ */
163
210
  function createHttp(opts) {
164
211
  return new http.Agent(Object.assign({}, DEFAULT_OPTS, opts || {}));
165
212
  }
@@ -173,11 +220,54 @@ function _getDefaultAgent() {
173
220
  return _defaultAgent;
174
221
  }
175
222
 
223
+ /**
224
+ * @primitive b.pqcAgent.reload
225
+ * @signature b.pqcAgent.reload()
226
+ * @since 0.9.14
227
+ * @status stable
228
+ * @related b.pqcAgent.create
229
+ *
230
+ * Tear down the lazily-built default agent and reset to null so the
231
+ * next `b.pqcAgent.agent` access rebuilds against current TLS posture
232
+ * + network-tls applyToContext output.
233
+ *
234
+ * Long-running daemons that rotate the framework's TLS posture (via
235
+ * `b.network.tls` config refresh, certificate-pinset reload, or a
236
+ * `C.TLS_GROUP_PREFERENCE` update behind a feature flag) need a way
237
+ * to re-source the outbound https.Agent without forking a new
238
+ * process. `reload()` calls `.destroy()` on the existing default
239
+ * agent — Node closes idle keep-alive sockets and lets in-flight
240
+ * sockets complete naturally — then nulls the cache so the next
241
+ * `agent` access builds fresh. Agents handed out via explicit
242
+ * `b.pqcAgent.create()` are unaffected; only the framework's lazy
243
+ * default is recycled.
244
+ *
245
+ * Returns `{ destroyed: boolean }` — `destroyed: true` when an agent
246
+ * was actually torn down, `false` when no default had been built
247
+ * (no callers yet asked for it).
248
+ *
249
+ * @example
250
+ * // operator's daemon picked up a refreshed TLS-pinset config:
251
+ * b.network.tls.reload();
252
+ * var res = b.pqcAgent.reload();
253
+ * logger.info("pqc-agent reloaded", res);
254
+ */
255
+ function reload() {
256
+ var hadAgent = _defaultAgent !== null;
257
+ if (hadAgent) {
258
+ try { _defaultAgent.destroy(); }
259
+ catch (_e) { /* destroy is best-effort */ }
260
+ _defaultAgent = null;
261
+ }
262
+ return { destroyed: hadAgent };
263
+ }
264
+
176
265
  module.exports = {
177
266
  // Read property — getter so the agent is built on first access.
178
267
  get agent() { return _getDefaultAgent(); },
179
268
  create: create,
180
269
  createHttp: createHttp,
270
+ reload: reload,
181
271
  DEFAULT_OPTS: DEFAULT_OPTS,
182
272
  KNOWN_TLS_GROUPS: KNOWN_TLS_GROUPS,
183
273
  enforced: true,
package/lib/pqc-gate.js CHANGED
@@ -39,7 +39,7 @@
39
39
  var net = require("node:net");
40
40
  var C = require("./constants");
41
41
  var { PQC_GROUPS } = require("./constants");
42
- var nb = require("./numeric-bounds");
42
+ var numericBounds = require("./numeric-bounds");
43
43
  var validateOpts = require("./validate-opts");
44
44
  var { boot } = require("./log");
45
45
 
@@ -155,14 +155,14 @@ function create(opts) {
155
155
  }
156
156
  var internalHost = typeof opts.internalHost === "string" ? opts.internalHost : "127.0.0.1";
157
157
  var bypass = Array.isArray(opts.bypass) ? opts.bypass.slice() : DEFAULT_BYPASS.slice();
158
- if (opts.clientHelloTimeoutMs !== undefined && !nb.isPositiveFiniteInt(opts.clientHelloTimeoutMs)) {
158
+ if (opts.clientHelloTimeoutMs !== undefined && !numericBounds.isPositiveFiniteInt(opts.clientHelloTimeoutMs)) {
159
159
  throw new Error("pqc-gate: clientHelloTimeoutMs must be a positive finite integer; got " +
160
- nb.shape(opts.clientHelloTimeoutMs));
160
+ numericBounds.shape(opts.clientHelloTimeoutMs));
161
161
  }
162
162
  var clientHelloTimeoutMs = opts.clientHelloTimeoutMs || DEFAULT_CLIENTHELLO_TIMEOUT_MS;
163
- if (opts.maxClientHelloBytes !== undefined && !nb.isPositiveFiniteInt(opts.maxClientHelloBytes)) {
163
+ if (opts.maxClientHelloBytes !== undefined && !numericBounds.isPositiveFiniteInt(opts.maxClientHelloBytes)) {
164
164
  throw new Error("pqc-gate: maxClientHelloBytes must be a positive finite integer; got " +
165
- nb.shape(opts.maxClientHelloBytes));
165
+ numericBounds.shape(opts.maxClientHelloBytes));
166
166
  }
167
167
  var maxClientHelloBytes = opts.maxClientHelloBytes || DEFAULT_MAX_CLIENTHELLO_BYTES;
168
168
  var log = opts.log || null;
@@ -22,7 +22,7 @@
22
22
  * conventions of its own.
23
23
  */
24
24
  var C = require("./constants");
25
- var fwCrypto = require("./crypto");
25
+ var bCrypto = require("./crypto");
26
26
  var lazyRequire = require("./lazy-require");
27
27
  var redisClient = require("./redis-client");
28
28
  var safeJson = require("./safe-json");
@@ -39,7 +39,7 @@ function create(opts) {
39
39
  // the local dispatch synchronously before awaiting the remote
40
40
  // write — without this filter every same-instance publish would
41
41
  // double-fire local handlers).
42
- var instanceNonce = fwCrypto.generateToken(C.BYTES.bytes(8));
42
+ var instanceNonce = bCrypto.generateToken(C.BYTES.bytes(8));
43
43
 
44
44
  var clientOpts = redisClient.pickClientOpts(opts, "redis");
45
45