@blamejs/blamejs-shop 0.3.15 → 0.3.16
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/admin.js +136 -3
- package/lib/asset-manifest.json +1 -1
- package/lib/catalog.js +61 -2
- package/lib/vendor/MANIFEST.json +2 -2
- package/lib/vendor/blamejs/CHANGELOG.md +2 -0
- package/lib/vendor/blamejs/api-snapshot.json +2 -2
- package/lib/vendor/blamejs/lib/a2a-tasks.js +6 -6
- package/lib/vendor/blamejs/lib/ai-input.js +1 -1
- package/lib/vendor/blamejs/lib/auth/acr-vocabulary.js +1 -1
- package/lib/vendor/blamejs/lib/auth/ciba.js +3 -3
- package/lib/vendor/blamejs/lib/auth/oauth.js +1 -1
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +1 -1
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +1 -1
- package/lib/vendor/blamejs/lib/breach-deadline.js +3 -3
- package/lib/vendor/blamejs/lib/calendar.js +2 -2
- package/lib/vendor/blamejs/lib/content-credentials.js +3 -3
- package/lib/vendor/blamejs/lib/ddl-change-control.js +2 -2
- package/lib/vendor/blamejs/lib/did.js +2 -2
- package/lib/vendor/blamejs/lib/dsr.js +4 -4
- package/lib/vendor/blamejs/lib/external-db.js +1 -1
- package/lib/vendor/blamejs/lib/guard-cidr.js +1 -1
- package/lib/vendor/blamejs/lib/guard-image.js +1 -1
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +1 -1
- package/lib/vendor/blamejs/lib/guard-time.js +1 -1
- package/lib/vendor/blamejs/lib/guard-xml.js +1 -1
- package/lib/vendor/blamejs/lib/http-client-cache.js +1 -1
- package/lib/vendor/blamejs/lib/iab-tcf.js +4 -4
- package/lib/vendor/blamejs/lib/json-schema.js +1 -1
- package/lib/vendor/blamejs/lib/jtd.js +1 -1
- package/lib/vendor/blamejs/lib/mail-auth.js +1 -1
- package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
- package/lib/vendor/blamejs/lib/mail-crypto-smime.js +1 -1
- package/lib/vendor/blamejs/lib/mail-server-mx.js +1 -1
- package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +1 -1
- package/lib/vendor/blamejs/lib/mail-server-submission.js +1 -1
- package/lib/vendor/blamejs/lib/mcp.js +7 -7
- package/lib/vendor/blamejs/lib/mdoc.js +1 -1
- package/lib/vendor/blamejs/lib/metrics.js +2 -2
- package/lib/vendor/blamejs/lib/middleware/compose-pipeline.js +1 -1
- package/lib/vendor/blamejs/lib/network-dnssec.js +2 -2
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +1 -1
- package/lib/vendor/blamejs/lib/network-tls.js +1 -1
- package/lib/vendor/blamejs/lib/network-tsig.js +3 -3
- package/lib/vendor/blamejs/lib/rfc3339.js +2 -2
- package/lib/vendor/blamejs/lib/safe-decompress.js +1 -1
- package/lib/vendor/blamejs/lib/standard-webhooks.js +3 -3
- package/lib/vendor/blamejs/lib/stream-throttle.js +2 -2
- package/lib/vendor/blamejs/lib/structured-fields.js +1 -1
- package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +1 -1
- package/lib/vendor/blamejs/lib/web-push-vapid.js +1 -1
- package/lib/vendor/blamejs/lib/webhook.js +1 -1
- package/lib/vendor/blamejs/lib/websocket.js +1 -1
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.14.8.json +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +221 -35
- package/package.json +1 -1
|
@@ -111,7 +111,7 @@ var PROFILES = Object.freeze({
|
|
|
111
111
|
framesPolicy: "reject",
|
|
112
112
|
maxWidth: C.BYTES.bytes(8192), // pixel cap, repurposing bytes() for clarity
|
|
113
113
|
maxHeight: C.BYTES.bytes(8192),
|
|
114
|
-
maxFrames: 60, // allow:raw-time-literal —
|
|
114
|
+
maxFrames: 60, // allow:raw-time-literal — max-frame count 60; coincidental multiple-of-60, not a duration, C.TIME N/A
|
|
115
115
|
maxBytes: C.BYTES.mib(32),
|
|
116
116
|
maxRuntimeMs: C.TIME.seconds(5),
|
|
117
117
|
},
|
|
@@ -371,7 +371,7 @@ function _hasControlChar(s) {
|
|
|
371
371
|
|
|
372
372
|
function _trunc(s) {
|
|
373
373
|
if (s.length <= 64) return s; // error-message truncation
|
|
374
|
-
return s.slice(0, 60) + "…"; // allow:raw-time-literal — char
|
|
374
|
+
return s.slice(0, 60) + "…"; // allow:raw-time-literal — truncation char-count 60; coincidental multiple-of-60, not a duration, C.TIME N/A
|
|
375
375
|
}
|
|
376
376
|
|
|
377
377
|
function _verdict(action, reason, extra) {
|
|
@@ -254,7 +254,7 @@ function _detectIssues(input, opts) {
|
|
|
254
254
|
snippet: "minute " + minute + " > 59",
|
|
255
255
|
});
|
|
256
256
|
}
|
|
257
|
-
if (second > 60) { // allow:raw-time-literal — leap-second ceiling
|
|
257
|
+
if (second > 60) { // allow:raw-time-literal — leap-second ceiling literal 60 (RFC 3339 5.6); coincidental multiple-of-60, not a duration, C.TIME N/A
|
|
258
258
|
issues.push({
|
|
259
259
|
kind: "second-range", severity: "high",
|
|
260
260
|
ruleId: "time.second-range",
|
|
@@ -303,7 +303,7 @@ function _detectIssues(input, opts) {
|
|
|
303
303
|
// get the NCR cap disabled with them. The `maxNumericCharRefs` opt
|
|
304
304
|
// is validated by `numericBounds.requireAllPositiveFiniteIntIfPresent`
|
|
305
305
|
// at the public-surface boundary above.
|
|
306
|
-
var ncrCap = opts.maxNumericCharRefs;
|
|
306
|
+
var ncrCap = opts.maxNumericCharRefs;
|
|
307
307
|
if (ncrCap !== undefined && ncrCap !== null) {
|
|
308
308
|
var ncrMatches = input.match(NUMERIC_CHAR_REF_RE); // allow:regex-no-length-cap — input bounded by maxBytes above
|
|
309
309
|
var ncrCount = ncrMatches === null ? 0 : ncrMatches.length;
|
|
@@ -66,7 +66,7 @@ var HEURISTIC_MAX_AGE_MS = C.TIME.hours(24);
|
|
|
66
66
|
// Statuses RFC 9110 designates as heuristically cacheable. (Plus 200/206
|
|
67
67
|
// which are universally cacheable when a freshness lifetime is given.)
|
|
68
68
|
var CACHEABLE_STATUSES = new Set([
|
|
69
|
-
200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501, // allow:raw-time-literal —
|
|
69
|
+
200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501, // allow:raw-time-literal — RFC 9111 cacheable status-code set; coincidental multiple-of-60 entries, not durations, C.TIME N/A
|
|
70
70
|
]);
|
|
71
71
|
|
|
72
72
|
// Headers that MUST not be forwarded when serving a 304-updated entry.
|
|
@@ -108,7 +108,7 @@ var TCF_V23_POLICY_VERSION = 4;
|
|
|
108
108
|
var SEGMENT_TYPE_DISCLOSED_VENDORS = 1; // TCF segment-type marker, not bytes
|
|
109
109
|
var SEGMENT_TYPE_ALLOWED_VENDORS = 2; // TCF segment-type marker, not bytes
|
|
110
110
|
var SEGMENT_TYPE_PUBLISHER_TC = 3; // TCF segment-type marker, not bytes
|
|
111
|
-
var MAX_TC_STRING_BYTES = 64 * 1024;
|
|
111
|
+
var MAX_TC_STRING_BYTES = 64 * 1024;
|
|
112
112
|
|
|
113
113
|
// base64url decode (no padding) → Buffer.
|
|
114
114
|
function _b64urlDecode(s) {
|
|
@@ -186,8 +186,8 @@ function _parseCore(buf) {
|
|
|
186
186
|
var publisherRestrictions = _parsePublisherRestrictions(r);
|
|
187
187
|
return {
|
|
188
188
|
version: version,
|
|
189
|
-
createdAt: createdRaw * 100,
|
|
190
|
-
lastUpdatedAt: lastUpdatedRaw * 100,
|
|
189
|
+
createdAt: createdRaw * 100,
|
|
190
|
+
lastUpdatedAt: lastUpdatedRaw * 100,
|
|
191
191
|
cmpId: cmpId,
|
|
192
192
|
cmpVersion: cmpVersion,
|
|
193
193
|
consentScreen: consentScreen,
|
|
@@ -545,7 +545,7 @@ function _idRuns(ids) {
|
|
|
545
545
|
function _decisec(t) {
|
|
546
546
|
var ms = t instanceof Date ? t.getTime() : (t == null ? Date.now() : Number(t));
|
|
547
547
|
if (!isFinite(ms) || ms < 0) throw IabTcfError.factory("iab-tcf/bad-value", "iabTcf.encode: timestamp must be a Date or non-negative epoch-ms");
|
|
548
|
-
return Math.round(ms / 100);
|
|
548
|
+
return Math.round(ms / 100);
|
|
549
549
|
}
|
|
550
550
|
|
|
551
551
|
// Bit writer mirroring _bitReader: bits are packed high-bit-first, then the
|
|
@@ -487,7 +487,7 @@ function _typeMatches(typeKw, instance, actual) {
|
|
|
487
487
|
function _checkNumber(schema, n, emit) {
|
|
488
488
|
if (typeof schema.multipleOf === "number") {
|
|
489
489
|
var q = n / schema.multipleOf;
|
|
490
|
-
if (!isFinite(q) || Math.abs(q - Math.round(q)) > 1e-9 * Math.max(1, Math.abs(q))) {
|
|
490
|
+
if (!isFinite(q) || Math.abs(q - Math.round(q)) > 1e-9 * Math.max(1, Math.abs(q))) {
|
|
491
491
|
// Exact check for integers; tolerance only bridges float error.
|
|
492
492
|
if (n % schema.multipleOf !== 0) emit("multipleOf", "value is not a multiple of " + schema.multipleOf);
|
|
493
493
|
}
|
|
@@ -33,7 +33,7 @@ var rfc3339 = require("./rfc3339");
|
|
|
33
33
|
|
|
34
34
|
var JtdError = defineClass("JtdError", { alwaysPermanent: true });
|
|
35
35
|
|
|
36
|
-
var MAX_DEPTH = 10000;
|
|
36
|
+
var MAX_DEPTH = 10000;
|
|
37
37
|
|
|
38
38
|
var TYPES = {
|
|
39
39
|
boolean: 1, string: 1, timestamp: 1, float32: 1, float64: 1,
|
|
@@ -1819,7 +1819,7 @@ function authResultsEmit(opts) {
|
|
|
1819
1819
|
// // }
|
|
1820
1820
|
|
|
1821
1821
|
var DMARC_RUA_MAX_REPORT_BYTES = C.BYTES.mib(8);
|
|
1822
|
-
var DMARC_RUA_MAX_RECORDS_PER_REPORT = 10000;
|
|
1822
|
+
var DMARC_RUA_MAX_RECORDS_PER_REPORT = 10000;
|
|
1823
1823
|
|
|
1824
1824
|
function _arrayOf(value) {
|
|
1825
1825
|
if (value === undefined || value === null) return [];
|
|
@@ -444,7 +444,7 @@ function validateTinyPsSvg(svgBytes) {
|
|
|
444
444
|
if (lname === "href" || lname === "xlink:href") {
|
|
445
445
|
if (aval.length > 0 && aval.charAt(0) !== "#") {
|
|
446
446
|
_vio("external-ref-forbidden",
|
|
447
|
-
"external reference in `" + aname + "='" + aval.slice(0, 60) /* allow:raw-time-literal — display truncation
|
|
447
|
+
"external reference in `" + aname + "='" + aval.slice(0, 60) /* allow:raw-time-literal — display truncation char-count 60; coincidental multiple-of-60, not a duration, C.TIME N/A */ + "...'` " +
|
|
448
448
|
"is forbidden in Tiny-PS (only `#fragment` permitted)");
|
|
449
449
|
}
|
|
450
450
|
}
|
|
@@ -754,7 +754,7 @@ function checkCert(opts) {
|
|
|
754
754
|
if (pub && pub.asymmetricKeyType === "rsa") {
|
|
755
755
|
var jwk = pub.export({ format: "jwk" });
|
|
756
756
|
var nBytes = Buffer.from(jwk.n, "base64url");
|
|
757
|
-
var bits = nBytes.length * 8; // allow:raw-time-literal —
|
|
757
|
+
var bits = nBytes.length * 8; // allow:raw-time-literal — byte-length*8 bit count; coincidental multiple-of-60 product, not a duration, C.TIME N/A
|
|
758
758
|
if (bits < RSA_MIN_BITS) {
|
|
759
759
|
throw new MailCryptoError("mail-crypto/smime/rsa-too-small",
|
|
760
760
|
"cert public key is " + bits + " RSA bits; minimum is " + RSA_MIN_BITS +
|
|
@@ -998,7 +998,7 @@ function create(opts) {
|
|
|
998
998
|
});
|
|
999
999
|
var deadline = Date.now() + timeoutMs;
|
|
1000
1000
|
while (connections.size > 0 && Date.now() < deadline) {
|
|
1001
|
-
await safeAsync.sleep(100);
|
|
1001
|
+
await safeAsync.sleep(100);
|
|
1002
1002
|
}
|
|
1003
1003
|
connections.forEach(function (sock) {
|
|
1004
1004
|
try { sock.destroy(); } catch (_e) { /* best-effort */ }
|
|
@@ -96,7 +96,7 @@ var MailServerRateLimitError = defineClass("MailServerRateLimitError", { alwaysP
|
|
|
96
96
|
|
|
97
97
|
var DEFAULTS = Object.freeze({
|
|
98
98
|
maxConcurrentConnectionsPerIp: 10,
|
|
99
|
-
connectionsPerIpPerMinute: 60, // allow:raw-time-literal — connection
|
|
99
|
+
connectionsPerIpPerMinute: 60, // allow:raw-time-literal — per-minute connection rate 60; time-derived (per-minute) single source of truth, C.TIME N/A as a count
|
|
100
100
|
authFailuresPerIpPer15Min: 10,
|
|
101
101
|
minBytesPerSecond: 100, // slow-loris byte-rate floor
|
|
102
102
|
// RCPT-TO recipient-failure cap defends against the 550-vs-250
|
|
@@ -1347,7 +1347,7 @@ function create(opts) {
|
|
|
1347
1347
|
});
|
|
1348
1348
|
var deadline = Date.now() + timeoutMs;
|
|
1349
1349
|
while (connections.size > 0 && Date.now() < deadline) {
|
|
1350
|
-
await safeAsync.sleep(100);
|
|
1350
|
+
await safeAsync.sleep(100);
|
|
1351
1351
|
}
|
|
1352
1352
|
connections.forEach(function (sock) {
|
|
1353
1353
|
try { sock.destroy(); } catch (_e) { /* best-effort */ }
|
|
@@ -45,12 +45,12 @@ var METHOD_NAME_MAX = 256;
|
|
|
45
45
|
// JSON-RPC 2.0 error codes (https://www.jsonrpc.org/specification#error_object).
|
|
46
46
|
// Negative numerics by spec; mapped to HTTP status for the framework's
|
|
47
47
|
// HTTP-shaped reply envelope.
|
|
48
|
-
var JSONRPC_PARSE_ERROR = -32700; // allow:raw-time-literal — not
|
|
49
|
-
var JSONRPC_INVALID_REQUEST = -32600;
|
|
50
|
-
var JSONRPC_METHOD_NOT_FOUND= -32601;
|
|
51
|
-
var JSONRPC_INVALID_PARAMS = -32602;
|
|
52
|
-
var JSONRPC_INTERNAL_ERROR = -32603;
|
|
53
|
-
var JSONRPC_AUTH_REQUIRED = -32001;
|
|
48
|
+
var JSONRPC_PARSE_ERROR = -32700; // allow:raw-time-literal — JSON-RPC error code -32700; coincidental multiple-of-60, not a time value, C.TIME N/A
|
|
49
|
+
var JSONRPC_INVALID_REQUEST = -32600;
|
|
50
|
+
var JSONRPC_METHOD_NOT_FOUND= -32601;
|
|
51
|
+
var JSONRPC_INVALID_PARAMS = -32602;
|
|
52
|
+
var JSONRPC_INTERNAL_ERROR = -32603;
|
|
53
|
+
var JSONRPC_AUTH_REQUIRED = -32001;
|
|
54
54
|
var TOOL_NAME_RE = /^[a-zA-Z][a-zA-Z0-9._-]{0,63}$/;
|
|
55
55
|
var RESOURCE_NAME_RE = /^[a-zA-Z][a-zA-Z0-9._/-]{0,255}$/;
|
|
56
56
|
|
|
@@ -424,7 +424,7 @@ function serverGuard(opts) {
|
|
|
424
424
|
* var safe = b.mcp.toolResult.sanitize(toolResp, { posture: "sanitize" });
|
|
425
425
|
* // → { content: [{ type: "text", text: "<cleaned>" }] }
|
|
426
426
|
*/
|
|
427
|
-
var DEFAULT_TOOL_OUTPUT_MAX_BYTES = 64 * 1024;
|
|
427
|
+
var DEFAULT_TOOL_OUTPUT_MAX_BYTES = 64 * 1024;
|
|
428
428
|
var PROMPT_INJECTION_MARKERS = [
|
|
429
429
|
"ignore (previous|prior|all) instructions",
|
|
430
430
|
"system:\\s*you are",
|
|
@@ -58,7 +58,7 @@ var { defineClass } = require("./framework-error");
|
|
|
58
58
|
|
|
59
59
|
var MdocError = defineClass("MdocError", { alwaysPermanent: true });
|
|
60
60
|
|
|
61
|
-
var HDR_X5CHAIN = 33;
|
|
61
|
+
var HDR_X5CHAIN = 33;
|
|
62
62
|
var TAG_ENCODED_CBOR = 24; // RFC 8949 §3.4.5.1 embedded-CBOR tag
|
|
63
63
|
// Tags ISO 18013-5 uses in issuer data: tdate(0), epoch(1), embedded
|
|
64
64
|
// CBOR(24), full-date(1004, RFC 8943). Bounded — others are refused.
|
|
@@ -729,7 +729,7 @@ function create(opts) {
|
|
|
729
729
|
exemplar = {
|
|
730
730
|
labels: { trace_id: req.span.traceId, span_id: req.span.spanId },
|
|
731
731
|
value: elapsedSec,
|
|
732
|
-
timestamp: Date.now() / 1000,
|
|
732
|
+
timestamp: Date.now() / 1000,
|
|
733
733
|
};
|
|
734
734
|
} else if (req.trace && req.trace.sampled && req.trace.traceId && req.trace.spanId) {
|
|
735
735
|
// Operators wiring traceparent directly without
|
|
@@ -740,7 +740,7 @@ function create(opts) {
|
|
|
740
740
|
exemplar = {
|
|
741
741
|
labels: { trace_id: req.trace.traceId, span_id: req.trace.spanId },
|
|
742
742
|
value: elapsedSec,
|
|
743
|
-
timestamp: Date.now() / 1000,
|
|
743
|
+
timestamp: Date.now() / 1000,
|
|
744
744
|
};
|
|
745
745
|
}
|
|
746
746
|
try { requestDuration.observe(durLabels, elapsedSec, exemplar); }
|
|
@@ -97,7 +97,7 @@ var CANONICAL_POSITIONS = Object.freeze({
|
|
|
97
97
|
botGuard: 42, // canonical position bucket
|
|
98
98
|
requireAuth: 50, // canonical position bucket
|
|
99
99
|
attachUser: 52, // canonical position bucket
|
|
100
|
-
handler: 60, // allow:raw-time-literal — pipeline position
|
|
100
|
+
handler: 60, // allow:raw-time-literal — pipeline position bucket; coincidental multiple-of-60, C.TIME N/A
|
|
101
101
|
errorHandler: 90, // canonical position bucket
|
|
102
102
|
});
|
|
103
103
|
|
|
@@ -293,7 +293,7 @@ function verifyRrset(opts) {
|
|
|
293
293
|
} else {
|
|
294
294
|
atMs = Date.now();
|
|
295
295
|
}
|
|
296
|
-
var nowSec = Math.floor(atMs / 1000);
|
|
296
|
+
var nowSec = Math.floor(atMs / 1000);
|
|
297
297
|
if (nowSec < (rrsig.inception >>> 0)) throw new DnssecError("dnssec/not-yet-valid", "dnssec.verifyRrset: RRSIG inception is in the future");
|
|
298
298
|
if (nowSec > (rrsig.expiration >>> 0)) throw new DnssecError("dnssec/expired", "dnssec.verifyRrset: RRSIG has expired");
|
|
299
299
|
|
|
@@ -349,7 +349,7 @@ var BASE32HEX = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; // RFC 4648 §7 ext
|
|
|
349
349
|
var TYPE_DS = 43; // IANA RR type DS
|
|
350
350
|
var TYPE_CNAME = 5;
|
|
351
351
|
var NSEC3_HASH_SHA1 = 1; // RFC 5155 §5 — the only registered NSEC3 hash
|
|
352
|
-
var DEFAULT_MAX_NSEC3_ITERATIONS = 150;
|
|
352
|
+
var DEFAULT_MAX_NSEC3_ITERATIONS = 150;
|
|
353
353
|
|
|
354
354
|
// KeyTrap (CVE-2023-50387) amplification caps. A hostile zone can publish
|
|
355
355
|
// many DNSKEYs sharing one 16-bit key tag and many RRSIGs, forcing a
|
|
@@ -716,7 +716,7 @@ async function tlsRptSubmit(report, opts) {
|
|
|
716
716
|
// tlsRpt.recordShape / tlsRpt.submit on the send side.
|
|
717
717
|
|
|
718
718
|
var TLS_RPT_MAX_REPORT_BYTES = C.BYTES.mib(8);
|
|
719
|
-
var TLS_RPT_MAX_POLICIES_PER_REPORT = 1024;
|
|
719
|
+
var TLS_RPT_MAX_POLICIES_PER_REPORT = 1024;
|
|
720
720
|
|
|
721
721
|
function tlsRptParseReport(body, opts) {
|
|
722
722
|
opts = opts || {};
|
|
@@ -837,7 +837,7 @@ function _parseTime(node) {
|
|
|
837
837
|
if (s.length === 13 && s.charAt(12) === "Z") { // UTCTime length per X.690
|
|
838
838
|
// UTCTime YYMMDDhhmmssZ — 50+ → 19xx, else 20xx (RFC 5280 §4.1.2.5).
|
|
839
839
|
year = parseInt(s.slice(0, 2), 10);
|
|
840
|
-
year += year >= 50 ? 1900 : 2000;
|
|
840
|
+
year += year >= 50 ? 1900 : 2000;
|
|
841
841
|
month = parseInt(s.slice(2, 4), 10);
|
|
842
842
|
day = parseInt(s.slice(4, 6), 10);
|
|
843
843
|
hour = parseInt(s.slice(6, 8), 10); // UTCTime hour-byte offsets
|
|
@@ -41,7 +41,7 @@ var TsigError = defineClass("TsigError", { alwaysPermanent: true });
|
|
|
41
41
|
|
|
42
42
|
var TYPE_TSIG = 250; // IANA RR type TSIG
|
|
43
43
|
var CLASS_ANY = 255; // TSIG RRs use CLASS ANY
|
|
44
|
-
var DEFAULT_FUDGE = 300;
|
|
44
|
+
var DEFAULT_FUDGE = 300;
|
|
45
45
|
|
|
46
46
|
// Algorithm name → Node hash. The strong HMAC-SHA-2 family is the safe set;
|
|
47
47
|
// HMAC-MD5 and HMAC-SHA-1 are refused unless allowLegacy (kept only for
|
|
@@ -225,7 +225,7 @@ function sign(message, opts) {
|
|
|
225
225
|
var secret = _secretBuf(opts.secret);
|
|
226
226
|
var fudge = opts.fudge == null ? DEFAULT_FUDGE : opts.fudge;
|
|
227
227
|
if (typeof fudge !== "number" || !isFinite(fudge) || fudge < 0 || fudge > 0xffff) throw new TsigError("tsig/bad-opt", "tsig.sign: fudge must be 0..65535 seconds"); // 16-bit fudge field
|
|
228
|
-
var time = opts.time == null ? Math.floor(Date.now() / 1000) : opts.time;
|
|
228
|
+
var time = opts.time == null ? Math.floor(Date.now() / 1000) : opts.time;
|
|
229
229
|
if (typeof time !== "number" || !isFinite(time) || time < 0) throw new TsigError("tsig/bad-opt", "tsig.sign: time must be a non-negative Unix-seconds number");
|
|
230
230
|
var error = opts.error == null ? 0 : opts.error;
|
|
231
231
|
var otherData = Buffer.isBuffer(opts.otherData) ? opts.otherData : Buffer.alloc(0);
|
|
@@ -379,7 +379,7 @@ function verify(message, opts) {
|
|
|
379
379
|
macValid = timingSafeEqual(rr.mac, expected.slice(0, rr.mac.length));
|
|
380
380
|
}
|
|
381
381
|
|
|
382
|
-
var now = opts.now == null ? Math.floor(Date.now() / 1000) : opts.now;
|
|
382
|
+
var now = opts.now == null ? Math.floor(Date.now() / 1000) : opts.now;
|
|
383
383
|
var timeValid = Math.abs(now - rr.timeSigned) <= rr.fudge;
|
|
384
384
|
|
|
385
385
|
var reason = null;
|
|
@@ -25,11 +25,11 @@ function isValidDateTime(s) {
|
|
|
25
25
|
if (!m) return false;
|
|
26
26
|
var mo = +m[2], d = +m[3], h = +m[4], mi = +m[5], se = +m[6];
|
|
27
27
|
if (mo < 1 || mo > 12 || d < 1 || d > 31 || h > 23 || mi > 59 || se > 60) return false; // allow:raw-time-literal — RFC 3339 field ranges (60 = leap second)
|
|
28
|
-
var days = [31, ((+m[1] % 4 === 0 && +m[1] % 100 !== 0) || +m[1] % 400 === 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
28
|
+
var days = [31, ((+m[1] % 4 === 0 && +m[1] % 100 !== 0) || +m[1] % 400 === 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
29
29
|
if (d > days[mo - 1]) return false;
|
|
30
30
|
var tz = m[8];
|
|
31
31
|
if (tz !== "Z" && tz !== "z") {
|
|
32
|
-
if (+tz.slice(1, 3) > 23 || +tz.slice(4, 6) > 59) return false;
|
|
32
|
+
if (+tz.slice(1, 3) > 23 || +tz.slice(4, 6) > 59) return false;
|
|
33
33
|
}
|
|
34
34
|
return true;
|
|
35
35
|
}
|
|
@@ -105,7 +105,7 @@ var _algorithms = {
|
|
|
105
105
|
// classic bomb shapes (1000:1) while leaving headroom for legitimate
|
|
106
106
|
// text / JSON / XML payloads (which compress 20-50:1 commonly). Per
|
|
107
107
|
// RFC 8460 §5.2 community guidance for TLS-RPT report decompression.
|
|
108
|
-
var DEFAULT_MAX_RATIO = 50;
|
|
108
|
+
var DEFAULT_MAX_RATIO = 50;
|
|
109
109
|
|
|
110
110
|
// Default input cap when operator omits opts.maxCompressedBytes —
|
|
111
111
|
// 4 MiB matches the TLS-RPT receive surface and is a reasonable
|
|
@@ -32,7 +32,7 @@ var { defineClass } = require("./framework-error");
|
|
|
32
32
|
|
|
33
33
|
var StandardWebhooksError = defineClass("StandardWebhooksError", { alwaysPermanent: true });
|
|
34
34
|
|
|
35
|
-
var DEFAULT_TOLERANCE_SEC = 300;
|
|
35
|
+
var DEFAULT_TOLERANCE_SEC = 300;
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* @primitive b.standardWebhooks.sign
|
|
@@ -70,7 +70,7 @@ function sign(opts) {
|
|
|
70
70
|
var id = opts.id || ("msg_" + bCrypto.generateToken(32)); // 32-char id token
|
|
71
71
|
var timestamp = typeof opts.timestamp === "number"
|
|
72
72
|
? opts.timestamp
|
|
73
|
-
: Math.floor(Date.now() / 1000);
|
|
73
|
+
: Math.floor(Date.now() / 1000);
|
|
74
74
|
if (timestamp <= 0 || !isFinite(timestamp)) {
|
|
75
75
|
throw new StandardWebhooksError("standard-webhooks/bad-timestamp",
|
|
76
76
|
"sign: timestamp must be a positive finite integer");
|
|
@@ -148,7 +148,7 @@ function verify(opts) {
|
|
|
148
148
|
numericBounds.requirePositiveFiniteIntIfPresent(opts.toleranceSec, "toleranceSec",
|
|
149
149
|
StandardWebhooksError, "standard-webhooks/bad-tolerance");
|
|
150
150
|
var tolerance = typeof opts.toleranceSec === "number" ? opts.toleranceSec : DEFAULT_TOLERANCE_SEC;
|
|
151
|
-
var nowSec = Math.floor(Date.now() / 1000);
|
|
151
|
+
var nowSec = Math.floor(Date.now() / 1000);
|
|
152
152
|
if (Math.abs(nowSec - ts) > tolerance) {
|
|
153
153
|
throw new StandardWebhooksError("standard-webhooks/timestamp-skew",
|
|
154
154
|
"verify: timestamp skew " + Math.abs(nowSec - ts) + "s exceeds tolerance " + tolerance + "s");
|
|
@@ -71,9 +71,9 @@ var StreamThrottleError = defineClass("StreamThrottleError", { alwaysPermanent:
|
|
|
71
71
|
// (bytes/sec ↔ wait-ms). This is a unit-conversion constant, not a
|
|
72
72
|
// memory cap or protocol-byte literal; the framework's C.TIME / C.BYTES
|
|
73
73
|
// helpers don't apply.
|
|
74
|
-
var MS_PER_SECOND = 1000;
|
|
74
|
+
var MS_PER_SECOND = 1000;
|
|
75
75
|
var NS_PER_MS = 1e6; // ns/ms unit conversion
|
|
76
|
-
var MS_PER_SECOND_HRTIME = 1000;
|
|
76
|
+
var MS_PER_SECOND_HRTIME = 1000;
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
79
|
* @primitive b.streamThrottle.create
|
|
@@ -542,7 +542,7 @@ function parse(input, type, opts) {
|
|
|
542
542
|
|
|
543
543
|
function _serDecimal(v, E) {
|
|
544
544
|
if (!isFinite(v)) throw E("structured-fields/serialize", "cannot serialize a non-finite decimal");
|
|
545
|
-
var n = Math.round(v * 1000) / 1000; // allow:raw-time-literal — RFC 8941
|
|
545
|
+
var n = Math.round(v * 1000) / 1000; // allow:raw-time-literal — RFC 8941 4.1.5 decimal-scale 10^3 rounding; coincidental * 1000, not a duration, C.TIME N/A
|
|
546
546
|
if (Math.abs(Math.trunc(n)).toString().length > 12) throw E("structured-fields/serialize", "decimal integer part exceeds 12 digits"); // §4.1.5 cap
|
|
547
547
|
var s = n.toString();
|
|
548
548
|
if (s.indexOf(".") === -1) s += ".0"; // a Decimal must carry a fractional part
|
|
@@ -81,7 +81,7 @@ var SealPemFileError = defineClass("SealPemFileError", { alwaysPermanent: true }
|
|
|
81
81
|
// doesn't sneak past the watcher. Operators with extremely-quiet
|
|
82
82
|
// renewal cycles can override via opts.pollInterval; the cost of
|
|
83
83
|
// 500ms polling on an idle PEM file is ~2 stat() syscalls/sec.
|
|
84
|
-
var DEFAULT_POLL_MS = 500;
|
|
84
|
+
var DEFAULT_POLL_MS = 500;
|
|
85
85
|
|
|
86
86
|
// PEM files are tiny — 4 KiB for an ECDSA key, ~8 KiB for a 4096-bit
|
|
87
87
|
// RSA key, ~64 KiB for a long cert chain. Cap at 1 MiB so an operator
|
|
@@ -134,7 +134,7 @@ function buildVapidAuthHeader(opts) {
|
|
|
134
134
|
"buildVapidAuthHeader: subscription.endpoint is not a parseable URL");
|
|
135
135
|
}
|
|
136
136
|
var aud = endpointUrl.origin;
|
|
137
|
-
var now = Math.floor(Date.now() / 1000);
|
|
137
|
+
var now = Math.floor(Date.now() / 1000);
|
|
138
138
|
// Inline JWT sign with ES256 — VAPID strictly mandates ECDSA-P256
|
|
139
139
|
// (RFC 8292 §3.1). The framework jwt.sign is PQC-first and refuses
|
|
140
140
|
// ES256 by design; VAPID is a wire-protocol constraint outside
|
|
@@ -955,7 +955,7 @@ function sign(input) {
|
|
|
955
955
|
}
|
|
956
956
|
ts = Math.floor(input.timestamp);
|
|
957
957
|
} else {
|
|
958
|
-
ts = Math.floor(Date.now() / 1000);
|
|
958
|
+
ts = Math.floor(Date.now() / 1000);
|
|
959
959
|
}
|
|
960
960
|
var hex = _hmacSha256Hex(secretBytes, ts + "." + bodyStr);
|
|
961
961
|
return "t=" + ts + ",v1=" + hex;
|
|
@@ -191,7 +191,7 @@ var CLOSE_GRACE_MS = C.TIME.seconds(2);
|
|
|
191
191
|
function _isValidCloseCode(code) {
|
|
192
192
|
if (code === 1004 || code === 1005 || code === 1006 || code === 1015) return false; // RFC 6455 §7.4.2 reserved codes
|
|
193
193
|
if (code >= 1000 && code <= 1011) return true; // allow:raw-time-literal — code is a numeric, not seconds
|
|
194
|
-
if (code >= 3000 && code <= 4999) return true; // allow:raw-time-literal — code
|
|
194
|
+
if (code >= 3000 && code <= 4999) return true; // allow:raw-time-literal — WebSocket close-code range bound (RFC 6455 7.4.2); coincidental multiple-of-60, C.TIME N/A
|
|
195
195
|
return false;
|
|
196
196
|
}
|
|
197
197
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../scripts/release-notes-schema.json",
|
|
3
|
+
"version": "0.14.8",
|
|
4
|
+
"date": "2026-05-30",
|
|
5
|
+
"headline": "Source-comment and codebase-check hygiene, plus a new require-block alignment check; no API or behaviour changes",
|
|
6
|
+
"summary": "Internal lint and comment cleanup with no operator-facing surface change. Several codebase-check comments and one stub helper name that described behaviour the check no longer has are corrected; an unused lint-suppression class and a set of stale duplicate-cluster qualifiers (functions that were since renamed or extracted) are pruned or re-pointed. Fifty-nine `// allow:` markers that named the byte-size or time-literal check on values those checks no longer flag are removed, and twenty self-negating rationales on markers the time check genuinely fires on are rewritten to say why the value coincidentally matches. A new codebase check holds top-of-file require blocks to consistent `=` column alignment, with the files that currently carry drift listed as a migration allowlist. No exported API, error code, wire format, or runtime behaviour changes.",
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"heading": "Changed",
|
|
10
|
+
"items": [
|
|
11
|
+
{
|
|
12
|
+
"title": "Lint-suppression and codebase-check comment cleanup",
|
|
13
|
+
"body": "Corrected codebase-check comments that overstated their check's scope (a duplicate-code threshold described as three files when the advisory threshold is two, a narrowed byte-literal check carrying its pre-narrowing description, and a deferred-scan helper named as though it enforced a guarantee it does not yet provide). Removed an unused lint-suppression class and its one dead in-code marker, and pruned or re-pointed stale duplicate-cluster qualifiers that named functions since renamed or extracted into shared helpers. Removed fifty-nine `// allow:` markers that suppressed nothing, and rewrote twenty self-negating marker rationales (which read \"not seconds\" while sitting on a value the time check fires on) to explain the coincidental match. Source-comment and test hygiene only."
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"heading": "Detectors",
|
|
19
|
+
"items": [
|
|
20
|
+
{
|
|
21
|
+
"title": "Require-block `=` alignment check",
|
|
22
|
+
"body": "A new codebase check flags a top-of-file require block that mixes its `=` column alignment — a fittable line whose `=` drifts off the column the rest of the block shares. Compact single-space blocks are exempt (only blocks that declare alignment intent are checked), as are destructures and long names physically too wide to reach the column, and blank- or comment-separated tiers align independently. The files that currently carry such drift are an explicit migration allowlist, reflowed over time; new code is held to the rule."
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|