@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
@@ -46,10 +46,10 @@
46
46
  * compressor (gzip, zstd) downstream of the framework primitive.
47
47
  */
48
48
 
49
- var fs = require("fs");
50
- var path = require("path");
49
+ var nodeFs = require("fs");
50
+ var nodePath = require("path");
51
51
  var atomicFile = require("../atomic-file");
52
- var backupCrypto = require("./crypto");
52
+ var bCrypto = require("./crypto");
53
53
  var backupManifest = require("./manifest");
54
54
  var validateOpts = require("../validate-opts");
55
55
  var { defineClass } = require("../framework-error");
@@ -68,19 +68,19 @@ function _emit(cb, ev) {
68
68
  function _encryptedPathFor(relativePath) {
69
69
  // POSIX-normalize separators in the bundle so manifests written on
70
70
  // Windows and Linux look the same on disk.
71
- var posix = relativePath.split(path.sep).join("/");
71
+ var posix = relativePath.split(nodePath.sep).join("/");
72
72
  return "files/" + posix + ".enc";
73
73
  }
74
74
 
75
75
  async function create(opts) {
76
76
  var t0 = Date.now();
77
77
  opts = opts || {};
78
- if (typeof opts.dataDir !== "string" || !fs.existsSync(opts.dataDir)) {
78
+ if (typeof opts.dataDir !== "string" || !nodeFs.existsSync(opts.dataDir)) {
79
79
  throw new BackupBundleError("backup-bundle/no-datadir",
80
80
  "create: opts.dataDir is required and must exist");
81
81
  }
82
82
  validateOpts.requireNonEmptyString(opts.outDir, "create: opts.outDir", BackupBundleError, "backup-bundle/no-outdir");
83
- if (fs.existsSync(opts.outDir)) {
83
+ if (nodeFs.existsSync(opts.outDir)) {
84
84
  throw new BackupBundleError("backup-bundle/outdir-exists",
85
85
  "create: outDir already exists: " + opts.outDir +
86
86
  " (refusing to overwrite — pick a fresh path)");
@@ -104,11 +104,11 @@ async function create(opts) {
104
104
  var progress = opts.progressCallback;
105
105
 
106
106
  atomicFile.ensureDir(outDir);
107
- atomicFile.ensureDir(path.join(outDir, "files"));
107
+ atomicFile.ensureDir(nodePath.join(outDir, "files"));
108
108
 
109
109
  // 1. Encrypt the vault key JSON
110
110
  _emit(progress, { phase: "wrap_vault_key" });
111
- var wrappedVk = await backupCrypto.encryptWithFreshSalt(opts.vaultKeyJson, passphrase);
111
+ var wrappedVk = await bCrypto.encryptWithFreshSalt(opts.vaultKeyJson, passphrase);
112
112
 
113
113
  // 2. Walk each include entry, encrypt the bytes, emit a blob
114
114
  var fileEntries = [];
@@ -124,8 +124,8 @@ async function create(opts) {
124
124
  throw new BackupBundleError("backup-bundle/bad-include",
125
125
  "create: files[" + i + "].relativePath must be a relative path (got '" + entry.relativePath + "')");
126
126
  }
127
- var srcPath = path.join(dataDir, entry.relativePath);
128
- if (!fs.existsSync(srcPath)) {
127
+ var srcPath = nodePath.join(dataDir, entry.relativePath);
128
+ if (!nodeFs.existsSync(srcPath)) {
129
129
  if (entry.required) {
130
130
  throw new BackupBundleError("backup-bundle/missing-required",
131
131
  "create: required file missing: " + entry.relativePath);
@@ -133,7 +133,7 @@ async function create(opts) {
133
133
  _emit(progress, { phase: "skip_missing", relativePath: entry.relativePath });
134
134
  continue;
135
135
  }
136
- var stat = fs.statSync(srcPath);
136
+ var stat = nodeFs.statSync(srcPath);
137
137
  if (!stat.isFile()) {
138
138
  // Directories aren't supported in this slice — the bundler
139
139
  // operates on a flat list of files. Operator wanting a recursive
@@ -143,12 +143,12 @@ async function create(opts) {
143
143
  }
144
144
 
145
145
  _emit(progress, { phase: "read", relativePath: entry.relativePath, size: stat.size });
146
- var plain = fs.readFileSync(srcPath);
147
- var checksum = backupCrypto.checksum(plain);
148
- var encResult = await backupCrypto.encryptWithFreshSalt(plain, passphrase);
146
+ var plain = nodeFs.readFileSync(srcPath);
147
+ var checksum = bCrypto.checksum(plain);
148
+ var encResult = await bCrypto.encryptWithFreshSalt(plain, passphrase);
149
149
  var encPath = _encryptedPathFor(entry.relativePath);
150
- var destFull = path.join(outDir, encPath);
151
- atomicFile.ensureDir(path.dirname(destFull));
150
+ var destFull = nodePath.join(outDir, encPath);
151
+ atomicFile.ensureDir(nodePath.dirname(destFull));
152
152
  atomicFile.writeSync(destFull, encResult.encrypted, { fileMode: 0o600 });
153
153
 
154
154
  var kind = entry.kind || "raw";
@@ -217,7 +217,7 @@ async function create(opts) {
217
217
  }
218
218
  }
219
219
  }
220
- var manifestPath = path.join(outDir, "manifest.json");
220
+ var manifestPath = nodePath.join(outDir, "manifest.json");
221
221
  atomicFile.writeSync(manifestPath, backupManifest.serialize(manifest), { fileMode: 0o600 });
222
222
 
223
223
  var durationMs = Date.now() - t0;
@@ -48,10 +48,10 @@
48
48
  * PQC-encrypted backup bundles — sealed columns + audit chain + keyring.
49
49
  */
50
50
 
51
- var fs = require("fs");
51
+ var nodeFs = require("fs");
52
52
  var os = require("os");
53
- var path = require("path");
54
- var crypto = require("../crypto");
53
+ var nodePath = require("path");
54
+ var bCrypto = require("../crypto");
55
55
  var atomicFile = require("../atomic-file");
56
56
  var backupBundle = require("./bundle");
57
57
  var backupManifest = require("./manifest");
@@ -93,16 +93,16 @@ function _isValidBundleId(s) {
93
93
  }
94
94
 
95
95
  function _generateBundleId() {
96
- return atomicFile.pathTimestamp() + "-" + crypto.generateToken(4);
96
+ return atomicFile.pathTimestamp() + "-" + bCrypto.generateToken(4);
97
97
  }
98
98
 
99
99
  function _dirSize(p) {
100
100
  var total = 0;
101
- var entries = fs.readdirSync(p, { withFileTypes: true });
101
+ var entries = nodeFs.readdirSync(p, { withFileTypes: true });
102
102
  for (var i = 0; i < entries.length; i++) {
103
- var f = path.join(p, entries[i].name);
103
+ var f = nodePath.join(p, entries[i].name);
104
104
  if (entries[i].isDirectory()) total += _dirSize(f);
105
- else if (entries[i].isFile()) total += fs.statSync(f).size;
105
+ else if (entries[i].isFile()) total += nodeFs.statSync(f).size;
106
106
  }
107
107
  return total;
108
108
  }
@@ -150,7 +150,7 @@ function localStorage(opts) {
150
150
  throw new BackupError("backup/bad-bundle-id",
151
151
  "bundleId must match the framework's timestamp+suffix format");
152
152
  }
153
- return path.join(root, bundleId);
153
+ return nodePath.join(root, bundleId);
154
154
  }
155
155
 
156
156
  return {
@@ -158,7 +158,7 @@ function localStorage(opts) {
158
158
  async writeBundle(bundleId, sourceDir) {
159
159
  atomicFile.ensureDir(root);
160
160
  var dest = _bundlePath(bundleId);
161
- if (fs.existsSync(dest)) {
161
+ if (nodeFs.existsSync(dest)) {
162
162
  throw new BackupError("backup/bundle-exists",
163
163
  "writeBundle: bundle '" + bundleId + "' already exists in storage");
164
164
  }
@@ -166,26 +166,26 @@ function localStorage(opts) {
166
166
  },
167
167
  async readBundle(bundleId, destDir) {
168
168
  var src = _bundlePath(bundleId);
169
- if (!fs.existsSync(src)) {
169
+ if (!nodeFs.existsSync(src)) {
170
170
  throw new BackupError("backup/bundle-not-found",
171
171
  "readBundle: '" + bundleId + "' not in storage at " + root);
172
172
  }
173
- if (fs.existsSync(destDir)) {
173
+ if (nodeFs.existsSync(destDir)) {
174
174
  throw new BackupError("backup/dest-exists",
175
175
  "readBundle: destDir already exists: " + destDir);
176
176
  }
177
177
  atomicFile.copyDirRecursive(src, destDir);
178
178
  },
179
179
  async listBundles() {
180
- if (!fs.existsSync(root)) return [];
181
- var entries = fs.readdirSync(root, { withFileTypes: true });
180
+ if (!nodeFs.existsSync(root)) return [];
181
+ var entries = nodeFs.readdirSync(root, { withFileTypes: true });
182
182
  var out = [];
183
183
  for (var i = 0; i < entries.length; i++) {
184
184
  if (!entries[i].isDirectory()) continue;
185
185
  if (!_isValidBundleId(entries[i].name)) continue;
186
- var p = path.join(root, entries[i].name);
186
+ var p = nodePath.join(root, entries[i].name);
187
187
  var stat;
188
- try { stat = fs.statSync(p); } catch (_e) { continue; }
188
+ try { stat = nodeFs.statSync(p); } catch (_e) { continue; }
189
189
  var size;
190
190
  try { size = _dirSize(p); } catch (_e) { size = 0; }
191
191
  out.push({
@@ -200,11 +200,11 @@ function localStorage(opts) {
200
200
  },
201
201
  async deleteBundle(bundleId) {
202
202
  var p = _bundlePath(bundleId);
203
- if (!fs.existsSync(p)) return;
204
- fs.rmSync(p, { recursive: true, force: true });
203
+ if (!nodeFs.existsSync(p)) return;
204
+ nodeFs.rmSync(p, { recursive: true, force: true });
205
205
  },
206
206
  async hasBundle(bundleId) {
207
- try { return fs.existsSync(_bundlePath(bundleId)); }
207
+ try { return nodeFs.existsSync(_bundlePath(bundleId)); }
208
208
  catch (_e) { return false; }
209
209
  },
210
210
  };
@@ -285,10 +285,10 @@ async function _resolveVaultKeyJson(vaultKeyJsonOpt) {
285
285
  * var path = require("node:path");
286
286
  * var os = require("node:os");
287
287
  *
288
- * var dataDir = fs.mkdtempSync(path.join(os.tmpdir(), "backup-data-"));
289
- * var root = fs.mkdtempSync(path.join(os.tmpdir(), "backup-root-"));
290
- * fs.writeFileSync(path.join(dataDir, "db.enc"), Buffer.from([1, 2, 3]));
291
- * fs.writeFileSync(path.join(dataDir, "db.key.enc"), Buffer.from([4, 5, 6]));
288
+ * var dataDir = nodeFs.mkdtempSync(nodePath.join(os.tmpdir(), "backup-data-"));
289
+ * var root = nodeFs.mkdtempSync(nodePath.join(os.tmpdir(), "backup-root-"));
290
+ * nodeFs.writeFileSync(nodePath.join(dataDir, "db.enc"), Buffer.from([1, 2, 3]));
291
+ * nodeFs.writeFileSync(nodePath.join(dataDir, "db.key.enc"), Buffer.from([4, 5, 6]));
292
292
  *
293
293
  * var engine = b.backup.create({
294
294
  * dataDir: dataDir,
@@ -308,7 +308,7 @@ async function _resolveVaultKeyJson(vaultKeyJsonOpt) {
308
308
  */
309
309
  function create(opts) {
310
310
  opts = opts || {};
311
- if (typeof opts.dataDir !== "string" || !fs.existsSync(opts.dataDir)) {
311
+ if (typeof opts.dataDir !== "string" || !nodeFs.existsSync(opts.dataDir)) {
312
312
  throw new BackupError("backup/no-datadir",
313
313
  "create: opts.dataDir is required and must exist");
314
314
  }
@@ -456,7 +456,7 @@ function create(opts) {
456
456
  runOpts = runOpts || {};
457
457
  var t0 = Date.now();
458
458
  var bundleId = _generateBundleId();
459
- var stagingDir = path.join(os.tmpdir(),
459
+ var stagingDir = nodePath.join(os.tmpdir(),
460
460
  "blamejs-backup-staging-" + bundleId.replace(/[:.]/g, "-"));
461
461
 
462
462
  // Flush the live DB to disk so the snapshot is current. Default
@@ -500,7 +500,7 @@ function create(opts) {
500
500
  progressCallback: runOpts.progressCallback,
501
501
  });
502
502
  } catch (e) {
503
- try { fs.rmSync(stagingDir, { recursive: true, force: true }); } catch (_e) { /* best-effort tmpdir cleanup */ }
503
+ try { nodeFs.rmSync(stagingDir, { recursive: true, force: true }); } catch (_e) { /* best-effort tmpdir cleanup */ }
504
504
  _emitAudit("backup.failure",
505
505
  { bundleId: bundleId, reason: (e && e.message) || String(e) }, "failure");
506
506
  throw e;
@@ -509,7 +509,7 @@ function create(opts) {
509
509
  try {
510
510
  await storage.writeBundle(bundleId, stagingDir);
511
511
  } catch (e) {
512
- try { fs.rmSync(stagingDir, { recursive: true, force: true }); } catch (_e) { /* best-effort tmpdir cleanup */ }
512
+ try { nodeFs.rmSync(stagingDir, { recursive: true, force: true }); } catch (_e) { /* best-effort tmpdir cleanup */ }
513
513
  _emitAudit("backup.failure",
514
514
  { bundleId: bundleId, reason: "storage.writeBundle: " + ((e && e.message) || String(e)) },
515
515
  "failure");
@@ -517,7 +517,7 @@ function create(opts) {
517
517
  "writing bundle to storage failed: " + ((e && e.message) || String(e)));
518
518
  }
519
519
 
520
- try { fs.rmSync(stagingDir, { recursive: true, force: true }); } catch (_e) { /* best-effort */ }
520
+ try { nodeFs.rmSync(stagingDir, { recursive: true, force: true }); } catch (_e) { /* best-effort */ }
521
521
 
522
522
  var summary = {
523
523
  bundleId: bundleId,
@@ -675,11 +675,11 @@ function create(opts) {
675
675
  }
676
676
  // Newest bundle (storage.listBundles returns newest first).
677
677
  var bundleId = bundles[0].bundleId;
678
- var stagingDir = path.join(testOpts.restoreTo,
678
+ var stagingDir = nodePath.join(testOpts.restoreTo,
679
679
  "test-" + bundleId.replace(/[:.]/g, "-"));
680
680
  // Refuse to overwrite an existing dir — operators get a fresh
681
681
  // restore every drill.
682
- if (fs.existsSync(stagingDir)) {
682
+ if (nodeFs.existsSync(stagingDir)) {
683
683
  _emitAudit("backup.test.failed",
684
684
  { bundleId: bundleId, reason: "stagingDir already exists: " + stagingDir },
685
685
  "failure");
@@ -688,12 +688,12 @@ function create(opts) {
688
688
  var manifestPath, manifest, sigVerification;
689
689
  try {
690
690
  await storage.readBundle(bundleId, stagingDir);
691
- manifestPath = path.join(stagingDir, "manifest.json");
692
- if (!fs.existsSync(manifestPath)) {
691
+ manifestPath = nodePath.join(stagingDir, "manifest.json");
692
+ if (!nodeFs.existsSync(manifestPath)) {
693
693
  throw new BackupError("backup/test-no-manifest",
694
694
  "manifest.json missing under restored bundle " + bundleId);
695
695
  }
696
- manifest = backupManifest.parse(fs.readFileSync(manifestPath, "utf8"));
696
+ manifest = backupManifest.parse(nodeFs.readFileSync(manifestPath, "utf8"));
697
697
  // Verify the manifest signature so a tampered backup test
698
698
  // surfaces here, not as a regulator finding later.
699
699
  sigVerification = backupManifest.verifySignature(manifest, {
@@ -740,7 +740,7 @@ function create(opts) {
740
740
  // Best-effort cleanup so the staging dir doesn't accumulate
741
741
  // across drills.
742
742
  if (testOpts.cleanup !== false) {
743
- try { fs.rmSync(stagingDir, { recursive: true, force: true }); }
743
+ try { nodeFs.rmSync(stagingDir, { recursive: true, force: true }); }
744
744
  catch (_e) { /* tmpdir cleanup best-effort */ }
745
745
  }
746
746
  }
@@ -804,12 +804,12 @@ function verifyManifestSignature(target, opts) {
804
804
  opts = opts || {};
805
805
  var manifest;
806
806
  if (typeof target === "string") {
807
- var manifestPath = path.join(target, "manifest.json");
808
- if (!fs.existsSync(manifestPath)) {
807
+ var manifestPath = nodePath.join(target, "manifest.json");
808
+ if (!nodeFs.existsSync(manifestPath)) {
809
809
  throw new BackupError("backup/no-manifest",
810
810
  "verifyManifestSignature: manifest.json missing at " + manifestPath);
811
811
  }
812
- try { manifest = backupManifest.parse(fs.readFileSync(manifestPath, "utf8")); }
812
+ try { manifest = backupManifest.parse(nodeFs.readFileSync(manifestPath, "utf8")); }
813
813
  catch (e) {
814
814
  throw new BackupError("backup/bad-manifest",
815
815
  "verifyManifestSignature: parse failed: " + ((e && e.message) || String(e)));
package/lib/budr.js CHANGED
@@ -24,7 +24,7 @@
24
24
  * Backup / Disaster-Recovery RTO/RPO declaration primitive for regulated workloads (HIPAA / DORA / ISO 22301:2019 / NIST SP 800-34).
25
25
  */
26
26
 
27
- var nb = require("./numeric-bounds");
27
+ var numericBounds = require("./numeric-bounds");
28
28
  var validateOpts = require("./validate-opts");
29
29
  var audit = require("./audit");
30
30
  var { defineClass } = require("./framework-error");
@@ -85,8 +85,8 @@ function declare(opts) {
85
85
  throw BudrError.factory("BAD_SERVICE",
86
86
  "budr.declare: service must match " + SERVICE_RE);
87
87
  }
88
- nb.requirePositiveFiniteIntIfPresent(opts.rtoMs, "budr.declare: rtoMs", BudrError, "BAD_RTO");
89
- nb.requirePositiveFiniteIntIfPresent(opts.rpoMs, "budr.declare: rpoMs", BudrError, "BAD_RPO");
88
+ numericBounds.requirePositiveFiniteIntIfPresent(opts.rtoMs, "budr.declare: rtoMs", BudrError, "BAD_RTO");
89
+ numericBounds.requirePositiveFiniteIntIfPresent(opts.rpoMs, "budr.declare: rpoMs", BudrError, "BAD_RPO");
90
90
  if (typeof opts.rtoMs !== "number" || typeof opts.rpoMs !== "number") {
91
91
  throw BudrError.factory("BAD_TARGETS",
92
92
  "budr.declare: rtoMs and rpoMs are required positive integer milliseconds");
package/lib/bundler.js CHANGED
@@ -26,7 +26,7 @@
26
26
  * override via `opts.hashLen` between 4 and 64). Source maps written
27
27
  * by an engine land as `<hashed>.<ext>.map` siblings.
28
28
  *
29
- * Watch mode: `bundler.watch(callback)` arms `fs.watch` on each
29
+ * Watch mode: `bundler.watch(callback)` arms `nodeFs.watch` on each
30
30
  * entry's directory, debounces bursts via `opts.graceMs` (default
31
31
  * 100 ms), and rebuilds the entire entry set on change.
32
32
  *
@@ -43,12 +43,12 @@
43
43
  * Client-side asset bundler — produces content-hashed `dist/<name>.<hash>.<ext>` files plus a `manifest.json` mapping logical name to hashed filename.
44
44
  */
45
45
 
46
- var path = require("path");
47
- var fs = require("fs");
48
- var crypto = require("./crypto");
46
+ var nodePath = require("path");
47
+ var nodeFs = require("fs");
48
+ var bCrypto = require("./crypto");
49
49
  var atomicFile = require("./atomic-file");
50
50
  var logModule = require("./log");
51
- var nb = require("./numeric-bounds");
51
+ var numericBounds = require("./numeric-bounds");
52
52
  var safeJson = require("./safe-json");
53
53
  var validateOpts = require("./validate-opts");
54
54
  var { defineClass } = require("./framework-error");
@@ -67,7 +67,7 @@ var DEFAULT_GRACE_MS = 100;
67
67
  function _hashContent(buf, hexLen) {
68
68
  // SHA3-512 → take the first hexLen hex chars. Same family as the
69
69
  // framework's other content fingerprints (no SHA-256 for new code).
70
- return crypto.sha3Hash(buf).slice(0, hexLen);
70
+ return bCrypto.sha3Hash(buf).slice(0, hexLen);
71
71
  }
72
72
 
73
73
  function _hashedName(baseName, hash, ext) {
@@ -200,7 +200,7 @@ function _validateEngine(eng) {
200
200
  * Build a content-hashed asset pipeline for a fixed set of named
201
201
  * entries. The returned object exposes `build()` (one-shot rebuild,
202
202
  * resolves to `{ outputs, manifestPath, manifest, durationMs }`),
203
- * `watch(callback)` (arm `fs.watch` and debounce-rebuild on change),
203
+ * `watch(callback)` (arm `nodeFs.watch` and debounce-rebuild on change),
204
204
  * and `close()` (drop watchers and pending timers).
205
205
  *
206
206
  * Throws `BundlerError` at config time on missing / malformed entries,
@@ -257,7 +257,7 @@ function create(opts) {
257
257
 
258
258
  var entries = Object.assign({}, opts.entries);
259
259
  var cwd = opts.cwd || process.cwd();
260
- var outdir = path.isAbsolute(opts.outdir) ? opts.outdir : path.resolve(cwd, opts.outdir);
260
+ var outdir = nodePath.isAbsolute(opts.outdir) ? opts.outdir : nodePath.resolve(cwd, opts.outdir);
261
261
  var manifestName = (opts.manifest === false || opts.manifest === null)
262
262
  ? null
263
263
  : (typeof opts.manifest === "string" && opts.manifest.length > 0
@@ -266,24 +266,24 @@ function create(opts) {
266
266
  var hashOn = opts.hash !== false;
267
267
  var hashLen = DEFAULT_HASH_LEN;
268
268
  if (opts.hashLen !== undefined) {
269
- if (!nb.isPositiveFiniteInt(opts.hashLen) ||
269
+ if (!numericBounds.isPositiveFiniteInt(opts.hashLen) ||
270
270
  opts.hashLen < MIN_HASH_LEN || opts.hashLen > MAX_HASH_LEN) {
271
271
  throw new BundlerError("bundler/bad-hash-len",
272
272
  "bundler.create: opts.hashLen must be a positive finite integer " +
273
273
  "between " + MIN_HASH_LEN + " and " + MAX_HASH_LEN +
274
- "; got " + nb.shape(opts.hashLen));
274
+ "; got " + numericBounds.shape(opts.hashLen));
275
275
  }
276
276
  hashLen = opts.hashLen;
277
277
  }
278
278
  var log = opts.log || null;
279
279
 
280
- // Test seam: tests pass a fake watcher so we don't actually fs.watch
280
+ // Test seam: tests pass a fake watcher so we don't actually nodeFs.watch
281
281
  var watchFn = opts._watch || function (dirOrFile, wopts, listener) {
282
- return fs.watch(dirOrFile, wopts, listener);
282
+ return nodeFs.watch(dirOrFile, wopts, listener);
283
283
  };
284
284
  var setTimeoutFn = opts._setTimeout || setTimeout;
285
285
  var clearTimeoutFn = opts._clearTimeout || clearTimeout;
286
- nb.requireNonNegativeFiniteIntIfPresent(opts.graceMs,
286
+ numericBounds.requireNonNegativeFiniteIntIfPresent(opts.graceMs,
287
287
  "bundler.create: opts.graceMs", BundlerError, "bundler/bad-grace-ms");
288
288
  var graceMs = opts.graceMs !== undefined ? opts.graceMs : DEFAULT_GRACE_MS;
289
289
 
@@ -292,7 +292,7 @@ function create(opts) {
292
292
  var watching = false;
293
293
 
294
294
  function _resolveEntry(p) {
295
- return path.isAbsolute(p) ? p : path.resolve(cwd, p);
295
+ return nodePath.isAbsolute(p) ? p : nodePath.resolve(cwd, p);
296
296
  }
297
297
 
298
298
  var _logVia = logModule.makeViaOrFallback(log, bootLog);
@@ -308,9 +308,9 @@ function create(opts) {
308
308
  for (var i = 0; i < names.length; i++) {
309
309
  var name = names[i];
310
310
  var entryPath = _resolveEntry(entries[name]);
311
- var ext = path.extname(entryPath);
311
+ var ext = nodePath.extname(entryPath);
312
312
  var raw;
313
- try { raw = fs.readFileSync(entryPath); }
313
+ try { raw = nodeFs.readFileSync(entryPath); }
314
314
  catch (e) {
315
315
  throw new BundlerError("bundler/read-failed",
316
316
  "could not read entry '" + name + "' at " + entryPath +
@@ -333,7 +333,7 @@ function create(opts) {
333
333
  var sourceMap = transformed && transformed.sourceMap;
334
334
  var hash = hashOn ? _hashContent(content, hashLen) : null;
335
335
  var outName = hashOn ? _hashedName(name, hash, ext) : (name + ext);
336
- var outPath = path.join(outdir, outName);
336
+ var outPath = nodePath.join(outdir, outName);
337
337
  // atomic-file write so a concurrent reader (the http server
338
338
  // serving outdir) never sees a partial file
339
339
  atomicFile.writeSync(outPath, content, { mode: 0o644 });
@@ -360,7 +360,7 @@ function create(opts) {
360
360
 
361
361
  var manifestPath = null;
362
362
  if (manifestName) {
363
- manifestPath = path.join(outdir, manifestName);
363
+ manifestPath = nodePath.join(outdir, manifestName);
364
364
  atomicFile.writeSync(
365
365
  manifestPath,
366
366
  safeJson.stringify(manifest, null, 2) + "\n",
@@ -407,8 +407,8 @@ function create(opts) {
407
407
  // Watch the entry's directory (single-file watches are flaky
408
408
  // across editors that write-then-rename). Filter events to the
409
409
  // entry's basename only.
410
- var dir = path.dirname(entryPath);
411
- var base = path.basename(entryPath);
410
+ var dir = nodePath.dirname(entryPath);
411
+ var base = nodePath.basename(entryPath);
412
412
  var w;
413
413
  try {
414
414
  w = watchFn(dir, { persistent: false }, function (eventType, filename) {
@@ -24,7 +24,7 @@
24
24
  * Top-level circuit-breaker primitive.
25
25
  */
26
26
 
27
- var retry = require("./retry");
27
+ var retryHelper = require("./retry");
28
28
 
29
29
  /**
30
30
  * @primitive b.circuitBreaker.create
@@ -34,11 +34,18 @@ var retry = require("./retry");
34
34
  * @related b.retry, b.httpClient
35
35
  *
36
36
  * Build a circuit-breaker. Returns a CircuitBreaker instance with
37
- * `wrap(fn)` (executes `fn` if the breaker is closed; throws RetryError
38
- * with `code: "retry/circuit-open"` when open), `state()`, `reset()`,
39
- * and `onStateChange(handler)` listener registration. Pass-through
40
- * factory: identical instance shape to `b.retry.CircuitBreaker`, with
41
- * the framework's `create(opts)` vocabulary.
37
+ * `wrap(fn)` (executes `fn` if the breaker is closed; throws an
38
+ * `Error` with `code: "CIRCUIT_OPEN"` + `isObjectStoreError: true` +
39
+ * `permanent: false` when open), `state()`, `reset()`, and
40
+ * `onStateChange(handler)` listener registration. Pass-through
41
+ * factory: identical instance shape to `b.retry.CircuitBreaker`,
42
+ * with the framework's `create(opts)` vocabulary.
43
+ *
44
+ * The `CIRCUIT_OPEN` error code is a pre-v1 artifact — every other
45
+ * framework error class uses namespaced codes (`retry/...`). The
46
+ * rename is deferred to v0.10 with a deprecation cycle so existing
47
+ * operators who match `err.code === "CIRCUIT_OPEN"` aren't broken
48
+ * in a patch.
42
49
  *
43
50
  * @opts
44
51
  * name: string, // identifier used in audit + state-change events
@@ -65,14 +72,22 @@ var retry = require("./retry");
65
72
  * result.value; // → 42
66
73
  */
67
74
  function create(opts) {
68
- return new retry.CircuitBreaker(opts || {});
75
+ // The CircuitBreaker class constructor is `(name, opts)` passing a
76
+ // single opts object lands it in the positional `name` slot, and the
77
+ // validator throws "name must be a non-empty string, got object."
78
+ // The factory's documented shape is `create({ name, ...opts })`;
79
+ // split the name out of opts before invoking the constructor.
80
+ // Caught by hermitstash-sync operator review against v0.9.12.
81
+ opts = opts || {};
82
+ var name = (opts && typeof opts.name === "string") ? opts.name : "";
83
+ return new retryHelper.CircuitBreaker(name, opts);
69
84
  }
70
85
 
71
86
  module.exports = {
72
87
  create: create,
73
- CircuitBreaker: retry.CircuitBreaker,
88
+ CircuitBreaker: retryHelper.CircuitBreaker,
74
89
  // Forward the error class so operators catching breaker rejections
75
90
  // can `instanceof` against the framework's RetryError without
76
91
  // requiring a separate b.retry import.
77
- RetryError: retry.RetryError,
92
+ RetryError: retryHelper.RetryError,
78
93
  };