@blamejs/core 0.15.12 → 0.15.14
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 +4 -0
- package/index.js +2 -0
- package/lib/a2a-tasks.js +45 -29
- package/lib/acme.js +6 -5
- package/lib/agent-event-bus.js +18 -4
- package/lib/agent-idempotency.js +7 -6
- package/lib/agent-orchestrator.js +2 -5
- package/lib/agent-saga.js +3 -5
- package/lib/agent-snapshot.js +32 -2
- package/lib/agent-tenant.js +2 -5
- package/lib/ai-adverse-decision.js +2 -15
- package/lib/ai-aedt-bias-audit.js +2 -1
- package/lib/ai-capability.js +1 -6
- package/lib/ai-content-detect.js +1 -3
- package/lib/ai-dp.js +1 -5
- package/lib/ai-frontier-protocol.js +1 -1
- package/lib/ai-input.js +2 -2
- package/lib/ai-model-manifest.js +1 -1
- package/lib/ai-output.js +16 -7
- package/lib/ai-pref.js +3 -8
- package/lib/ai-quota.js +3 -14
- package/lib/api-key.js +37 -28
- package/lib/api-snapshot.js +4 -1
- package/lib/app-shutdown.js +7 -1
- package/lib/archive-adapters.js +2 -4
- package/lib/archive-entry-policy.js +32 -0
- package/lib/archive-gz.js +9 -0
- package/lib/archive-read.js +14 -24
- package/lib/archive-tar-read.js +56 -24
- package/lib/archive.js +6 -12
- package/lib/arg-parser.js +7 -6
- package/lib/asn1-der.js +70 -22
- package/lib/asyncapi-traits.js +2 -6
- package/lib/atomic-file.js +312 -33
- package/lib/audit-chain.js +183 -54
- package/lib/audit-daily-review.js +36 -16
- package/lib/audit-emit.js +82 -0
- package/lib/audit-sign.js +258 -0
- package/lib/audit-tools.js +108 -23
- package/lib/audit.js +91 -2
- package/lib/auth/access-lock.js +7 -29
- package/lib/auth/bot-challenge.js +1 -1
- package/lib/auth/ciba.js +43 -4
- package/lib/auth/dpop.js +29 -36
- package/lib/auth/fido-mds3.js +14 -16
- package/lib/auth/jwt-external.js +26 -8
- package/lib/auth/jwt.js +15 -17
- package/lib/auth/lockout.js +24 -27
- package/lib/auth/oauth.js +67 -45
- package/lib/auth/oid4vci.js +55 -32
- package/lib/auth/oid4vp.js +3 -2
- package/lib/auth/openid-federation.js +6 -6
- package/lib/auth/passkey.js +4 -4
- package/lib/auth/password.js +8 -2
- package/lib/auth/saml.js +70 -40
- package/lib/auth/sd-jwt-vc-holder.js +2 -14
- package/lib/auth/sd-jwt-vc-issuer.js +2 -14
- package/lib/auth/sd-jwt-vc.js +25 -5
- package/lib/auth/status-list.js +21 -9
- package/lib/auth/step-up.js +15 -13
- package/lib/auth-bot-challenge.js +27 -39
- package/lib/backup/bundle.js +18 -20
- package/lib/backup/crypto.js +23 -8
- package/lib/backup/index.js +55 -67
- package/lib/backup/manifest.js +7 -1
- package/lib/bounded-map.js +112 -1
- package/lib/breach-deadline.js +1 -11
- package/lib/break-glass.js +41 -22
- package/lib/cache.js +7 -18
- package/lib/cbor.js +36 -12
- package/lib/cdn-cache-control.js +15 -12
- package/lib/cert.js +8 -13
- package/lib/chain-writer.js +162 -47
- package/lib/cli.js +10 -2
- package/lib/client-hints.js +7 -9
- package/lib/cloud-events.js +43 -33
- package/lib/cluster-storage.js +9 -41
- package/lib/cms-codec.js +2 -1
- package/lib/codepoint-class.js +84 -1
- package/lib/compliance-ai-act-logging.js +1 -6
- package/lib/compliance-ai-act-transparency.js +2 -4
- package/lib/compliance-eaa.js +2 -12
- package/lib/compliance-sanctions-fetcher.js +21 -28
- package/lib/compliance-sanctions.js +11 -21
- package/lib/compliance.js +3 -10
- package/lib/config-drift.js +24 -20
- package/lib/content-credentials.js +11 -8
- package/lib/content-digest.js +21 -12
- package/lib/cookies.js +15 -13
- package/lib/cose.js +39 -11
- package/lib/cra-report.js +1 -11
- package/lib/crdt.js +2 -1
- package/lib/crypto-field.js +34 -33
- package/lib/crypto.js +138 -7
- package/lib/csp.js +239 -3
- package/lib/daemon.js +46 -42
- package/lib/data-act.js +46 -13
- package/lib/db-file-lifecycle.js +14 -6
- package/lib/db-query.js +75 -49
- package/lib/db.js +66 -27
- package/lib/dbsc.js +5 -6
- package/lib/ddl-change-control.js +18 -14
- package/lib/deprecate.js +4 -5
- package/lib/did.js +6 -2
- package/lib/dora.js +43 -13
- package/lib/dr-runbook.js +1 -1
- package/lib/dsa.js +2 -1
- package/lib/dsr.js +30 -20
- package/lib/early-hints.js +19 -0
- package/lib/eat.js +5 -1
- package/lib/external-db-migrate.js +21 -22
- package/lib/external-db.js +74 -30
- package/lib/fda-21cfr11.js +42 -13
- package/lib/fdx.js +22 -18
- package/lib/file-upload.js +80 -66
- package/lib/flag-evaluation-context.js +5 -8
- package/lib/flag-providers.js +6 -2
- package/lib/forms.js +1 -1
- package/lib/framework-error.js +12 -0
- package/lib/framework-schema.js +19 -0
- package/lib/fsm.js +7 -12
- package/lib/gate-contract.js +911 -39
- package/lib/gdpr-ropa.js +22 -22
- package/lib/graphql-federation.js +18 -5
- package/lib/guard-agent-registry.js +2 -1
- package/lib/guard-all.js +3 -2
- package/lib/guard-archive.js +9 -30
- package/lib/guard-auth.js +23 -80
- package/lib/guard-cidr.js +20 -96
- package/lib/guard-csv.js +135 -196
- package/lib/guard-domain.js +23 -106
- package/lib/guard-dsn.js +17 -14
- package/lib/guard-email.js +46 -53
- package/lib/guard-envelope.js +2 -2
- package/lib/guard-event-bus-topic.js +2 -1
- package/lib/guard-filename.js +12 -60
- package/lib/guard-graphql.js +28 -75
- package/lib/guard-html-wcag.js +15 -2
- package/lib/guard-html.js +74 -128
- package/lib/guard-idempotency-key.js +2 -1
- package/lib/guard-image.js +280 -77
- package/lib/guard-imap-command.js +9 -10
- package/lib/guard-jmap.js +1 -1
- package/lib/guard-json.js +101 -109
- package/lib/guard-jsonpath.js +20 -88
- package/lib/guard-jwt.js +32 -114
- package/lib/guard-list-id.js +2 -7
- package/lib/guard-list-unsubscribe.js +2 -7
- package/lib/guard-mail-compose.js +5 -6
- package/lib/guard-mail-move.js +3 -2
- package/lib/guard-mail-query.js +5 -3
- package/lib/guard-mail-sieve.js +6 -7
- package/lib/guard-managesieve-command.js +6 -5
- package/lib/guard-markdown.js +76 -110
- package/lib/guard-message-id.js +5 -6
- package/lib/guard-mime.js +20 -99
- package/lib/guard-oauth.js +19 -73
- package/lib/guard-pdf.js +65 -72
- package/lib/guard-pop3-command.js +13 -14
- package/lib/guard-posture-chain.js +2 -1
- package/lib/guard-regex.js +24 -99
- package/lib/guard-saga-config.js +2 -1
- package/lib/guard-shell.js +22 -87
- package/lib/guard-smtp-command.js +9 -12
- package/lib/guard-sql.js +15 -13
- package/lib/guard-stream-args.js +2 -1
- package/lib/guard-svg.js +103 -149
- package/lib/guard-template.js +23 -80
- package/lib/guard-tenant-id.js +2 -1
- package/lib/guard-text.js +592 -0
- package/lib/guard-time.js +27 -95
- package/lib/guard-uuid.js +21 -93
- package/lib/guard-xml.js +76 -106
- package/lib/guard-yaml.js +24 -60
- package/lib/html-balance.js +7 -3
- package/lib/http-client-cache.js +5 -12
- package/lib/http-client-cookie-jar.js +35 -16
- package/lib/http-client.js +233 -74
- package/lib/http-message-signature.js +3 -2
- package/lib/i18n-messageformat.js +5 -7
- package/lib/i18n.js +83 -26
- package/lib/iab-tcf.js +3 -2
- package/lib/importmap-integrity.js +41 -1
- package/lib/inbox.js +8 -8
- package/lib/incident-report.js +12 -27
- package/lib/ip-utils.js +49 -6
- package/lib/jobs.js +3 -2
- package/lib/json-patch.js +1 -1
- package/lib/json-path.js +24 -3
- package/lib/jtd.js +2 -2
- package/lib/keychain.js +6 -18
- package/lib/legal-hold.js +30 -23
- package/lib/log-stream-cloudwatch.js +44 -112
- package/lib/log-stream-otlp-grpc.js +17 -14
- package/lib/log-stream-otlp.js +16 -80
- package/lib/log-stream-webhook.js +20 -92
- package/lib/log.js +2 -2
- package/lib/mail-agent.js +2 -2
- package/lib/mail-arc-sign.js +8 -3
- package/lib/mail-arf.js +4 -3
- package/lib/mail-auth.js +43 -69
- package/lib/mail-bimi.js +35 -55
- package/lib/mail-bounce.js +3 -3
- package/lib/mail-crypto-pgp.js +3 -2
- package/lib/mail-crypto-smime.js +71 -6
- package/lib/mail-dav.js +8 -35
- package/lib/mail-deploy.js +15 -14
- package/lib/mail-dkim.js +19 -38
- package/lib/mail-greylist.js +17 -30
- package/lib/mail-helo.js +4 -7
- package/lib/mail-journal.js +13 -9
- package/lib/mail-mdn.js +12 -7
- package/lib/mail-rbl.js +7 -12
- package/lib/mail-scan.js +5 -7
- package/lib/mail-send-deliver.js +33 -20
- package/lib/mail-server-imap.js +32 -87
- package/lib/mail-server-jmap.js +39 -52
- package/lib/mail-server-managesieve.js +29 -83
- package/lib/mail-server-mx.js +33 -74
- package/lib/mail-server-net.js +177 -0
- package/lib/mail-server-pop3.js +30 -83
- package/lib/mail-server-rate-limit.js +30 -6
- package/lib/mail-server-registry.js +1 -1
- package/lib/mail-server-submission.js +34 -73
- package/lib/mail-server-tls.js +98 -2
- package/lib/mail-spam-score.js +9 -12
- package/lib/mail-store-fts.js +1 -1
- package/lib/mail-store.js +3 -2
- package/lib/mail.js +28 -13
- package/lib/markup-escape.js +31 -0
- package/lib/markup-tokenizer.js +78 -0
- package/lib/mcp-tool-registry.js +26 -23
- package/lib/mcp.js +7 -5
- package/lib/mdoc.js +36 -14
- package/lib/metrics.js +46 -33
- package/lib/middleware/age-gate.js +3 -23
- package/lib/middleware/api-encrypt.js +13 -24
- package/lib/middleware/assetlinks.js +2 -7
- package/lib/middleware/bearer-auth.js +2 -1
- package/lib/middleware/body-parser.js +41 -52
- package/lib/middleware/bot-disclose.js +7 -10
- package/lib/middleware/bot-guard.js +28 -28
- package/lib/middleware/clear-site-data.js +5 -1
- package/lib/middleware/compression.js +9 -0
- package/lib/middleware/cors.js +32 -23
- package/lib/middleware/csrf-protect.js +73 -23
- package/lib/middleware/daily-byte-quota.js +12 -30
- package/lib/middleware/deny-response.js +19 -1
- package/lib/middleware/fetch-metadata.js +35 -4
- package/lib/middleware/idempotency-key.js +4 -20
- package/lib/middleware/network-allowlist.js +61 -30
- package/lib/middleware/rate-limit.js +45 -44
- package/lib/middleware/scim-server.js +5 -3
- package/lib/middleware/security-headers.js +33 -7
- package/lib/middleware/security-txt.js +2 -6
- package/lib/middleware/speculation-rules.js +6 -3
- package/lib/middleware/tus-upload.js +14 -29
- package/lib/middleware/web-app-manifest.js +2 -7
- package/lib/migrations.js +4 -13
- package/lib/mime-parse.js +34 -17
- package/lib/module-loader.js +44 -0
- package/lib/money.js +105 -0
- package/lib/mtls-ca.js +125 -41
- package/lib/network-byte-quota.js +4 -18
- package/lib/network-dane.js +8 -6
- package/lib/network-dns-resolver.js +98 -7
- package/lib/network-dns.js +9 -2
- package/lib/network-dnssec.js +18 -17
- package/lib/network-heartbeat.js +3 -2
- package/lib/network-smtp-policy.js +52 -46
- package/lib/network-tls.js +67 -47
- package/lib/network-tsig.js +2 -2
- package/lib/nis2-report.js +2 -12
- package/lib/nist-crosswalk.js +1 -1
- package/lib/nonce-store.js +81 -3
- package/lib/ntp-check.js +28 -0
- package/lib/numeric-bounds.js +31 -8
- package/lib/object-store/azure-blob-bucket-ops.js +2 -6
- package/lib/object-store/azure-blob.js +6 -47
- package/lib/object-store/gcs-bucket-ops.js +4 -2
- package/lib/object-store/gcs.js +14 -75
- package/lib/object-store/http-put.js +2 -7
- package/lib/object-store/http-request.js +157 -0
- package/lib/object-store/local.js +37 -17
- package/lib/object-store/sigv4-bucket-ops.js +2 -1
- package/lib/object-store/sigv4.js +10 -79
- package/lib/observability-otlp-exporter.js +29 -29
- package/lib/observability.js +95 -0
- package/lib/openapi-paths-builder.js +7 -3
- package/lib/otel-export.js +7 -10
- package/lib/outbox.js +54 -41
- package/lib/pagination.js +11 -15
- package/lib/parsers/safe-env.js +5 -4
- package/lib/parsers/safe-ini.js +10 -4
- package/lib/parsers/safe-toml.js +11 -9
- package/lib/parsers/safe-xml.js +3 -3
- package/lib/parsers/safe-yaml.js +28 -9
- package/lib/pick.js +63 -5
- package/lib/pipl-cn.js +69 -59
- package/lib/privacy-pass.js +8 -6
- package/lib/problem-details.js +2 -5
- package/lib/pubsub.js +4 -8
- package/lib/queue-local.js +10 -3
- package/lib/redact.js +9 -4
- package/lib/render.js +4 -2
- package/lib/request-helpers.js +334 -29
- package/lib/resource-access-lock.js +3 -3
- package/lib/restore-bundle.js +46 -18
- package/lib/restore-rollback.js +10 -4
- package/lib/restore.js +24 -22
- package/lib/retention.js +23 -9
- package/lib/router.js +17 -4
- package/lib/safe-async.js +457 -0
- package/lib/safe-buffer.js +137 -6
- package/lib/safe-decompress.js +2 -1
- package/lib/safe-dns.js +2 -1
- package/lib/safe-ical.js +14 -28
- package/lib/safe-icap.js +1 -1
- package/lib/safe-json.js +51 -8
- package/lib/safe-jsonpath.js +6 -5
- package/lib/safe-mime.js +25 -29
- package/lib/safe-redirect.js +2 -5
- package/lib/safe-schema.js +7 -6
- package/lib/safe-sieve.js +1 -1
- package/lib/safe-sql.js +126 -0
- package/lib/safe-vcard.js +13 -27
- package/lib/sandbox-worker.js +15 -2
- package/lib/sandbox.js +4 -3
- package/lib/scheduler.js +22 -13
- package/lib/sec-cyber.js +82 -37
- package/lib/seeders.js +4 -11
- package/lib/self-update-standalone-verifier.js +16 -0
- package/lib/self-update.js +92 -69
- package/lib/session-device-binding.js +112 -66
- package/lib/session.js +219 -7
- package/lib/sql.js +228 -81
- package/lib/sse.js +6 -10
- package/lib/static.js +201 -111
- package/lib/storage.js +4 -2
- package/lib/structured-fields.js +275 -16
- package/lib/template.js +7 -5
- package/lib/tenant-quota.js +53 -38
- package/lib/tsa.js +16 -17
- package/lib/validate-opts.js +154 -8
- package/lib/vault/index.js +5 -0
- package/lib/vault/passphrase-ops.js +22 -26
- package/lib/vault/passphrase-source.js +8 -3
- package/lib/vault/rotate.js +13 -18
- package/lib/vault/seal-pem-file.js +34 -49
- package/lib/vault-aad.js +3 -2
- package/lib/vc.js +3 -8
- package/lib/vendor/MANIFEST.json +10 -10
- package/lib/vendor/public-suffix-list.dat +23 -10
- package/lib/vendor/public-suffix-list.data.js +5498 -5494
- package/lib/vex.js +35 -13
- package/lib/web-push-vapid.js +23 -20
- package/lib/webhook-dispatcher.js +706 -0
- package/lib/webhook.js +59 -19
- package/lib/websocket-channels.js +9 -7
- package/lib/websocket.js +8 -4
- package/lib/worm.js +3 -4
- package/lib/ws-client.js +65 -56
- package/lib/x509-chain.js +44 -0
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
|
|
67
67
|
var validateOpts = require("../validate-opts");
|
|
68
68
|
var safeBuffer = require("../safe-buffer");
|
|
69
|
+
var safeJson = require("../safe-json");
|
|
69
70
|
|
|
70
71
|
// Per W3C draft + Chromium implementation. `immediate` triggers the
|
|
71
72
|
// speculation as soon as the rules are seen; `conservative` waits
|
|
@@ -129,7 +130,7 @@ function _validateRules(rules, label) {
|
|
|
129
130
|
throw new TypeError(label + "." + actionKey + "[" + ei +
|
|
130
131
|
"].where must be a `where` clause object (W3C draft, e.g. { href_matches: \"/path/*\" })");
|
|
131
132
|
}
|
|
132
|
-
if (typeof rule.eagerness !== "string" || !EAGERNESS_LEVELS
|
|
133
|
+
if (typeof rule.eagerness !== "string" || !Object.prototype.hasOwnProperty.call(EAGERNESS_LEVELS, rule.eagerness)) {
|
|
133
134
|
throw new TypeError(label + "." + actionKey + "[" + ei +
|
|
134
135
|
"].eagerness must be one of: " + Object.keys(EAGERNESS_LEVELS).join(", "));
|
|
135
136
|
}
|
|
@@ -245,8 +246,10 @@ function create(opts) {
|
|
|
245
246
|
}
|
|
246
247
|
|
|
247
248
|
// Pre-built inline JSON. The body is small (rules objects are
|
|
248
|
-
// typically ~200 bytes);
|
|
249
|
-
|
|
249
|
+
// typically ~200 bytes); stringify once and cache. Uses the
|
|
250
|
+
// <script>-safe serializer so a rules value containing "</script>"
|
|
251
|
+
// (or U+2028/U+2029) cannot break out of the injected element.
|
|
252
|
+
var inlineJson = inline ? safeJson.stringifyForScript(rulesObj) : null;
|
|
250
253
|
|
|
251
254
|
return function speculationRules(req, res, next) {
|
|
252
255
|
if (!inline) {
|
|
@@ -150,10 +150,10 @@ function _parseChecksumHeader(headerValue, allowedSet) {
|
|
|
150
150
|
// alphabet); refuse those on the RAW value BEFORE the slice/trim
|
|
151
151
|
// normalisation (same v0.8.90 trim-before-validate bug class).
|
|
152
152
|
if (structuredFields.containsControlBytes(headerValue)) return { error: "malformed" };
|
|
153
|
-
var
|
|
154
|
-
if (
|
|
155
|
-
var algo =
|
|
156
|
-
var digestB64 =
|
|
153
|
+
var kvp = structuredFields.parseKeyValuePiece(headerValue, " ");
|
|
154
|
+
if (kvp.value === null) return { error: "malformed" };
|
|
155
|
+
var algo = kvp.key;
|
|
156
|
+
var digestB64 = kvp.value.trim();
|
|
157
157
|
if (algo.length === 0 || digestB64.length === 0) return { error: "malformed" };
|
|
158
158
|
if (!allowedSet[algo]) return { error: "algo-unsupported" };
|
|
159
159
|
if (!/^[A-Za-z0-9+/=]+$/.test(digestB64)) return { error: "malformed" };
|
|
@@ -311,19 +311,11 @@ function _emitTusBaseHeaders(res, extra) {
|
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
function _readChunk(req, maxChunkSize) {
|
|
314
|
-
return
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
sizeMessage: "PATCH body exceeded maxChunkSize",
|
|
320
|
-
});
|
|
321
|
-
req.on("data", function (c) {
|
|
322
|
-
try { collector.push(c); }
|
|
323
|
-
catch (e) { req.removeAllListeners("data"); reject(e); }
|
|
324
|
-
});
|
|
325
|
-
req.on("end", function () { resolve(collector.result()); });
|
|
326
|
-
req.on("error", function (e) { reject(e); });
|
|
314
|
+
return safeBuffer.collectStream(req, {
|
|
315
|
+
maxBytes: maxChunkSize,
|
|
316
|
+
errorClass: TusError,
|
|
317
|
+
sizeCode: "tus/chunk-too-large",
|
|
318
|
+
sizeMessage: "PATCH body exceeded maxChunkSize",
|
|
327
319
|
});
|
|
328
320
|
}
|
|
329
321
|
|
|
@@ -388,11 +380,8 @@ function create(opts) {
|
|
|
388
380
|
}
|
|
389
381
|
|
|
390
382
|
var store = opts.store;
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
throw new TusError("tus/bad-store",
|
|
394
|
-
"middleware.tusUpload: store must implement { create, head, append, terminate }");
|
|
395
|
-
}
|
|
383
|
+
validateOpts.requireMethods(store, ["create", "head", "append", "terminate"],
|
|
384
|
+
"middleware.tusUpload: store", TusError, "tus/bad-store");
|
|
396
385
|
|
|
397
386
|
var maxSize = opts.maxSize;
|
|
398
387
|
if (maxSize !== undefined && (typeof maxSize !== "number" || !isFinite(maxSize) || maxSize <= 0)) {
|
|
@@ -410,7 +399,7 @@ function create(opts) {
|
|
|
410
399
|
|
|
411
400
|
var extensions = Array.isArray(opts.extensions) ? opts.extensions.slice() : DEFAULT_EXTENSIONS.slice();
|
|
412
401
|
for (var i = 0; i < extensions.length; i++) {
|
|
413
|
-
if (!KNOWN_EXTENSIONS
|
|
402
|
+
if (!Object.prototype.hasOwnProperty.call(KNOWN_EXTENSIONS, extensions[i])) {
|
|
414
403
|
throw new TusError("tus/bad-opts",
|
|
415
404
|
"middleware.tusUpload: unknown extension '" + extensions[i] + "'");
|
|
416
405
|
}
|
|
@@ -427,7 +416,7 @@ function create(opts) {
|
|
|
427
416
|
var checksumAlgorithmSet = {};
|
|
428
417
|
for (var j = 0; j < checksumAlgorithms.length; j++) {
|
|
429
418
|
var algo = checksumAlgorithms[j];
|
|
430
|
-
if (!KNOWN_CHECKSUM_ALGORITHMS
|
|
419
|
+
if (!Object.prototype.hasOwnProperty.call(KNOWN_CHECKSUM_ALGORITHMS, algo)) {
|
|
431
420
|
throw new TusError("tus/bad-opts",
|
|
432
421
|
"middleware.tusUpload: unknown checksum algorithm '" + algo + "'");
|
|
433
422
|
}
|
|
@@ -451,11 +440,7 @@ function create(opts) {
|
|
|
451
440
|
return new Date(rec.expireAt).toUTCString();
|
|
452
441
|
}
|
|
453
442
|
|
|
454
|
-
|
|
455
|
-
if (!auditOn) return;
|
|
456
|
-
try { observability().safeEvent("middleware.tusUpload." + verb, 1, {}); }
|
|
457
|
-
catch (_e) { /* drop-silent — observability sink */ }
|
|
458
|
-
}
|
|
443
|
+
var _emitMetric = observability().namespaced("middleware.tusUpload", auditOn);
|
|
459
444
|
|
|
460
445
|
async function _handleOptions(req, res) {
|
|
461
446
|
var headers = _emitTusBaseHeaders(res, {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
var lazyRequire = require("../lazy-require");
|
|
30
30
|
var safeJson = require("../safe-json");
|
|
31
31
|
var validateOpts = require("../validate-opts");
|
|
32
|
+
var denyResponse = require("./deny-response");
|
|
32
33
|
var { defineClass } = require("../framework-error");
|
|
33
34
|
|
|
34
35
|
var WebAppManifestError = defineClass("WebAppManifestError", { alwaysPermanent: true });
|
|
@@ -135,13 +136,7 @@ function create(opts) {
|
|
|
135
136
|
(alsoAtJsonPath && path === "/manifest.json");
|
|
136
137
|
if (!matches) return next();
|
|
137
138
|
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
138
|
-
|
|
139
|
-
res.writeHead(405, { // HTTP 405 status
|
|
140
|
-
"Allow": "GET, HEAD",
|
|
141
|
-
"Content-Type": "text/plain; charset=utf-8",
|
|
142
|
-
"Content-Length": Buffer.byteLength(bodyMsg),
|
|
143
|
-
});
|
|
144
|
-
res.end(bodyMsg);
|
|
139
|
+
denyResponse.methodNotAllowed(res, "GET, HEAD");
|
|
145
140
|
return;
|
|
146
141
|
}
|
|
147
142
|
res.writeHead(200, { // HTTP 200 status
|
package/lib/migrations.js
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
41
|
var nodePath = require("node:path");
|
|
42
|
+
var moduleLoader = require("./module-loader");
|
|
42
43
|
var atomicFile = require("./atomic-file");
|
|
43
44
|
var dbSchema = require("./db-schema");
|
|
44
45
|
var frameworkSchema = require("./framework-schema");
|
|
@@ -269,21 +270,11 @@ function _resolveDb(opts) {
|
|
|
269
270
|
}
|
|
270
271
|
|
|
271
272
|
function _loadMigration(file, dir) {
|
|
272
|
-
var
|
|
273
|
-
|
|
274
|
-
// changes a migration file between calls picks up the new content.
|
|
275
|
-
// Production deployments would always restart the process, but this
|
|
276
|
-
// keeps test fixtures sane.
|
|
277
|
-
try { delete require.cache[require.resolve(fullPath)]; } catch (_e) { /* not yet cached */ }
|
|
278
|
-
var mod;
|
|
279
|
-
// Operator-supplied migration — dynamic by design, can't be bundle-
|
|
280
|
-
// traced. Host-CLI scope; deploying via SEA / pkg drops this surface.
|
|
281
|
-
try { mod = require(fullPath); } // allow:dynamic-require — operator-supplied migration
|
|
282
|
-
catch (e) {
|
|
283
|
-
throw new MigrationError("migrations/load-failed",
|
|
273
|
+
var mod = moduleLoader.requireFresh(nodePath.join(dir, file), function (e) {
|
|
274
|
+
return new MigrationError("migrations/load-failed",
|
|
284
275
|
"migration '" + file + "' failed to load: " + ((e && e.message) || String(e)),
|
|
285
276
|
true);
|
|
286
|
-
}
|
|
277
|
+
});
|
|
287
278
|
if (!mod || typeof mod.up !== "function") {
|
|
288
279
|
throw new MigrationError("migrations/missing-up",
|
|
289
280
|
"migration '" + file + "' must export an `up(db)` function", true);
|
package/lib/mime-parse.js
CHANGED
|
@@ -37,32 +37,48 @@
|
|
|
37
37
|
* mdn: 1 MiB) so this module's hot-path doesn't add its own cap.
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
|
-
function
|
|
41
|
-
// RFC 5322 §2.2
|
|
42
|
-
//
|
|
43
|
-
// the
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
function classifyHeaderBlock(text) {
|
|
41
|
+
// RFC 5322 §2.2 — every line of a header section is either a header field
|
|
42
|
+
// (`name: value`), a folding continuation (leading WSP), or the empty line
|
|
43
|
+
// that ends the section. Anything else is MALFORMED — and a colon-less line
|
|
44
|
+
// sitting in the header section is the header-injection / SMTP-smuggling
|
|
45
|
+
// signal (attacker content on a bare line followed by an injected
|
|
46
|
+
// Bcc/To/From header). `fields` is the parsed headers (boundary-aware,
|
|
47
|
+
// continuation-unfolded); `malformed` is the injection/structure evidence the
|
|
48
|
+
// silent-skip parsers (email, mime, dsn, arc) all dropped on the floor.
|
|
49
|
+
var lines = String(text == null ? "" : text).split(/\r?\n/);
|
|
50
|
+
var unfolded = []; // [{ line, lineIndex }]
|
|
46
51
|
for (var i = 0; i < lines.length; i += 1) {
|
|
47
52
|
var line = lines[i];
|
|
48
|
-
if (line.length === 0) break;
|
|
53
|
+
if (line.length === 0) break; // header/body boundary
|
|
49
54
|
if ((line.charAt(0) === " " || line.charAt(0) === "\t") && unfolded.length > 0) {
|
|
50
|
-
unfolded[unfolded.length - 1] += " " + line.replace(/^\s+/, "");
|
|
55
|
+
unfolded[unfolded.length - 1].line += " " + line.replace(/^\s+/, "");
|
|
51
56
|
} else {
|
|
52
|
-
unfolded.push(line);
|
|
57
|
+
unfolded.push({ line: line, lineIndex: i });
|
|
53
58
|
}
|
|
54
59
|
}
|
|
55
|
-
var
|
|
60
|
+
var fields = [];
|
|
61
|
+
var malformed = [];
|
|
56
62
|
for (var j = 0; j < unfolded.length; j += 1) {
|
|
57
|
-
var
|
|
58
|
-
var colonAt =
|
|
59
|
-
if (colonAt === -1)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
var entry = unfolded[j];
|
|
64
|
+
var colonAt = entry.line.indexOf(":");
|
|
65
|
+
if (colonAt === -1) {
|
|
66
|
+
malformed.push({ lineIndex: entry.lineIndex, line: entry.line, reason: "no-colon" });
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
fields.push({
|
|
70
|
+
name: entry.line.slice(0, colonAt).trim(),
|
|
71
|
+
value: entry.line.slice(colonAt + 1).trim(),
|
|
63
72
|
});
|
|
64
73
|
}
|
|
65
|
-
return
|
|
74
|
+
return { fields: fields, malformed: malformed };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function parseHeaderBlock(text) {
|
|
78
|
+
// The fields view of the shared classifier — kept for every caller that only
|
|
79
|
+
// wants the parsed headers (the malformed lines are reached via
|
|
80
|
+
// classifyHeaderBlock for structure/injection validation).
|
|
81
|
+
return classifyHeaderBlock(text).fields;
|
|
66
82
|
}
|
|
67
83
|
|
|
68
84
|
function splitHeadersAndBody(text) {
|
|
@@ -189,6 +205,7 @@ function addressType(addr) {
|
|
|
189
205
|
|
|
190
206
|
module.exports = {
|
|
191
207
|
parseHeaderBlock: parseHeaderBlock,
|
|
208
|
+
classifyHeaderBlock: classifyHeaderBlock,
|
|
192
209
|
splitHeadersAndBody: splitHeadersAndBody,
|
|
193
210
|
findHeader: findHeader,
|
|
194
211
|
parseContentType: parseContentType,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* lib/module-loader.js — the single audited entry point for loading an
|
|
4
|
+
* operator-supplied module file (a migration or a seed) by path.
|
|
5
|
+
*
|
|
6
|
+
* Operator modules execute arbitrary code on `require`, so the dynamic
|
|
7
|
+
* `require()` lives here behind ONE `allow:dynamic-require` marker rather
|
|
8
|
+
* than scattered across every host-CLI loader (`b.migrations`,
|
|
9
|
+
* `b.seeders`, `b.externalDb.migrate`). The require cache is busted first
|
|
10
|
+
* so a dev / test rewriting a fixture between calls picks up the new
|
|
11
|
+
* content (production deployments restart the process). The dynamic
|
|
12
|
+
* require does not survive SEA / esbuild bundling — operator migrations
|
|
13
|
+
* and seeds are host-CLI scope, not framework-internal scope.
|
|
14
|
+
*
|
|
15
|
+
* The caller owns path construction (it knows its own directory layout)
|
|
16
|
+
* and the typed, domain-specific error it throws on a load failure
|
|
17
|
+
* (parse error, throwing top-level code), so resolution stays identical
|
|
18
|
+
* to the per-loader form it replaces.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* requireFresh(absPath, onLoadError) — bust the require cache for
|
|
23
|
+
* `absPath`, then require it fresh. `absPath` MUST be absolute (a bare
|
|
24
|
+
* relative path would resolve against node_modules, which is never an
|
|
25
|
+
* operator file). On a load failure, `onLoadError(err)` builds the
|
|
26
|
+
* caller's typed error, which is thrown.
|
|
27
|
+
*
|
|
28
|
+
* var mod = moduleLoader.requireFresh(path.join(dir, file), function (e) {
|
|
29
|
+
* return new MigrationError("migrations/load-failed",
|
|
30
|
+
* "migration '" + file + "' failed to load: " + ((e && e.message) || String(e)), true);
|
|
31
|
+
* });
|
|
32
|
+
*/
|
|
33
|
+
function requireFresh(absPath, onLoadError) {
|
|
34
|
+
try { delete require.cache[require.resolve(absPath)]; } catch (_e) { /* not yet cached */ }
|
|
35
|
+
try {
|
|
36
|
+
return require(absPath); // allow:dynamic-require — operator-supplied module (migration / seed)
|
|
37
|
+
} catch (e) {
|
|
38
|
+
throw onLoadError(e);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
requireFresh: requireFresh,
|
|
44
|
+
};
|
package/lib/money.js
CHANGED
|
@@ -277,6 +277,32 @@ Money.prototype.multiply = function (factor, opts) {
|
|
|
277
277
|
return new Money(quotient, this.currency);
|
|
278
278
|
};
|
|
279
279
|
|
|
280
|
+
/**
|
|
281
|
+
* @primitive b.money.Money.roundToIncrement
|
|
282
|
+
* @signature b.money.Money.roundToIncrement(step, opts?)
|
|
283
|
+
* @since 0.15.13
|
|
284
|
+
* @status stable
|
|
285
|
+
* @related b.money.roundMinor, b.money.Money
|
|
286
|
+
*
|
|
287
|
+
* Snap this amount to the nearest multiple of `step` minor units, returning a
|
|
288
|
+
* new `Money` in the same currency — the cash-rounding step a coarser
|
|
289
|
+
* denomination needs (CHF to the nearest 0.05, SEK to the nearest 0.10, a
|
|
290
|
+
* 100-unit price step) without leaving the type. Integer-only; immutable;
|
|
291
|
+
* negative amounts (refund previews) round on the correct side of the tie. See
|
|
292
|
+
* `b.money.roundMinor` for the raw-integer form and the mode semantics.
|
|
293
|
+
*
|
|
294
|
+
* @opts
|
|
295
|
+
* mode: "half-even" | "half-up" | "half-down" | "ceiling" | "floor", // default: half-even
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* b.money.of("12.32", "CHF").roundToIncrement(5, { mode: "half-up" }); // → CHF 12.30
|
|
299
|
+
* b.money.of("19.97", "SEK").roundToIncrement(10); // → SEK 20.00
|
|
300
|
+
*/
|
|
301
|
+
Money.prototype.roundToIncrement = function (step, opts) {
|
|
302
|
+
opts = opts || {};
|
|
303
|
+
return new Money(roundMinor(this._minor, step, opts.mode || "half-even"), this.currency);
|
|
304
|
+
};
|
|
305
|
+
|
|
280
306
|
// _rationalFromDecimalString -- `"1.085"` -> { num: 1085n, den: 1000n }.
|
|
281
307
|
// Strict shape; same refusals as _parseDecimalString.
|
|
282
308
|
function _rationalFromDecimalString(s) {
|
|
@@ -333,6 +359,84 @@ function _divRound(n, d, rounding) {
|
|
|
333
359
|
return r < 0n ? q - 1n : q + 1n;
|
|
334
360
|
}
|
|
335
361
|
|
|
362
|
+
// Cash-rounding modes for roundMinor / Money.roundToIncrement. half-even
|
|
363
|
+
// (banker's) is the default and matches the rest of the module; half-up rounds
|
|
364
|
+
// a tie away from zero, half-down toward zero; ceiling/floor are directional
|
|
365
|
+
// (toward +inf / -inf) regardless of distance.
|
|
366
|
+
var INCREMENT_MODES = {
|
|
367
|
+
"half-even": true, "half-up": true, "half-down": true, "ceiling": true, "floor": true,
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
function _toIncrementBigInt(step) {
|
|
371
|
+
if (typeof step === "bigint") {
|
|
372
|
+
if (step <= 0n) throw new MoneyError("money/bad-increment",
|
|
373
|
+
"step must be a positive integer of minor units");
|
|
374
|
+
return step;
|
|
375
|
+
}
|
|
376
|
+
if (typeof step === "number" && Number.isInteger(step) && step > 0) return BigInt(step);
|
|
377
|
+
throw new MoneyError("money/bad-increment",
|
|
378
|
+
"step must be a positive integer (BigInt or safe integer Number) of minor units; got " +
|
|
379
|
+
(typeof step === "number" ? String(step) : typeof step));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* @primitive b.money.roundMinor
|
|
384
|
+
* @signature b.money.roundMinor(minor, step, mode?)
|
|
385
|
+
* @since 0.15.13
|
|
386
|
+
* @status stable
|
|
387
|
+
* @related b.money.Money, b.money.fromMinorUnits
|
|
388
|
+
*
|
|
389
|
+
* Snap a raw minor-unit integer to the nearest multiple of `step` minor units —
|
|
390
|
+
* the cash-rounding step a coarser cash denomination needs even though the
|
|
391
|
+
* currency's ISO 4217 minor unit is finer (a CHF total to the nearest 5 rappen
|
|
392
|
+
* after the 1/2-rappen coins were retired, a SEK total to the nearest 10 öre, a
|
|
393
|
+
* JPY total to a 100-unit psychological-pricing step). Pure BigInt math — no
|
|
394
|
+
* `Number` in the value path — and the remainder sign is handled so a negative
|
|
395
|
+
* amount (a refund preview) rounds on the correct side of the tie.
|
|
396
|
+
*
|
|
397
|
+
* `minor` accepts a BigInt or a safe integer `Number`; the return is a BigInt.
|
|
398
|
+
*
|
|
399
|
+
* @opts
|
|
400
|
+
* mode: "half-even" | "half-up" | "half-down" | "ceiling" | "floor", // default: half-even
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* b.money.roundMinor(1232n, 5n); // CHF 12.32 → nearest 0.05 → 1230n (12.30)
|
|
404
|
+
* b.money.roundMinor(25n, 10n, "half-even"); // tie → even multiple → 20n
|
|
405
|
+
* b.money.roundMinor(25n, 10n, "half-up"); // tie away from zero → 30n
|
|
406
|
+
* b.money.roundMinor(-25n, 10n, "half-up"); // refund tie away from zero → -30n
|
|
407
|
+
*/
|
|
408
|
+
function roundMinor(minor, step, mode) {
|
|
409
|
+
mode = mode || "half-even";
|
|
410
|
+
if (typeof minor === "number" && Number.isInteger(minor)) minor = BigInt(minor);
|
|
411
|
+
if (typeof minor !== "bigint") {
|
|
412
|
+
throw new MoneyError("money/bad-minor-units",
|
|
413
|
+
"minor must be an integer (BigInt or safe integer Number); got " + (typeof minor));
|
|
414
|
+
}
|
|
415
|
+
if (!Object.prototype.hasOwnProperty.call(INCREMENT_MODES, mode)) {
|
|
416
|
+
throw new MoneyError("money/bad-rounding-mode",
|
|
417
|
+
"mode must be one of half-even | half-up | half-down | ceiling | floor; got " + String(mode));
|
|
418
|
+
}
|
|
419
|
+
var stepBig = _toIncrementBigInt(step);
|
|
420
|
+
var q = minor / stepBig;
|
|
421
|
+
var r = minor - q * stepBig;
|
|
422
|
+
if (r === 0n) return minor;
|
|
423
|
+
// lower = the multiple toward -inf, upper = toward +inf. BigInt division
|
|
424
|
+
// truncates toward zero, so the bracket flips by sign of `minor`.
|
|
425
|
+
var lower, upper;
|
|
426
|
+
if (minor >= 0n) { lower = q * stepBig; upper = lower + stepBig; }
|
|
427
|
+
else { upper = q * stepBig; lower = upper - stepBig; }
|
|
428
|
+
if (mode === "floor") return lower;
|
|
429
|
+
if (mode === "ceiling") return upper;
|
|
430
|
+
var distLow = minor - lower; // >= 0
|
|
431
|
+
var distHigh = upper - minor; // >= 0
|
|
432
|
+
if (distLow < distHigh) return lower;
|
|
433
|
+
if (distHigh < distLow) return upper;
|
|
434
|
+
// Exactly on the tie.
|
|
435
|
+
if (mode === "half-up") return (minor >= 0n) ? upper : lower; // away from zero
|
|
436
|
+
if (mode === "half-down") return (minor >= 0n) ? lower : upper; // toward zero
|
|
437
|
+
return ((lower / stepBig) % 2n === 0n) ? lower : upper; // half-even
|
|
438
|
+
}
|
|
439
|
+
|
|
336
440
|
// allocate -- split `this` into `weights.length` parts proportional to
|
|
337
441
|
// the weights, distributing every minor unit. Largest-remainder
|
|
338
442
|
// method: floor each share, then hand out the leftover units to the
|
|
@@ -693,6 +797,7 @@ module.exports = {
|
|
|
693
797
|
parse: parse,
|
|
694
798
|
zero: zero,
|
|
695
799
|
convert: convert,
|
|
800
|
+
roundMinor: roundMinor,
|
|
696
801
|
CURRENCIES: CURRENCIES,
|
|
697
802
|
Money: Money,
|
|
698
803
|
MoneyError: MoneyError,
|