@blamejs/core 0.7.91 → 0.7.92
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/observability.js +25 -0
- package/lib/retention.js +11 -5
- 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.92** (2026-05-06) — Retention floors + observability semconv expansion. **`b.retention.complianceFloor(<posture>, candidateMs)`** now recognizes `nis2` (3 years — NIS2 Art. 23 incident reporting), `cra` (5 years — CRA Art. 14 vulnerability handling logs), `lgpd-br` (5 years — Brazil fiscal record minimum + LGPD Art. 16), `appi-jp` (3 years — Japan APPI handler-of-record), `pdpa-sg` (1 year — PDPA breach notification audit trail), and `uk-gdpr` (6 years — UK ICO guidance + statutory limit alignment). `gdpr` continues to have no fixed minimum (Art. 5(1)(e) is "no longer than necessary" — operator-driven). **`b.observability.SEMCONV`** gains RPC attributes (`RPC_SYSTEM` / `RPC_SERVICE` / `RPC_METHOD` / `RPC_GRPC_STATUS_CODE`), additional messaging keys (`MESSAGING_CLIENT_ID` / `MESSAGING_MESSAGE_ID` / `MESSAGING_DESTINATION_PARTITION_ID` / `MESSAGING_BATCH_MESSAGE_COUNT`), network transport (`NETWORK_TRANSPORT` / `NETWORK_CONNECTION_TYPE`), process / runtime identification (`PROCESS_PID` / `PROCESS_RUNTIME_NAME` / `PROCESS_RUNTIME_VERSION`), service identification (`SERVICE_NAME` / `SERVICE_VERSION` / `SERVICE_INSTANCE_ID`), and telemetry SDK self-id (`TELEMETRY_SDK_NAME` / `TELEMETRY_SDK_LANGUAGE` / `TELEMETRY_SDK_VERSION`). Operators wiring the framework's tap into a gRPC-fronted OTel collector or an outbox-fed Kafka topic now reference the canonical attribute names directly without an aliasing table on their side.
|
|
12
|
+
|
|
11
13
|
- **0.7.91** (2026-05-06) — Compliance-posture vocabulary expanded + OpenTelemetry semantic-convention attribute table. **`b.compliance.set(<posture>)`** now accepts thirteen new posture names: `wmhmda` (Washington My Health My Data Act), `bipa` (Illinois Biometric Information Privacy Act), `ccpa` (California Consumer Privacy Act), `nis2` (EU NIS2 Directive), `cra` (EU Cyber Resilience Act), `ai-act` (EU AI Act), `lgpd-br` (Brazil LGPD), `pipl-cn` (China PIPL), `appi-jp` (Japan APPI), `pdpa-sg` (Singapore PDPA), `pipeda-ca` (Canada PIPEDA), `uk-gdpr` (UK GDPR). Existing `hipaa` / `pci-dss` / `gdpr` / `soc2` / `dora` / `sox` continue to work. Postures map to per-primitive defaults via the existing compliancePosture opt on guards, retention, dora, etc. — operators set the deployment-wide posture once and primitives that key off it pick up the right defaults. **`b.observability.SEMCONV`** — frozen attribute-name table tracking the OpenTelemetry semantic-convention stable namespace (1.27+). HTTP server attributes (`http.request.method`, `http.response.status_code`, `http.route`, `server.address`, `client.address`), URL (`url.full`, `url.path`, `url.scheme`), database (`db.system`, `db.namespace`, `db.operation.name`, `db.query.text`), messaging (`messaging.system`, `messaging.destination.name`), auth (`user.id`, `session.id`), errors (`error.type`, `exception.type`, `exception.message`). Operators wiring the framework's tap into an OTel SDK reference these constants instead of hand-rolling the names — no aliasing table on the operator side, and string typos throw at access time instead of producing mis-named span attributes that the OTel collector silently drops.
|
|
12
14
|
|
|
13
15
|
- **0.7.90** (2026-05-06) — `b.outbox` — transactional outbox primitive for at-least-once event publication without distributed transactions. **`b.outbox.create({ externalDb, table, publisher, ... })`** returns an outbox instance with three core operations: `enqueue(event, txn)` writes the outbox row inside the operator's transaction (using the `txClient` returned by `b.externalDb.transaction`), `start()` spins a polling publisher worker that claims rows via `SELECT ... FOR UPDATE SKIP LOCKED` (Postgres) and dispatches to the operator-supplied async `publisher(event)` callback, `stop()` gracefully shuts the worker down. Failed publishes retry with exponential backoff (`retryBackoff: { initialMs, maxMs, factor }`); rows that exceed `maxAttempts` are marked `'dead'` for operator triage and an `system.outbox.deadletter` audit event fires. Schema is operator-managed: `outbox.declareSchema(externalDb)` runs an idempotent `CREATE TABLE IF NOT EXISTS ... (id, topic, payload, key, headers, enqueued_at, next_attempt_at, published_at, attempts, last_error, status)` + a partial index on `(next_attempt_at) WHERE status = 'pending'`. `pendingCount()` / `deadCount()` expose the queue depth + DLQ depth for operator dashboards. Observability events on every state transition (`outbox.enqueued` / `outbox.published` / `outbox.publish-failed` / `outbox.dead-letter`).
|
package/lib/observability.js
CHANGED
|
@@ -195,6 +195,31 @@ var SEMCONV = Object.freeze({
|
|
|
195
195
|
EXCEPTION_TYPE: "exception.type",
|
|
196
196
|
EXCEPTION_MESSAGE: "exception.message",
|
|
197
197
|
EXCEPTION_STACKTRACE: "exception.stacktrace",
|
|
198
|
+
// RPC
|
|
199
|
+
RPC_SYSTEM: "rpc.system",
|
|
200
|
+
RPC_SERVICE: "rpc.service",
|
|
201
|
+
RPC_METHOD: "rpc.method",
|
|
202
|
+
RPC_GRPC_STATUS_CODE: "rpc.grpc.status_code",
|
|
203
|
+
// Messaging — additional client/server attrs
|
|
204
|
+
MESSAGING_CLIENT_ID: "messaging.client.id",
|
|
205
|
+
MESSAGING_MESSAGE_ID: "messaging.message.id",
|
|
206
|
+
MESSAGING_DESTINATION_PARTITION_ID: "messaging.destination.partition.id",
|
|
207
|
+
MESSAGING_BATCH_MESSAGE_COUNT: "messaging.batch.message_count",
|
|
208
|
+
// Network — transport / connection state
|
|
209
|
+
NETWORK_TRANSPORT: "network.transport",
|
|
210
|
+
NETWORK_CONNECTION_TYPE: "network.connection.type",
|
|
211
|
+
// Process / runtime
|
|
212
|
+
PROCESS_PID: "process.pid",
|
|
213
|
+
PROCESS_RUNTIME_NAME: "process.runtime.name",
|
|
214
|
+
PROCESS_RUNTIME_VERSION: "process.runtime.version",
|
|
215
|
+
// Service identification
|
|
216
|
+
SERVICE_NAME: "service.name",
|
|
217
|
+
SERVICE_VERSION: "service.version",
|
|
218
|
+
SERVICE_INSTANCE_ID: "service.instance.id",
|
|
219
|
+
// Telemetry SDK self-identification
|
|
220
|
+
TELEMETRY_SDK_NAME: "telemetry.sdk.name",
|
|
221
|
+
TELEMETRY_SDK_LANGUAGE: "telemetry.sdk.language",
|
|
222
|
+
TELEMETRY_SDK_VERSION: "telemetry.sdk.version",
|
|
198
223
|
});
|
|
199
224
|
|
|
200
225
|
module.exports = {
|
package/lib/retention.js
CHANGED
|
@@ -445,11 +445,17 @@ function create(opts) {
|
|
|
445
445
|
// SOC 2 (CC1–CC9) — 1 year typical; auditor-driven
|
|
446
446
|
// DORA Art. 17 (incident logs) — 5 years
|
|
447
447
|
var COMPLIANCE_RETENTION_FLOOR_MS = Object.freeze({
|
|
448
|
-
"pci-dss": C.TIME.days(365),
|
|
449
|
-
"hipaa": C.TIME.days(365 * 6),
|
|
450
|
-
"sox": C.TIME.days(365 * 7),
|
|
451
|
-
"soc2": C.TIME.days(365),
|
|
452
|
-
"dora": C.TIME.days(365 * 5),
|
|
448
|
+
"pci-dss": C.TIME.days(365), // 12 months — PCI-DSS §10.7.1
|
|
449
|
+
"hipaa": C.TIME.days(365 * 6), // 6 years — 45 CFR §164.316(b)(2)(i)
|
|
450
|
+
"sox": C.TIME.days(365 * 7), // 7 years — Sarbanes-Oxley §802
|
|
451
|
+
"soc2": C.TIME.days(365), // 1 year — typical SOC 2 audit window
|
|
452
|
+
"dora": C.TIME.days(365 * 5), // 5 years — DORA Article 17 incident logs
|
|
453
|
+
"nis2": C.TIME.days(365 * 3), // 3 years — NIS2 Art. 23 incident reporting
|
|
454
|
+
"cra": C.TIME.days(365 * 5), // 5 years — CRA Art. 14 vulnerability handling logs
|
|
455
|
+
"lgpd-br": C.TIME.days(365 * 5), // 5 years — Brazil LGPD Art. 16 + fiscal-record minimum
|
|
456
|
+
"appi-jp": C.TIME.days(365 * 3), // 3 years — Japan APPI handler-of-record requirement
|
|
457
|
+
"pdpa-sg": C.TIME.days(365 * 1), // 1 year — PDPA breach-notification audit trail
|
|
458
|
+
"uk-gdpr": C.TIME.days(365 * 6), // 6 years — UK ICO guidance, statutory limit alignment
|
|
453
459
|
});
|
|
454
460
|
|
|
455
461
|
// Operator passes a posture name + a candidate ttlMs; returns the
|
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:3879cfe5-c335-4b6c-9133-99b33bbd5666",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-05-
|
|
8
|
+
"timestamp": "2026-05-06T08:05:33.048Z",
|
|
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.92",
|
|
23
23
|
"type": "library",
|
|
24
24
|
"name": "blamejs",
|
|
25
|
-
"version": "0.7.
|
|
25
|
+
"version": "0.7.92",
|
|
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.92",
|
|
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.92",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|