@blamejs/core 0.15.30 → 0.15.32

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.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,10 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.15.x
10
10
 
11
+ - v0.15.32 (2026-06-26) — **Internal test-suite hardening only — the published library's runtime behavior and public API are unchanged (source-comment marker text aside).** Three more suppression classes in the codebase-patterns guard suite were re-verified from scratch and renamed to descriptive tokens, with their old names recorded as retired so the prior approval cannot be silently resurrected and their in-source marker comments updated to match. No runtime code, public API, or wire format changed. **Detectors:** *Three more suppression-marker classes re-verified and their tokens retired* — Continuing the re-verification pass: each marked site for the process-exit, hand-rolled buffer-collect, and raw-outbound-http guard classes was re-read and confirmed (operator-opt-in exits; bounded protocol-framing / TLV assembly; framework-routed outbound calls), then the class was renamed to a descriptive token and its old name added to the retired-token set. This is test-suite tooling; no shipped framework behavior changed.
12
+
13
+ - v0.15.31 (2026-06-26) — **Internal test-suite hardening only — the published library's runtime behavior and public API are unchanged (source-comment marker text aside).** The codebase-patterns guard suite gains a gate that retires a renamed suppression-marker token: once a suppression class is re-verified and renamed, its old token cannot be silently re-registered, so a later suppression has to be re-examined under the new name instead of inheriting a stale approval. Eight suppression classes were re-verified and renamed to descriptive tokens this release, and their in-source marker comments were updated to match. No runtime code, public API, or wire format changed. **Detectors:** *Re-verification gate retires a renamed suppression-marker token* — A new guard refuses to re-register a retired suppression-marker token, and the orphan check points a stale marker at its current name. When a suppression class is re-verified, it is renamed to a descriptive token and the old name is recorded as retired, so the old approval cannot be quietly resurrected — a future suppression must be re-examined and re-stamped under the new name. This is test-suite tooling; no shipped framework behavior changed.
14
+
11
15
  - v0.15.30 (2026-06-26) — **Importing the webhook module for inbound signature verification no longer pulls the Node HTTP client (or its `node:http` / `node:https` / `node:http2` chain), so `b.webhook.verify` runs in a Worker / edge runtime when the module is imported directly.** lib/webhook and its delivery store eagerly required the outbound HTTP client at module load — directly, and transitively through the persistence-backed dispatcher — so importing the webhook module threw in a Cloudflare Workers / edge runtime that has no node:http / node:net / node:tls, even though b.webhook.verify needs only HMAC-SHA-256 and a timing-safe compare. The HTTP client and the SQL-backed dispatcher are now resolved lazily, only on the outbound send / dispatch paths; importing the module for inbound verification loads no Node networking module. Verified by asserting no networking builtin appears in process.moduleLoadList on the verify path. The framework's aggregate entry point still initializes the networking stack eagerly, so the edge verify path is the webhook module imported directly rather than the aggregate b namespace. **Fixed:** *Inbound webhook verification loads without the Node networking stack (Worker / edge runtime)* — The webhook module and its dispatcher delivery store required the outbound HTTP client (node:http / node:https / node:http2) at module load, so importing the module threw in a runtime without those builtins — even though b.webhook.verify is HMAC-SHA-256 plus a timing-safe compare and the dispatcher (SQL-backed persistence) is only needed for outbound delivery. The HTTP client and the dispatcher are now resolved lazily, on the outbound send / dispatch paths only; the inbound verify path loads no Node networking module. An edge handler that imports the webhook module directly can pre-verify an inbound Stripe webhook signature with the primitive's hardening (Stripe-Signature size cap, v1-hex anti-DoS cap, minimum-tolerance floor, optional atomic replay store) instead of hand-rolling the t=/v1= parse, tolerance window, and timing-safe compare. The framework's aggregate entry still loads the networking stack eagerly; import the webhook module directly for the edge verify path.
12
16
 
