@blamejs/core 0.6.60 → 0.6.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,8 @@ upgrading across more than a few patches at a time.
8
8
 
9
9
  ## v0.6.x
10
10
 
11
+ - **0.6.61** (2026-05-03) — `b.safeSchema.string().email()` enforces RFC 5321 §4.5.3.1.3's 254-character cap on the address. Pre-fix the validator was the regex-only `/^[^\s@]+@[^\s@]+\.[^\s@]+$/`, which accepts arbitrarily long matching strings — an operator chaining `.email()` on a request body was open to a DoS shape (50 KB email passes validation, downstream DB writes / log lines unbounded). Now `.email()` rejects with `string/email-too-long` at 255+ chars before the regex even runs, with a message naming the RFC. Operators with a legitimate non-RFC reason for longer addresses skip `.email()` and chain `.regex(custom)` directly. **Tests** — 4 new layer-0 assertions: 254-char address accepts, 255 / 500 char addresses reject, error code `string/email-too-long` exposed for operator handler routing. Smoke 7211 → 7215 / wiki e2e 178 / Linux 85.8s / eslint clean / shellcheck clean.
12
+
11
13
  - **0.6.60** (2026-05-03) — `b.pagination.encodeCursor` correctness fixes for non-plain types in cursor state. The `_canonicalize` walker did `if (typeof === "object") Object.keys(...)`, which silently lost data on three classes of input: **Date** silently encoded as `{}` (Date instances have no own enumerable keys); **Buffer / Uint8Array** silently encoded as `{"0":97,"1":98,…}` (indexed-key serialisation); **circular references** stack-overflowed instead of throwing a clean error. After encode → decode the operator's data was either gone or unrecognisable. The fix: Date now serialises to its ISO string (matches stdlib `JSON.stringify` semantics — round-trips through encode/decode as the ISO string operators expect); Buffer / Uint8Array / Map / Set / RegExp throw `pagination/bad-state` with a message naming the offending constructor and pointing operators at the right conversion (`"convert to a plain primitive (string / number / iso-string) first"`); circular references throw `pagination/bad-state` cleanly via WeakSet cycle detection. **Tests** — 7 new layer-0 assertions: Date round-trip preserved, all 5 non-plain types reject cleanly, circular reference rejects without stack overflow. Smoke 7204→7211 / wiki e2e 178 / Linux 85.3s / eslint clean / shellcheck clean.
12
14
 
13
15
  - **0.6.59** (2026-05-03) — HTTP/2 session teardown deduplication + http-client sweep. v0.6.58's inline `session.close() + session.destroy()` block in `lib/log-stream-otlp-grpc.js` was the right fix for the OTLP-gRPC sink hang, but the same bug class lives in `lib/http-client.js` — the h2 transport pool had 5 call sites running the bare `session.close()` (`_resetTransports`, the ALPN-fallback path, the h2 connect-error path, the h2c connect-error path, the idle-timeout handler, and `_resetForTest`) all of which leak the underlying TCP socket on idle / error / fallback paths in exactly the same way. New `lib/http2-teardown.js` exports `tearDownH2Session(session)` which performs the close()-then-destroy() routine; `lib/http-client.js` and `lib/log-stream-otlp-grpc.js` both import it. The OTLP-gRPC v0.6.58 inline block is removed in favour of the shared helper. **Tests** — verified in a node:24-alpine docker container: smoke 7204 checks in 85.3 seconds. Wiki e2e 178 / eslint clean / shellcheck clean.
@@ -404,6 +404,17 @@ function _stringMethods(schema, spec) {
404
404
  };
405
405
  schema.email = function () {
406
406
  return chain(function (v, p) {
407
+ // RFC 5321 §4.5.3.1.3 — max forward-path is 256 octets including
408
+ // angle brackets, so the address itself is bounded at 254 chars.
409
+ // Without this cap an operator chaining .email() on a request body
410
+ // is open to a DoS shape (50 KB email -> downstream DB writes
411
+ // unbounded string columns, log lines, etc.). Operators with a
412
+ // legitimate non-RFC reason for longer emails skip .email() and
413
+ // chain .regex(custom) directly.
414
+ if (v.length > 254) {
415
+ return _fail(p, "string/email-too-long",
416
+ "must be a valid email address (max 254 chars per RFC 5321)");
417
+ }
407
418
  return EMAIL_RE.test(v) ? { ok: true } :
408
419
  _fail(p, "string/email", "must be a valid email address");
409
420
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.6.60",
3
+ "version": "0.6.61",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
@@ -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:093bc38b-dc67-48ed-87ba-000e374831f6",
5
+ "serialNumber": "urn:uuid:4c584992-71fc-4053-b097-fe6dc1dbb573",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-05-03T13:37:48.709Z",
8
+ "timestamp": "2026-05-03T13:46:27.072Z",
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.6.60",
22
+ "bom-ref": "@blamejs/core@0.6.61",
23
23
  "type": "library",
24
24
  "name": "blamejs",
25
- "version": "0.6.60",
25
+ "version": "0.6.61",
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.6.60",
29
+ "purl": "pkg:npm/%40blamejs/core@0.6.61",
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.6.60",
57
+ "ref": "@blamejs/core@0.6.61",
58
58
  "dependsOn": []
59
59
  }
60
60
  ]