@blamejs/core 0.7.99 → 0.7.100
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 +2 -0
- package/lib/network-tls.js +78 -0
- package/package.json +1 -1
- package/sbom.cyclonedx.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,8 @@ upgrading across more than a few patches at a time.
|
|
|
8
8
|
|
|
9
9
|
## v0.7.x
|
|
10
10
|
|
|
11
|
+
- **0.7.100** (2026-05-06) — `b.network.tls.expiryMonitor({ intervalMs, windowMs, onExpiring })` — periodic CA-trust-store expiry monitor. Runs `expiringSoon(windowMs)` on a schedule; emits `network.tls.ca.expiry_check` audit event on every check (with `expiring` count + `total` CA count), `network.tls.ca.expiring` audit event when any CA falls inside the window, and the matching `network.tls.ca.expiring` observability counter. Optional `onExpiring(rows)` operator hook fires on every check that surfaces expiring CAs so operators can wire pager / Slack alerts. Audit metadata captures the expiring CA labels + the earliest `validTo` timestamp so dashboards can compute "days until first expiry" without re-querying. Returns a handle with `.stop()` for graceful shutdown. Closes the v0.7.26 OCSP/CT batch's continuous-trust-monitoring follow-up.
|
|
12
|
+
|
|
11
13
|
- **0.7.99** (2026-05-06) — `b.db.integrityCheck()` + `b.db.integrityMonitor({ intervalMs, ... })` — periodic SQLite corruption detection. **`b.db.integrityCheck()`** runs `PRAGMA integrity_check` against the live database and returns `"ok"` on a healthy database, or an array of corruption description strings on damage. Operators wire this into `/healthz` handlers or one-off CLI checks. **`b.db.integrityMonitor({ intervalMs, onCorruption })`** runs the check on a schedule (24h default), emits `system.db.integrity_ok` / `system.db.integrity_corrupt` audit events, and fires the `db.integrity_check_ok` / `db.integrity_check_corrupt` observability counters. Optional `onCorruption(issues)` operator hook fires on every corrupt-result so operators can wire pager alerts. The previous boot-time-only integrity check (added in v0.7.79) continues to run unchanged at db.init; the monitor is for long-running deployments where filesystem-level corruption can develop after boot. Returns a handle with `.stop()` for graceful shutdown.
|
|
12
14
|
|
|
13
15
|
- **0.7.98** (2026-05-06) — `b.ntpCheck.monitor({ intervalMs, ... })` — periodic clock-drift monitor that runs `checkDrift` on a schedule and emits audit + observability events on threshold crossings. Returns a handle with `.stop()` for graceful shutdown. Audit emissions: `system.ntp.checked` (every check), `system.ntp.drift_warn` (drift exceeds warn threshold), `system.ntp.drift_fatal` (drift exceeds fatal threshold), `system.ntp.unreachable` (every server in the list failed to respond). Observability event: `ntp.drift_ms` gauge on every successful check, labeled with the responding server. Optional `onDrift(result)` operator hook fires on every warning/fatal check so operators can wire pager / Slack notifications. The previous boot-time-only `b.ntpCheck.bootCheck` continues to run unchanged at db.init; the monitor is for long-running deployments where clock-drift can develop after boot (container with no RTC sync, ntpd stopped after boot, etc.). Closes the v0.7.79 audit-batch slice for continuous time integrity.
|
package/lib/network-tls.js
CHANGED
|
@@ -9,6 +9,7 @@ var C = require("./constants");
|
|
|
9
9
|
var safeBuffer = require("./safe-buffer");
|
|
10
10
|
var validateOpts = require("./validate-opts");
|
|
11
11
|
var lazyRequire = require("./lazy-require");
|
|
12
|
+
var safeAsync = require("./safe-async");
|
|
12
13
|
var { defineClass } = require("./framework-error");
|
|
13
14
|
|
|
14
15
|
var TlsTrustError = defineClass("TlsTrustError", { alwaysPermanent: true });
|
|
@@ -248,6 +249,82 @@ function expiringSoon(windowMs) {
|
|
|
248
249
|
});
|
|
249
250
|
}
|
|
250
251
|
|
|
252
|
+
// expiryMonitor — periodic check that emits audit + observability
|
|
253
|
+
// events when any CA in the trust store falls inside the expiry
|
|
254
|
+
// window. Returns a handle with .stop() for graceful shutdown.
|
|
255
|
+
//
|
|
256
|
+
// var mon = b.network.tls.expiryMonitor({
|
|
257
|
+
// intervalMs: C.TIME.hours(6),
|
|
258
|
+
// windowMs: C.TIME.days(30),
|
|
259
|
+
// onExpiring: function (rows) { /* operator hook — alerts */ },
|
|
260
|
+
// });
|
|
261
|
+
// ...
|
|
262
|
+
// mon.stop();
|
|
263
|
+
//
|
|
264
|
+
// Audit emissions:
|
|
265
|
+
// network.tls.ca.expiry_check — every check, reports total + expiring count
|
|
266
|
+
// network.tls.ca.expiring — when expiringSoon(windowMs) > 0
|
|
267
|
+
//
|
|
268
|
+
// Observability event: network.tls.ca.expiring counter labeled with
|
|
269
|
+
// the count.
|
|
270
|
+
function expiryMonitor(opts) {
|
|
271
|
+
opts = opts || {};
|
|
272
|
+
var intervalMs = opts.intervalMs;
|
|
273
|
+
var windowMs = opts.windowMs;
|
|
274
|
+
var auditOn = opts.audit !== false;
|
|
275
|
+
if (typeof intervalMs !== "number" || !isFinite(intervalMs) || intervalMs <= 0) {
|
|
276
|
+
throw new TlsTrustError("tls/bad-interval",
|
|
277
|
+
"tls.expiryMonitor: intervalMs must be a positive finite number");
|
|
278
|
+
}
|
|
279
|
+
if (typeof windowMs !== "number" || !isFinite(windowMs) || windowMs <= 0) {
|
|
280
|
+
throw new TlsTrustError("tls/bad-window",
|
|
281
|
+
"tls.expiryMonitor: windowMs must be a positive finite number");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function _tick() {
|
|
285
|
+
var rows;
|
|
286
|
+
try { rows = expiringSoon(windowMs); }
|
|
287
|
+
catch (_e) { return; }
|
|
288
|
+
if (auditOn) {
|
|
289
|
+
try {
|
|
290
|
+
audit().safeEmit({
|
|
291
|
+
action: "network.tls.ca.expiry_check",
|
|
292
|
+
outcome: rows.length > 0 ? "warn" : "ok",
|
|
293
|
+
metadata: { total: STATE.cas.length, expiring: rows.length, windowMs: windowMs },
|
|
294
|
+
});
|
|
295
|
+
} catch (_e) { /* drop-silent */ }
|
|
296
|
+
}
|
|
297
|
+
if (rows.length > 0) {
|
|
298
|
+
try { observability().safeEvent("network.tls.ca.expiring", rows.length, {}); }
|
|
299
|
+
catch (_e) { /* drop-silent */ }
|
|
300
|
+
if (auditOn) {
|
|
301
|
+
try {
|
|
302
|
+
audit().safeEmit({
|
|
303
|
+
action: "network.tls.ca.expiring",
|
|
304
|
+
outcome: "warn",
|
|
305
|
+
metadata: {
|
|
306
|
+
count: rows.length,
|
|
307
|
+
labels: rows.map(function (r) { return r.label; }),
|
|
308
|
+
earliestValidTo: rows.reduce(function (acc, r) {
|
|
309
|
+
var ms = r.validTo ? Date.parse(r.validTo) : Infinity;
|
|
310
|
+
return ms < acc ? ms : acc;
|
|
311
|
+
}, Infinity),
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
} catch (_e) { /* drop-silent */ }
|
|
315
|
+
}
|
|
316
|
+
if (typeof opts.onExpiring === "function") {
|
|
317
|
+
try { opts.onExpiring(rows); } catch (_e) { /* operator hook */ }
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
var handle = safeAsync.repeating(_tick, intervalMs, { name: "tls-expiry-monitor" });
|
|
323
|
+
return {
|
|
324
|
+
stop: function () { if (handle) { handle.stop(); handle = null; } },
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
251
328
|
function captureBaselineFingerprints() {
|
|
252
329
|
STATE.baselineFingerprints = STATE.cas.map(function (e) { return e.meta.fingerprint256; });
|
|
253
330
|
}
|
|
@@ -1557,6 +1634,7 @@ module.exports = {
|
|
|
1557
1634
|
clearAll: clearAll,
|
|
1558
1635
|
purgeExpired: purgeExpired,
|
|
1559
1636
|
expiringSoon: expiringSoon,
|
|
1637
|
+
expiryMonitor: expiryMonitor,
|
|
1560
1638
|
useSystemTrust: useSystemTrust,
|
|
1561
1639
|
isSystemTrustEnabled: isSystemTrustEnabled,
|
|
1562
1640
|
getTrustStore: getTrustStore,
|
package/package.json
CHANGED
package/sbom.cyclonedx.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:
|
|
5
|
+
"serialNumber": "urn:uuid:41d841af-2890-4424-89ab-7b411b784c39",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-05-06T09:
|
|
8
|
+
"timestamp": "2026-05-06T09:26:08.410Z",
|
|
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.7.
|
|
22
|
+
"bom-ref": "@blamejs/core@0.7.100",
|
|
23
23
|
"type": "library",
|
|
24
24
|
"name": "blamejs",
|
|
25
|
-
"version": "0.7.
|
|
25
|
+
"version": "0.7.100",
|
|
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.7.
|
|
29
|
+
"purl": "pkg:npm/%40blamejs/core@0.7.100",
|
|
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.7.
|
|
57
|
+
"ref": "@blamejs/core@0.7.100",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|