13
17
  - v0.15.29 (2026-06-25) — **JSON parsing of operator and untrusted input is routed through `b.safeJson` everywhere, so a `"__proto__"` member is stripped and the parse is size-bounded — `b.openapi.parse`, `b.asyncapi.parse`, and `b.sandbox.run` were using a raw `JSON.parse`.** b.openapi.parse and b.asyncapi.parse parsed an operator-supplied document string with a raw JSON.parse, which re-creates a "__proto__" member as an own key and imposes no size bound; b.sandbox.run parsed the untrusted sandboxed code's serialized result the same way (proto member kept, depth unbounded). All three now route through b.safeJson, which strips the prototype-pollution keys and applies the depth / key / size caps. A new b.safeJson.parseStringOrObject primitive captures the recurring "accept a document as a JSON string OR a pre-built object" shape (a string is parsed safely, an object passes through) that openapi and asyncapi had each hand-rolled, with each consumer's typed error class and a generous document size cap passed as data. Valid input parses identically to before; a malicious or oversized document is now defused rather than accepted. **Added:** *b.safeJson.parseStringOrObject(input, opts?)* — Accepts either a JSON string — parsed through b.safeJson.parse, so the prototype-pollution-key strip and depth / key / size caps apply — or an already-decoded plain object (returned unchanged). For the recurring "operator hands me a document as a JSON string or a pre-built object" surface (b.openapi / b.asyncapi). The consumer's typed error class, error codes, label, and size cap are passed as options, so a raw JSON.parse on operator input cannot be hand-rolled per consumer. **Security:** *Operator and untrusted JSON parses strip __proto__ and bound size (no raw JSON.parse)* — A raw JSON.parse keeps a "__proto__" object member as an own key (a prototype-pollution gadget for any downstream merge) and parses unbounded input. b.openapi.parse and b.asyncapi.parse used it on operator document strings, and b.sandbox.run used it on the untrusted sandboxed code's JSON-serialized result. All now route through b.safeJson — the prototype-pollution keys are stripped and the depth / key / size caps apply (a 16 MiB document cap for openapi/asyncapi, the existing result-bytes cap for the sandbox). Internal JSON parses (the sealed DSR store payloads, the VEX canonical re-format) route through the same primitive too, so the guarantee cannot be bypassed one call site at a time. Valid input is unaffected; a "__proto__"-laden or oversized payload is defused.
@@ -247,7 +247,7 @@ function create(opts) {
247
247
  var exitCode = (process.exitCode !== undefined && process.exitCode !== 0)
248
248
  ? process.exitCode : (allOk ? 0 : 1);
249
249
  setImmediate(function () {
250
- // allow:process-exit — operator opted into exitAfterPhases,
250
+ // allow:process-exit-operator-optin — operator opted into exitAfterPhases,
251
251
  // delegating process lifecycle to the orchestrator
252
252
  process.exit(exitCode);
253
253
  });
@@ -280,7 +280,7 @@ function create(opts) {
280
280
  // Bounded forced exit after the grace deadline, armed ONLY inside the
281
281
  // signal handler (operator opted into installSignalHandlers,
282
282
  // delegating process lifecycle to the orchestrator).
283
- // allow:process-exit — operator-delegated lifecycle, watchdog only
283
+ // allow:process-exit-operator-optin — operator-delegated lifecycle, watchdog only
284
284
  process.exit(process.exitCode || 1);
285
285
  }, graceMs + forceExitMarginMs);
286
286
  if (typeof watchdog.unref === "function") watchdog.unref();
package/lib/arg-parser.js CHANGED
@@ -550,7 +550,7 @@ function create(opts) {
550
550
  // `<prog> help [<cmd>]`
551
551
  var topic = (split.rest && split.rest.length > 0) ? split.rest[0] : null;
552
552
  var msg = topic && commandsByName[topic] ? help(topic) : help();
553
- if (exitOnHelp) { stdout.write(msg + "\n"); process.exit(0); } // allow:process-exit — explicit { exit: true } from a bin/ shim
553
+ if (exitOnHelp) { stdout.write(msg + "\n"); process.exit(0); } // allow:process-exit-operator-optin — explicit { exit: true } from a bin/ shim
554
554
  return { command: null, flags: {}, positionals: [], helpRequested: true, helpText: msg };
555
555
  }
556
556
 
