@blamejs/core 0.8.43 → 0.8.49
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 +92 -0
- package/README.md +10 -10
- package/index.js +52 -0
- package/lib/a2a.js +159 -34
- package/lib/acme.js +762 -0
- package/lib/ai-pref.js +166 -43
- package/lib/api-key.js +108 -47
- package/lib/api-snapshot.js +157 -40
- package/lib/app-shutdown.js +113 -77
- package/lib/archive.js +337 -40
- package/lib/arg-parser.js +697 -0
- package/lib/asyncapi.js +99 -55
- package/lib/atomic-file.js +465 -104
- package/lib/audit-chain.js +123 -34
- package/lib/audit-daily-review.js +389 -0
- package/lib/audit-sign.js +302 -56
- package/lib/audit-tools.js +412 -63
- package/lib/audit.js +656 -35
- package/lib/auth/jwt-external.js +17 -0
- package/lib/auth/oauth.js +7 -0
- package/lib/auth-bot-challenge.js +505 -0
- package/lib/auth-header.js +92 -25
- package/lib/backup/bundle.js +26 -0
- package/lib/backup/index.js +512 -89
- package/lib/backup/manifest.js +168 -7
- package/lib/break-glass.js +415 -39
- package/lib/budr.js +103 -30
- package/lib/bundler.js +86 -66
- package/lib/cache.js +192 -72
- package/lib/chain-writer.js +65 -40
- package/lib/circuit-breaker.js +56 -33
- package/lib/cli-helpers.js +106 -75
- package/lib/cli.js +6 -30
- package/lib/cloud-events.js +99 -32
- package/lib/cluster-storage.js +162 -37
- package/lib/cluster.js +340 -49
- package/lib/codepoint-class.js +66 -0
- package/lib/compliance.js +424 -24
- package/lib/config-drift.js +111 -46
- package/lib/config.js +94 -40
- package/lib/consent.js +165 -18
- package/lib/constants.js +1 -0
- package/lib/content-credentials.js +153 -48
- package/lib/cookies.js +154 -62
- package/lib/credential-hash.js +133 -61
- package/lib/crypto-field.js +702 -18
- package/lib/crypto-hpke.js +256 -0
- package/lib/crypto.js +744 -22
- package/lib/csv.js +178 -35
- package/lib/daemon.js +456 -0
- package/lib/dark-patterns.js +186 -55
- package/lib/db-query.js +79 -2
- package/lib/db.js +1431 -60
- package/lib/ddl-change-control.js +523 -0
- package/lib/deprecate.js +195 -40
- package/lib/dev.js +82 -39
- package/lib/dora.js +67 -48
- package/lib/dr-runbook.js +368 -0
- package/lib/dsr.js +142 -11
- package/lib/dual-control.js +91 -56
- package/lib/events.js +120 -41
- package/lib/external-db-migrate.js +192 -2
- package/lib/external-db.js +795 -50
- package/lib/fapi2.js +122 -1
- package/lib/fda-21cfr11.js +395 -0
- package/lib/fdx.js +132 -2
- package/lib/file-type.js +87 -0
- package/lib/file-upload.js +93 -0
- package/lib/flag.js +82 -20
- package/lib/forms.js +132 -29
- package/lib/framework-error.js +169 -0
- package/lib/framework-schema.js +163 -35
- package/lib/gate-contract.js +849 -175
- package/lib/graphql-federation.js +68 -7
- package/lib/guard-all.js +172 -55
- package/lib/guard-archive.js +286 -124
- package/lib/guard-auth.js +194 -21
- package/lib/guard-cidr.js +190 -28
- package/lib/guard-csv.js +397 -51
- package/lib/guard-domain.js +213 -91
- package/lib/guard-email.js +236 -29
- package/lib/guard-filename.js +307 -75
- package/lib/guard-graphql.js +263 -30
- package/lib/guard-html.js +310 -116
- package/lib/guard-image.js +243 -30
- package/lib/guard-json.js +260 -54
- package/lib/guard-jsonpath.js +235 -23
- package/lib/guard-jwt.js +284 -30
- package/lib/guard-markdown.js +204 -22
- package/lib/guard-mime.js +190 -26
- package/lib/guard-oauth.js +277 -28
- package/lib/guard-pdf.js +251 -27
- package/lib/guard-regex.js +226 -18
- package/lib/guard-shell.js +229 -26
- package/lib/guard-svg.js +177 -10
- package/lib/guard-template.js +232 -21
- package/lib/guard-time.js +195 -29
- package/lib/guard-uuid.js +189 -30
- package/lib/guard-xml.js +259 -36
- package/lib/guard-yaml.js +241 -44
- package/lib/honeytoken.js +63 -27
- package/lib/html-balance.js +83 -0
- package/lib/http-client.js +486 -59
- package/lib/http-message-signature.js +582 -0
- package/lib/i18n.js +102 -49
- package/lib/iab-mspa.js +112 -32
- package/lib/iab-tcf.js +107 -2
- package/lib/inbox.js +90 -52
- package/lib/keychain.js +865 -0
- package/lib/legal-hold.js +374 -0
- package/lib/local-db-thin.js +320 -0
- package/lib/log-stream.js +281 -51
- package/lib/log.js +184 -86
- package/lib/mail-bounce.js +107 -62
- package/lib/mail.js +295 -58
- package/lib/mcp.js +108 -27
- package/lib/metrics.js +98 -89
- package/lib/middleware/age-gate.js +36 -0
- package/lib/middleware/ai-act-disclosure.js +37 -0
- package/lib/middleware/api-encrypt.js +45 -0
- package/lib/middleware/assetlinks.js +40 -0
- package/lib/middleware/asyncapi-serve.js +35 -0
- package/lib/middleware/attach-user.js +40 -0
- package/lib/middleware/bearer-auth.js +40 -0
- package/lib/middleware/body-parser.js +230 -0
- package/lib/middleware/bot-disclose.js +34 -0
- package/lib/middleware/bot-guard.js +39 -0
- package/lib/middleware/compression.js +37 -0
- package/lib/middleware/cookies.js +32 -0
- package/lib/middleware/cors.js +40 -0
- package/lib/middleware/csp-nonce.js +40 -0
- package/lib/middleware/csp-report.js +34 -0
- package/lib/middleware/csrf-protect.js +43 -0
- package/lib/middleware/daily-byte-quota.js +53 -85
- package/lib/middleware/db-role-for.js +40 -0
- package/lib/middleware/dpop.js +40 -0
- package/lib/middleware/error-handler.js +37 -14
- package/lib/middleware/fetch-metadata.js +39 -0
- package/lib/middleware/flag-context.js +34 -0
- package/lib/middleware/gpc.js +33 -0
- package/lib/middleware/headers.js +35 -0
- package/lib/middleware/health.js +46 -0
- package/lib/middleware/host-allowlist.js +30 -0
- package/lib/middleware/network-allowlist.js +38 -0
- package/lib/middleware/openapi-serve.js +34 -0
- package/lib/middleware/rate-limit.js +160 -18
- package/lib/middleware/request-id.js +36 -18
- package/lib/middleware/request-log.js +37 -0
- package/lib/middleware/require-aal.js +29 -0
- package/lib/middleware/require-auth.js +32 -0
- package/lib/middleware/require-bound-key.js +41 -0
- package/lib/middleware/require-content-type.js +32 -0
- package/lib/middleware/require-methods.js +27 -0
- package/lib/middleware/require-mtls.js +33 -0
- package/lib/middleware/require-step-up.js +37 -0
- package/lib/middleware/security-headers.js +44 -0
- package/lib/middleware/security-txt.js +38 -0
- package/lib/middleware/span-http-server.js +37 -0
- package/lib/middleware/sse.js +36 -0
- package/lib/middleware/trace-log-correlation.js +33 -0
- package/lib/middleware/trace-propagate.js +32 -0
- package/lib/middleware/tus-upload.js +90 -0
- package/lib/middleware/web-app-manifest.js +53 -0
- package/lib/mtls-ca.js +100 -70
- package/lib/network-byte-quota.js +308 -0
- package/lib/network-heartbeat.js +135 -0
- package/lib/network-tls.js +534 -4
- package/lib/network.js +103 -0
- package/lib/notify.js +114 -43
- package/lib/ntp-check.js +192 -51
- package/lib/observability.js +145 -47
- package/lib/openapi.js +90 -44
- package/lib/outbox.js +99 -1
- package/lib/pagination.js +168 -86
- package/lib/parsers/index.js +16 -5
- package/lib/permissions.js +93 -40
- package/lib/pqc-agent.js +84 -8
- package/lib/pqc-software.js +94 -60
- package/lib/process-spawn.js +95 -21
- package/lib/pubsub.js +96 -66
- package/lib/queue.js +375 -54
- package/lib/redact.js +793 -21
- package/lib/render.js +139 -47
- package/lib/request-helpers.js +485 -121
- package/lib/restore-bundle.js +142 -39
- package/lib/restore-rollback.js +136 -45
- package/lib/retention.js +178 -50
- package/lib/retry.js +116 -33
- package/lib/router.js +475 -23
- package/lib/safe-async.js +543 -94
- package/lib/safe-buffer.js +337 -41
- package/lib/safe-json.js +467 -62
- package/lib/safe-jsonpath.js +285 -0
- package/lib/safe-schema.js +631 -87
- package/lib/safe-sql.js +221 -59
- package/lib/safe-url.js +278 -46
- package/lib/sandbox-worker.js +135 -0
- package/lib/sandbox.js +358 -0
- package/lib/scheduler.js +135 -70
- package/lib/self-update.js +647 -0
- package/lib/session-device-binding.js +431 -0
- package/lib/session.js +259 -49
- package/lib/slug.js +138 -26
- package/lib/ssrf-guard.js +316 -56
- package/lib/storage.js +433 -70
- package/lib/subject.js +405 -23
- package/lib/template.js +148 -8
- package/lib/tenant-quota.js +545 -0
- package/lib/testing.js +440 -53
- package/lib/time.js +291 -23
- package/lib/tls-exporter.js +239 -0
- package/lib/tracing.js +90 -74
- package/lib/uuid.js +97 -22
- package/lib/vault/index.js +284 -22
- package/lib/vault/seal-pem-file.js +66 -0
- package/lib/watcher.js +368 -0
- package/lib/webhook.js +196 -63
- package/lib/websocket.js +393 -68
- package/lib/wiki-concepts.js +338 -0
- package/lib/worker-pool.js +464 -0
- package/package.json +3 -3
- package/sbom.cyclonedx.json +7 -7
package/lib/backup/manifest.js
CHANGED
|
@@ -69,10 +69,16 @@
|
|
|
69
69
|
*/
|
|
70
70
|
|
|
71
71
|
var C = require("../constants");
|
|
72
|
+
var lazyRequire = require("../lazy-require");
|
|
72
73
|
var safeBuffer = require("../safe-buffer");
|
|
73
74
|
var safeJson = require("../safe-json");
|
|
74
75
|
var { FrameworkError } = require("../framework-error");
|
|
75
76
|
|
|
77
|
+
// audit-sign is loaded lazily — manifest.js is consumed by both the
|
|
78
|
+
// backup writer (which has audit-sign initialized) and read-only
|
|
79
|
+
// inspectors (CLI / verifier) where audit-sign may not be wired.
|
|
80
|
+
var auditSign = lazyRequire(function () { return require("../audit-sign"); });
|
|
81
|
+
|
|
76
82
|
class BackupManifestError extends FrameworkError {
|
|
77
83
|
constructor(code, message) {
|
|
78
84
|
super(message, code);
|
|
@@ -189,6 +195,31 @@ function validate(manifest) {
|
|
|
189
195
|
(manifest.metadata === null || typeof manifest.metadata !== "object" || Array.isArray(manifest.metadata))) {
|
|
190
196
|
errors.push("metadata: must be a plain object when present");
|
|
191
197
|
}
|
|
198
|
+
// Optional signature block. When present, every sub-field is
|
|
199
|
+
// required — partial signatures are a smell (operators saw an
|
|
200
|
+
// unsigned bundle and tried to hand-edit a signature in).
|
|
201
|
+
if (manifest.signature !== undefined) {
|
|
202
|
+
if (manifest.signature === null || typeof manifest.signature !== "object" ||
|
|
203
|
+
Array.isArray(manifest.signature)) {
|
|
204
|
+
errors.push("signature: must be a plain object when present");
|
|
205
|
+
} else {
|
|
206
|
+
if (typeof manifest.signature.algorithm !== "string" || manifest.signature.algorithm.length === 0) {
|
|
207
|
+
errors.push("signature.algorithm: required non-empty string");
|
|
208
|
+
}
|
|
209
|
+
if (typeof manifest.signature.publicKey !== "string" || manifest.signature.publicKey.length === 0) {
|
|
210
|
+
errors.push("signature.publicKey: required non-empty string");
|
|
211
|
+
}
|
|
212
|
+
if (typeof manifest.signature.fingerprint !== "string" || manifest.signature.fingerprint.length === 0) {
|
|
213
|
+
errors.push("signature.fingerprint: required non-empty string");
|
|
214
|
+
}
|
|
215
|
+
if (!_isBase64(manifest.signature.value)) {
|
|
216
|
+
errors.push("signature.value: required base64 string");
|
|
217
|
+
}
|
|
218
|
+
if (!_isIso8601(manifest.signature.signedAt)) {
|
|
219
|
+
errors.push("signature.signedAt: required ISO-8601 timestamp string");
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
192
223
|
return { ok: errors.length === 0, errors: errors };
|
|
193
224
|
}
|
|
194
225
|
|
|
@@ -216,12 +247,7 @@ function create(opts) {
|
|
|
216
247
|
return manifest;
|
|
217
248
|
}
|
|
218
249
|
|
|
219
|
-
function
|
|
220
|
-
var v = validate(manifest);
|
|
221
|
-
if (!v.ok) {
|
|
222
|
-
throw new BackupManifestError("backup-manifest/invalid",
|
|
223
|
-
"serialize: " + v.errors.join("; "));
|
|
224
|
-
}
|
|
250
|
+
function _canonical(manifest, includeSignature) {
|
|
225
251
|
// Stable key ordering so the same manifest object always serializes
|
|
226
252
|
// to the same bytes (operators can hash the manifest as part of
|
|
227
253
|
// bundle-integrity logging without surprises across runs).
|
|
@@ -245,7 +271,139 @@ function serialize(manifest) {
|
|
|
245
271
|
}),
|
|
246
272
|
};
|
|
247
273
|
if (manifest.metadata) canonical.metadata = manifest.metadata;
|
|
248
|
-
|
|
274
|
+
// Signature block lives alongside the rest of the manifest fields
|
|
275
|
+
// and is itself stable-ordered. Sign-time canonicalization (the
|
|
276
|
+
// bytes the audit-sign keypair signs) excludes the signature field
|
|
277
|
+
// so the signature can be appended without altering the signed
|
|
278
|
+
// payload.
|
|
279
|
+
if (includeSignature && manifest.signature) {
|
|
280
|
+
canonical.signature = {
|
|
281
|
+
algorithm: manifest.signature.algorithm,
|
|
282
|
+
publicKey: manifest.signature.publicKey,
|
|
283
|
+
fingerprint: manifest.signature.fingerprint,
|
|
284
|
+
value: manifest.signature.value,
|
|
285
|
+
signedAt: manifest.signature.signedAt,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
return canonical;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// The canonical payload the audit-sign keypair signs over — the
|
|
292
|
+
// manifest serialized without its `signature` field. Exposed so
|
|
293
|
+
// verifiers can recompute the exact bytes that produced the signature.
|
|
294
|
+
function signingPayload(manifest) {
|
|
295
|
+
return JSON.stringify(_canonical(manifest, false), null, 2) + "\n";
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function serialize(manifest) {
|
|
299
|
+
var v = validate(manifest);
|
|
300
|
+
if (!v.ok) {
|
|
301
|
+
throw new BackupManifestError("backup-manifest/invalid",
|
|
302
|
+
"serialize: " + v.errors.join("; "));
|
|
303
|
+
}
|
|
304
|
+
return JSON.stringify(_canonical(manifest, true), null, 2) + "\n";
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Sign the manifest in-place via the audit-sign keypair (ML-DSA-87
|
|
308
|
+
// or SLH-DSA-SHAKE-256f — whichever audit-sign was initialized with).
|
|
309
|
+
// The signature covers the manifest's canonical bytes WITHOUT the
|
|
310
|
+
// signature field; appending it does not change the signed payload.
|
|
311
|
+
function sign(manifest) {
|
|
312
|
+
var v = validate(manifest);
|
|
313
|
+
if (!v.ok) {
|
|
314
|
+
throw new BackupManifestError("backup-manifest/invalid",
|
|
315
|
+
"sign: " + v.errors.join("; "));
|
|
316
|
+
}
|
|
317
|
+
var signer = auditSign();
|
|
318
|
+
if (!signer || typeof signer.sign !== "function") {
|
|
319
|
+
throw new BackupManifestError("backup-manifest/no-signer",
|
|
320
|
+
"sign: audit-sign module is not available; call b.auditSign.init() first");
|
|
321
|
+
}
|
|
322
|
+
var payload = signingPayload(manifest);
|
|
323
|
+
var signatureBytes;
|
|
324
|
+
try { signatureBytes = signer.sign(payload); }
|
|
325
|
+
catch (e) {
|
|
326
|
+
throw new BackupManifestError("backup-manifest/sign-failed",
|
|
327
|
+
"sign: audit-sign.sign threw: " + ((e && e.message) || String(e)));
|
|
328
|
+
}
|
|
329
|
+
manifest.signature = {
|
|
330
|
+
algorithm: signer.getAlgorithm(),
|
|
331
|
+
publicKey: signer.getPublicKey(),
|
|
332
|
+
fingerprint: signer.getPublicKeyFingerprint(),
|
|
333
|
+
value: signatureBytes.toString("base64"),
|
|
334
|
+
signedAt: new Date().toISOString(),
|
|
335
|
+
};
|
|
336
|
+
return manifest;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Verify a previously-signed manifest. Returns { ok, reason?,
|
|
340
|
+
// fingerprint? }. Caller policy decides whether a missing or
|
|
341
|
+
// fingerprint-mismatched signature is fatal — verifyManifestSignature
|
|
342
|
+
// in lib/backup/index.js wraps this with operator-facing semantics.
|
|
343
|
+
function verifySignature(manifest, opts) {
|
|
344
|
+
opts = opts || {};
|
|
345
|
+
if (!manifest || typeof manifest !== "object") {
|
|
346
|
+
return { ok: false, reason: "manifest must be an object" };
|
|
347
|
+
}
|
|
348
|
+
if (!manifest.signature || typeof manifest.signature !== "object") {
|
|
349
|
+
return { ok: false, reason: "manifest has no signature block" };
|
|
350
|
+
}
|
|
351
|
+
var sig = manifest.signature;
|
|
352
|
+
if (typeof sig.algorithm !== "string" || sig.algorithm.length === 0) {
|
|
353
|
+
return { ok: false, reason: "signature.algorithm is required" };
|
|
354
|
+
}
|
|
355
|
+
if (typeof sig.publicKey !== "string" || sig.publicKey.length === 0) {
|
|
356
|
+
return { ok: false, reason: "signature.publicKey is required" };
|
|
357
|
+
}
|
|
358
|
+
if (typeof sig.value !== "string" || sig.value.length === 0) {
|
|
359
|
+
return { ok: false, reason: "signature.value is required" };
|
|
360
|
+
}
|
|
361
|
+
// Caller may pin the expected fingerprint — operators tracking key
|
|
362
|
+
// rotation pass the active audit-sign fingerprint and refuse any
|
|
363
|
+
// bundle signed under a different historical key.
|
|
364
|
+
if (typeof opts.expectedFingerprint === "string" &&
|
|
365
|
+
opts.expectedFingerprint.length > 0 &&
|
|
366
|
+
sig.fingerprint !== opts.expectedFingerprint) {
|
|
367
|
+
return {
|
|
368
|
+
ok: false,
|
|
369
|
+
reason: "signature.fingerprint=" + sig.fingerprint +
|
|
370
|
+
" does not match expectedFingerprint=" + opts.expectedFingerprint,
|
|
371
|
+
fingerprint: sig.fingerprint,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
var payload = signingPayload(manifest);
|
|
375
|
+
var sigBuf;
|
|
376
|
+
try { sigBuf = Buffer.from(sig.value, "base64"); }
|
|
377
|
+
catch (_e) {
|
|
378
|
+
return { ok: false, reason: "signature.value is not valid base64" };
|
|
379
|
+
}
|
|
380
|
+
// Use audit-sign.verify when available (handles algorithm dispatch
|
|
381
|
+
// identically to the signer); fall back to nodeCrypto.verify for
|
|
382
|
+
// verifier processes that don't init audit-sign.
|
|
383
|
+
var ok;
|
|
384
|
+
try {
|
|
385
|
+
var signer = auditSign();
|
|
386
|
+
if (signer && typeof signer.verify === "function") {
|
|
387
|
+
ok = signer.verify(payload, sigBuf, sig.publicKey);
|
|
388
|
+
} else {
|
|
389
|
+
ok = require("node:crypto").verify(null,
|
|
390
|
+
Buffer.from(payload, "utf8"), sig.publicKey, sigBuf);
|
|
391
|
+
}
|
|
392
|
+
} catch (e) {
|
|
393
|
+
return {
|
|
394
|
+
ok: false,
|
|
395
|
+
reason: "verify threw: " + ((e && e.message) || String(e)),
|
|
396
|
+
fingerprint: sig.fingerprint,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
if (!ok) {
|
|
400
|
+
return {
|
|
401
|
+
ok: false,
|
|
402
|
+
reason: "signature did not verify under provided publicKey",
|
|
403
|
+
fingerprint: sig.fingerprint,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
return { ok: true, fingerprint: sig.fingerprint };
|
|
249
407
|
}
|
|
250
408
|
|
|
251
409
|
function parse(jsonStr) {
|
|
@@ -275,6 +433,9 @@ module.exports = {
|
|
|
275
433
|
validate: validate,
|
|
276
434
|
serialize: serialize,
|
|
277
435
|
parse: parse,
|
|
436
|
+
sign: sign,
|
|
437
|
+
signingPayload: signingPayload,
|
|
438
|
+
verifySignature: verifySignature,
|
|
278
439
|
FORMAT_VERSION: FORMAT_VERSION,
|
|
279
440
|
FRAMEWORK_NAME: FRAMEWORK_NAME,
|
|
280
441
|
VALID_KINDS: VALID_KINDS,
|