@@ -582,7 +582,7 @@ function create(opts) {
582
582
 
583
583
  if (cmdParsed.helpRequested || preParsed.helpRequested) {
584
584
  var cmsg = _renderCommandHelp(parser, cmdEntry);
585
- if (exitOnHelp) { stdout.write(cmsg + "\n"); process.exit(0); } // allow:process-exit — explicit { exit: true } from a bin/ shim
585
+ if (exitOnHelp) { stdout.write(cmsg + "\n"); process.exit(0); } // allow:process-exit-operator-optin — explicit { exit: true } from a bin/ shim
586
586
  return { command: cmdEntry.name, flags: {}, positionals: [], helpRequested: true, helpText: cmsg };
587
587
  }
588
588
 
@@ -606,7 +606,7 @@ function create(opts) {
606
606
  // as a flag-only parser. Honor `--` and aggregate everything else.
607
607
  if (preParsed.helpRequested) {
608
608
  var hmsg = _renderHelp(parser);
609
- if (exitOnHelp) { stdout.write(hmsg + "\n"); process.exit(0); } // allow:process-exit — explicit { exit: true } from a bin/ shim
609
+ if (exitOnHelp) { stdout.write(hmsg + "\n"); process.exit(0); } // allow:process-exit-operator-optin — explicit { exit: true } from a bin/ shim
610
610
  return { command: null, flags: {}, positionals: [], helpRequested: true, helpText: hmsg };
611
611
  }
612
612
  _applyDefaultsAndRequired(parser.flags.list, preParsed.flags, "top-level");
@@ -420,7 +420,7 @@ function _verifyAndParseBlob(token) {
420
420
  * typeof blob.entries.length === "number";
421
421
  * // → true
422
422
  */
423
- async function fetch(opts) { // allow:raw-outbound-http — function name is fetch, internal call routes through b.httpClient
423
+ async function fetch(opts) { // allow:raw-outbound-http-framework-internal — function name is fetch, internal call routes through b.httpClient
424
424
  opts = opts || {};
425
425
  validateOpts(opts, ["url", "caCertificate", "force", "timeoutMs"], "auth.fido_mds3.fetch");
426
426
 
package/lib/cert.js CHANGED
@@ -721,7 +721,7 @@ function create(opts) {
721
721
  var chain = _splitPemChain(ctx.cert);
722
722
  if (chain.length < 2) return; // no issuer in the served chain
723
723
  try {
724
- // allow:raw-outbound-http — b.network.tls.ocsp.fetch composes b.httpClient internally (SSRF guard + pinned DNS); not a raw outbound call
724
+ // allow:raw-outbound-http-framework-internal — b.network.tls.ocsp.fetch composes b.httpClient internally (SSRF guard + pinned DNS); not a raw outbound call
725
725
  var rv = await networkTls().ocsp.fetch({ leafPem: chain[0], issuerPem: chain[1] });
726
726
  ctx.ocspResponse = rv.ocspDer;
727
727
  _emitAudit("cert.ocsp.refreshed", "success", { name: name });
package/lib/compliance.js CHANGED
@@ -443,7 +443,7 @@ function set(posture) {
443
443
  // guaranteed). Pure signal — no behavior change.
444
444
  var REGULATED = ["hipaa", "pci-dss", "sox", "gdpr", "soc2", "fda-21cfr11"];
445
445
  if (REGULATED.indexOf(posture) !== -1) {
446
- var tz = process.env.TZ; // allow:raw-process-env — bootstrap signal, no operator-supplied default needed
446
+ var tz = process.env.TZ; // allow:raw-process-env-bootstrap — bootstrap signal, no operator-supplied default needed
447
447
  if (typeof tz === "string" && tz !== "UTC" && tz !== "Etc/UTC") {
448
448
  _emitAudit("compliance.posture.tz_warning",
449
449
  { posture: posture, tz: tz, recommendation: "Set TZ=UTC under regulated postures so audit timestamps align with regulator expectations." },
@@ -288,7 +288,7 @@ function fileLifecycle(opts) {
288
288
  "fileLifecycle.startFlushTimer: timer already running — call stop() first");
289
289
  }
290
290
  var interval = sopts.intervalMs || flushIntervalMs;
291
- encTimer = setInterval(function () { // allow:timer-no-unref — .unref() called immediately below; timer doesn't pin the event loop
291
+ encTimer = setInterval(function () { // allow:timer-no-unref-unrefed-below — .unref() called immediately below; timer doesn't pin the event loop
292
292
  try { flushNow(db); }
293
293
  catch (e) {
294
294
  _emitAudit("flush_failed", "failure", {
@@ -242,7 +242,7 @@ function validate(headerValue, opts) {
242
242
  // so a `localhost.` label-suffix is already refused at the segment-
243
243
  // shape level (an empty trailing segment fails the dot-atom-text
244
244
  // grammar). No trailing-dot bypass surface here.
245
- var isLocalScopeTld = lastLabel === "localhost" || lastLabel === "local" || lastLabel === "lan"; // allow:hostname-compare-trailing-dot — see comment above; List-Id parts already split on `.` so trailing-dot label is empty and refused upstream
245
+ var isLocalScopeTld = lastLabel === "localhost" || lastLabel === "local" || lastLabel === "lan"; // allow:hostname-compare-trailing-dot-pre-split-refused — see comment above; List-Id parts already split on `.` so trailing-dot label is empty and refused upstream
246
246
  if (caps.requireFqdn) {
247
247
  if (parts.length < 3 && !isLocalScopeTld) { // FQDN requires ≥ 3 labels for non-local-scope namespace
248
248
  return _refuse("list-id has < 3 labels for non-local-scope namespace (FQDN required under '" +
package/lib/log.js CHANGED
@@ -589,7 +589,7 @@ function _escapeC0Controls(s) {
589
589
  // runs before safeEnv on the boot path; safeEnv requires log, so log
590
590
  // can't go through safeEnv to read its own level.
591
591
  function _bootMinLevel() {
592
- // allow:raw-process-env — see header comment above
592
+ // allow:raw-process-env-bootstrap — see header comment above
593
593
  var raw = process.env.BLAMEJS_BOOT_LOG_LEVEL || process.env.LOG_LEVEL || "info";
594
594
  return Object.prototype.hasOwnProperty.call(LEVELS, raw) ? LEVELS[raw] : LEVELS.info;
595
595
  }
@@ -563,7 +563,7 @@ function sign(opts) {
563
563
  // signed-part bytes plus the armored signature.
564
564
  // MIME-boundary uniqueness only (not a security token); operator
565
565
  // key/cert material flows through createSign/verify, not this path.
566
- // allow:raw-randombytes-token — boundary string, not auth credential
566
+ // allow:raw-randombytes-token-mime-boundary — boundary string, not auth credential
567
567
  var boundary = "blamejs-pgp-" + nodeCrypto.randomBytes(12).toString("hex");
568
568
  // The OpenPGP signature covers the signed-part bytes exactly, so the
569
569
  // multipart/signed wrapper is assembled as a Buffer — a JS-string round
@@ -213,7 +213,7 @@ async function _applyMtaStsPolicy(domain, mxs, policyMode, auditEmit) {
213
213
  if (policyMode === "off") return mxs;
214
214
  var sts;
215
215
  try {
216
- sts = await smtpPolicy().mtaSts.fetch(domain); // allow:raw-outbound-http — method call on b.network.smtp.policy wrapper, not a raw `fetch(`
216
+ sts = await smtpPolicy().mtaSts.fetch(domain); // allow:raw-outbound-http-framework-internal — method call on b.network.smtp.policy wrapper, not a raw `fetch(`
217
217
  } catch (e) {
218
218
  if (policyMode === "enforce") {
219
219
  throw new DeliverError("deliver/mta-sts-fetch-failed",
@@ -72,7 +72,7 @@ function _scheme(req) {
72
72
  // client used (forwarded), NOT a Secure/HSTS/origin trust decision. Routing
73
73
  // through trustedProtocol would drop the forwarded scheme from spans behind a
74
74
  // proxy (less accurate telemetry) for no security gain.
75
- // allow:raw-xfp — telemetry label, not a trust sink (see above).
75
+ // allow:raw-xfp-telemetry-only — telemetry label, not a trust sink (see above).
76
76
  var x = req.headers && (req.headers["x-forwarded-proto"] || "");
77
77
  if (typeof x === "string" && x.length > 0) {
78
78
  var first = x.split(",")[0].trim().toLowerCase();
@@ -82,7 +82,7 @@ function _scheme(req) {
82
82
  }
83
83
 
84
84
  function _serverAddress(req) {
85
- // allow:raw-xfp — display-only: server.address span attribute (telemetry),
85
+ // allow:raw-xfp-telemetry-only — display-only: server.address span attribute (telemetry),
86
86
  // not an authority trust decision. Same rationale as _scheme above.
87
87
  var hostHeader = req.headers && (req.headers["x-forwarded-host"] || req.headers.host);
88
88
  if (typeof hostHeader === "string" && hostHeader.length > 0) {
@@ -488,7 +488,7 @@ async function _wireLookup(name, qtype, timeoutMs) {
488
488
  // Raw DoH wire-format request — bypasses b.httpClient envelope
489
489
  // because we need the raw binary response bytes for safeDns to
490
490
  // parse (httpClient assumes JSON/text shapes).
491
- var req = https.request({ // allow:raw-outbound-http — DoH wire-format response bytes; b.httpClient envelopes assume text/JSON, and httpClient → ssrfGuard → DNS → DoH would form a cycle
491
+ var req = https.request({ // allow:raw-outbound-http-framework-internal — DoH wire-format response bytes; b.httpClient envelopes assume text/JSON, and httpClient → ssrfGuard → DNS → DoH would form a cycle
492
492
  hostname: u.hostname,
493
493
  port: u.port || 443, // HTTPS port
494
494
  path: u.pathname + u.search,
@@ -660,7 +660,7 @@ async function tlsRptSubmit(report, opts) {
660
660
  try {
661
661
  if (/^https:\/\//i.test(uri)) {
662
662
  entry.kind = "https";
663
- // allow:raw-outbound-http — `client` is the framework httpClient
663
+ // allow:raw-outbound-http-framework-internal — `client` is the framework httpClient
664
664
  // (or operator-supplied test mock); SSRF + DNS-pin already
665
665
  // applied through the framework wrapper.
666
666
  var rv = await client.request({
package/lib/pqc-gate.js CHANGED
@@ -232,7 +232,7 @@ function create(opts) {
232
232
  // each chunk to read the record-length prefix) before deciding
233
233
  // whether more data is needed. boundedChunkCollector is append-
234
234
  // only with no peek, doesn't fit.
235
- // allow:handrolled-buffer-collect — see comment above
235
+ // allow:handrolled-buffer-collect-bounded-framing — see comment above
236
236
  var buf = Buffer.concat(chunks);
237
237
  var recordLen = buf.readUInt16BE(3);
238
238
  var neededLen = 5 + recordLen;
package/lib/static.js CHANGED
@@ -1409,7 +1409,7 @@ function create(opts) {
1409
1409
  // pre-allocate a closure for every served byte. Tracked for extraction.
1410
1410
  var idleTimer = null;
1411
1411
  function resetIdleTimer() {
1412
- if (idleTimer) clearTimeout(idleTimer); // allow:handrolled-debounce — file-stream idle deadline
1412
+ if (idleTimer) clearTimeout(idleTimer); // allow:handrolled-debounce-stream-idle — file-stream idle deadline
1413
1413
  idleTimer = setTimeout(function () {
1414
1414
  try { fileStream.destroy(_err("IDLE_TIMEOUT", "client idle for " + maxIdleMs + "ms")); }
1415
1415
  catch (_) { /* stream already torn down */ }
@@ -1420,7 +1420,7 @@ function create(opts) {
1420
1420
 
1421
1421
  // Cancellation propagation: when the client disconnects mid-stream.
1422
1422
  function onClientClose() {
1423
- try { fileStream.destroy(); } catch (_) { /* allow:silent-catch — stream already torn down */ }
1423
+ try { fileStream.destroy(); } catch (_) { /* allow:silent-catch-stream-teardown — stream already torn down */ }
1424
1424
  releaseSlot();
1425
1425
  if (idleTimer) { clearTimeout(idleTimer); idleTimer = null; }
1426
1426
  }
@@ -1442,7 +1442,7 @@ function create(opts) {
1442
1442
  error: e && e.message,
1443
1443
  }, actorCtx));
1444
1444
  }
1445
- try { res.destroy(e); } catch (_) { /* allow:silent-catch — response already torn down */ }
1445
+ try { res.destroy(e); } catch (_) { /* allow:silent-catch-stream-teardown — response already torn down */ }
1446
1446
  releaseSlot();
1447
1447
  if (idleTimer) { clearTimeout(idleTimer); idleTimer = null; }
1448
1448
  });
package/lib/vault-aad.js CHANGED
@@ -99,7 +99,7 @@ function _canonicalize(parts) {
99
99
  valLenBuf.writeUInt32BE(valBuf.length);
100
100
  chunks.push(keyLenBuf, keyBuf, valLenBuf, valBuf);
101
101
  }
102
- return Buffer.concat(chunks); // allow:handrolled-buffer-collect — AAD canonicalization, bounded by length-prefixed field shape
102
+ return Buffer.concat(chunks); // allow:handrolled-buffer-collect-bounded-framing — AAD canonicalization, bounded by length-prefixed field shape
103
103
  }
104
104
 
105
105
  function buildColumnAad(opts) {
@@ -113,7 +113,7 @@ function _timingSafeHexEqual(a, b) {
113
113
  // length now guarantees equal byte length.
114
114
  var ba = Buffer.from(a, "utf8");
115
115
  var bb = Buffer.from(b, "utf8");
116
- return nodeCrypto.timingSafeEqual(ba, bb); // allow:raw-timing-safe-equal — hex + length pre-check above guarantees same-length ASCII inputs; b.crypto wrapper would be circular at boot
116
+ return nodeCrypto.timingSafeEqual(ba, bb); // allow:raw-timing-safe-equal-boot-prechecked — hex + length pre-check above guarantees same-length ASCII inputs; b.crypto wrapper would be circular at boot
117
117
  }
118
118
 
119
119
  // KNOWN_VENDOR_DATA — the canonical list of vendored data names. Each
package/lib/watcher.js CHANGED
@@ -528,7 +528,7 @@ function create(opts) {
528
528
  throw new WatcherError("watcher/start-failed",
529
529
  "watcher.create: initial poll walk failed: " + ((e && e.message) || String(e)));
530
530
  }
531
- pollTimer = setInterval(_pollTick, pollIntervalMs); // allow:timer-no-unref — .unref() called immediately below; timer doesn't pin the event loop
531
+ pollTimer = setInterval(_pollTick, pollIntervalMs); // allow:timer-no-unref-unrefed-below — .unref() called immediately below; timer doesn't pin the event loop
532
532
  if (typeof pollTimer.unref === "function") pollTimer.unref();
533
533
  } else {
534
534
  try {
package/lib/ws-client.js CHANGED
@@ -492,7 +492,7 @@ class WsClient extends EventEmitter {
492
492
  }
493
493
 
494
494
  _consumeHandshake(chunk) {
495
- // allow:handrolled-buffer-collect — handshake header capped at 64 KiB below; once handshake parses we switch to FrameParser
495
+ // allow:handrolled-buffer-collect-bounded-framing — handshake header capped at 64 KiB below; once handshake parses we switch to FrameParser
496
496
  this._handshakeBuf = Buffer.concat([this._handshakeBuf, chunk]);
497
497
  var headerEnd = this._handshakeBuf.indexOf("\r\n\r\n");
498
498
  if (headerEnd === -1) {
@@ -737,7 +737,7 @@ class WsClient extends EventEmitter {
737
737
  return;
738
738
  }
739
739
  if (frame.fin) {
740
- var fullPayload = Buffer.concat(this._fragmentChunks); // allow:handrolled-buffer-collect — bounded by maxMessageBytes below
740
+ var fullPayload = Buffer.concat(this._fragmentChunks); // allow:handrolled-buffer-collect-bounded-framing — bounded by maxMessageBytes below
741
741
  if (safeBuffer.byteLengthOf(fullPayload) > this._opts.maxMessageBytes) {
742
742
  this._handleSocketError(new WsClientError("ws-client/message-too-big",
743
743
  "incoming message exceeds maxMessageBytes (" + this._opts.maxMessageBytes + ")"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.15.30",
3
+ "version": "0.15.32",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
package/sbom.cdx.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.5",
5
- "serialNumber": "urn:uuid:4fb829b1-aa27-4095-8449-786674226709",
5
+ "serialNumber": "urn:uuid:c545cdae-c805-48ed-bc85-5ab5c993961a",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-06-26T11:54:05.342Z",
8
+ "timestamp": "2026-06-26T20:40:06.256Z",
9
9
  "lifecycles": [
10
10
  {
11
11
  "phase": "build"
@@ -19,14 +19,14 @@
19
19
  }
20
20
  ],
21
21
  "component": {
22
- "bom-ref": "@blamejs/core@0.15.30",
22
+ "bom-ref": "@blamejs/core@0.15.32",
23
23
  "type": "application",
24
24
  "name": "blamejs",
25
- "version": "0.15.30",
25
+ "version": "0.15.32",
26
26
  "scope": "required",
27
27
  "author": "blamejs contributors",
28
28
  "description": "The Node framework that owns its stack.",
29
- "purl": "pkg:npm/%40blamejs/core@0.15.30",
29
+ "purl": "pkg:npm/%40blamejs/core@0.15.32",
30
30
  "properties": [],
31
31
  "externalReferences": [
32
32
  {
@@ -54,7 +54,7 @@
54
54
  "components": [],
55
55
  "dependencies": [
56
56
  {
57
- "ref": "@blamejs/core@0.15.30",
57
+ "ref": "@blamejs/core@0.15.32",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]