@blamejs/core 0.8.42 → 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 +93 -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
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// wiki-concepts — narrative-shaped framework topics that don't belong
|
|
3
|
+
// to any single primitive. Each @concept block becomes one wiki page,
|
|
4
|
+
// driven by the entries in examples/wiki/wiki.config.js.
|
|
5
|
+
//
|
|
6
|
+
// This file exports nothing. It exists purely as the source of truth
|
|
7
|
+
// for cross-cutting docs. The same JSDoc-comment convention as
|
|
8
|
+
// @primitive blocks: single-line tags first, prose body, multi-line
|
|
9
|
+
// @section blocks last (each becomes an <h2> on the rendered page).
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @concept welcome
|
|
13
|
+
* @title Welcome
|
|
14
|
+
* @nav Welcome
|
|
15
|
+
* @related b.createApp, b.audit, b.crypto, b.session
|
|
16
|
+
*
|
|
17
|
+
* blamejs is a Node framework for operators who care more about what
|
|
18
|
+
* the wire actually does than how loudly the README claims to do it.
|
|
19
|
+
* Zero npm runtime dependencies. Post-quantum crypto from line zero.
|
|
20
|
+
* Sealed-by-default storage. Audit chain on every operator action.
|
|
21
|
+
*
|
|
22
|
+
* Every primitive on this site is documented from its source file —
|
|
23
|
+
* the `@primitive` JSDoc block above each function IS the wiki page
|
|
24
|
+
* section. Drift between code and docs is structurally impossible:
|
|
25
|
+
* the same diff that changes the function changes the documentation.
|
|
26
|
+
*
|
|
27
|
+
* @section Install
|
|
28
|
+
* The framework targets Node Active LTS (24+). No transpilation
|
|
29
|
+
* step, no Babel, no build pipeline. CommonJS, `var`, `node:`
|
|
30
|
+
* builtins, no shipped TypeScript.
|
|
31
|
+
*
|
|
32
|
+
* ```bash
|
|
33
|
+
* npm install @blamejs/core
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* Then in any `.js` file:
|
|
37
|
+
*
|
|
38
|
+
* ```javascript
|
|
39
|
+
* var b = require("@blamejs/core");
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* Every public primitive is accessible from the `b` namespace —
|
|
43
|
+
* `b.crypto`, `b.audit`, `b.session`, `b.uuid`, etc. Browse the
|
|
44
|
+
* API index for the full list, or jump to a concern group from the
|
|
45
|
+
* sidebar.
|
|
46
|
+
*
|
|
47
|
+
* @section First server
|
|
48
|
+
* `b.createApp({ dataDir, routes })` boots the framework with
|
|
49
|
+
* strict CSP, CSRF, origin verification, bot-guard, encrypted
|
|
50
|
+
* sessions, sealed storage, and the audit chain wired into the
|
|
51
|
+
* request lifecycle. Operators who do nothing get the same posture
|
|
52
|
+
* as operators who carefully read every config option.
|
|
53
|
+
*
|
|
54
|
+
* ```javascript
|
|
55
|
+
* var b = require("@blamejs/core");
|
|
56
|
+
*
|
|
57
|
+
* var app = await b.createApp({
|
|
58
|
+
* dataDir: "./data",
|
|
59
|
+
* routes: function (router) {
|
|
60
|
+
* router.get("/", function (req, res) {
|
|
61
|
+
* b.render.htmlString(res, "<h1>Hello from blamejs</h1>");
|
|
62
|
+
* });
|
|
63
|
+
* },
|
|
64
|
+
* });
|
|
65
|
+
*
|
|
66
|
+
* await app.listen({ port: 3000 });
|
|
67
|
+
* // → server listening on :3000 with CSP / CSRF / origin / audit / sealed storage all on.
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* That snippet is a production-posture server. Every default that
|
|
71
|
+
* matters is already on. Read the Concepts pages for the details.
|
|
72
|
+
*
|
|
73
|
+
* @section Sealed storage example
|
|
74
|
+
* Every database column except IDs / timestamps / FK references is
|
|
75
|
+
* sealed at rest by default. The framework's vault wraps each
|
|
76
|
+
* value in a versioned envelope with AAD bound to the row context.
|
|
77
|
+
*
|
|
78
|
+
* ```javascript
|
|
79
|
+
* var b = require("@blamejs/core");
|
|
80
|
+
*
|
|
81
|
+
* await b.db.declareTable({
|
|
82
|
+
* name: "users",
|
|
83
|
+
* columns: { id: "TEXT PRIMARY KEY", email: "TEXT NOT NULL", note: "TEXT" },
|
|
84
|
+
* sealedFields: ["note"],
|
|
85
|
+
* });
|
|
86
|
+
*
|
|
87
|
+
* await b.db.insert("users", { id: b.uuid.v7(), email: "a@b.com", note: "PHI here" });
|
|
88
|
+
* // The `note` column lands as a versioned ciphertext on disk; reads
|
|
89
|
+
* // through b.db transparently decrypt for application code.
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @section Audit chain example
|
|
93
|
+
* Every operator action emits a tamper-evident audit row. The chain
|
|
94
|
+
* is hash-linked and periodically signed with SLH-DSA-SHAKE-256f
|
|
95
|
+
* (FIPS 205 stateless hash signature).
|
|
96
|
+
*
|
|
97
|
+
* ```javascript
|
|
98
|
+
* b.audit.emit({
|
|
99
|
+
* event: "wiki.page.edited",
|
|
100
|
+
* actor: req.user.id,
|
|
101
|
+
* subject: page.slug,
|
|
102
|
+
* outcome: "success",
|
|
103
|
+
* metadata: { from: prev.updatedAt, to: now },
|
|
104
|
+
* });
|
|
105
|
+
* // Returns immediately; the row lands on the audit chain
|
|
106
|
+
* // synchronously, prev_hash linked, before the request response.
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @section How to read this site
|
|
110
|
+
* - **Concepts** — the framework's posture and patterns: security
|
|
111
|
+
* defaults, envelope versioning, validation discipline,
|
|
112
|
+
* compliance postures, modernity posture.
|
|
113
|
+
* - **Reference** — auto-generated tables: every error class, every
|
|
114
|
+
* env var, every CLI command, every vendored dep, the full API
|
|
115
|
+
* index.
|
|
116
|
+
* - **Tools / Validation / etc.** — per-namespace primitive guides,
|
|
117
|
+
* each rendered straight from `@primitive` source comments. The
|
|
118
|
+
* code↔docs link is structural, not aspirational.
|
|
119
|
+
*
|
|
120
|
+
* @section What's next
|
|
121
|
+
* The wiki is in active migration. New namespaces appear in the
|
|
122
|
+
* sidebar as their `@primitive` blocks land in the source. The
|
|
123
|
+
* API index lists every primitive currently documented;
|
|
124
|
+
* undocumented surface still works in code but isn't yet wiki-
|
|
125
|
+
* visible.
|
|
126
|
+
*
|
|
127
|
+
* For framework rules + design decisions read the **Concepts**
|
|
128
|
+
* pages. For runtime configuration read **Reference / Environment
|
|
129
|
+
* variables**. For day-to-day operator tasks read **Reference /
|
|
130
|
+
* CLI commands**.
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @concept security-defaults
|
|
135
|
+
* @title Security defaults
|
|
136
|
+
* @nav Concepts
|
|
137
|
+
* @related b.middleware, b.audit, b.session, b.csrf
|
|
138
|
+
*
|
|
139
|
+
* Every blamejs primitive ships with hostile-input handling,
|
|
140
|
+
* transport hardening, and audit emission already wired into the
|
|
141
|
+
* request lifecycle. Operators who do nothing get the same posture
|
|
142
|
+
* as operators who carefully read every config option.
|
|
143
|
+
*
|
|
144
|
+
* Defaults are *not* opt-in. CSRF, origin verification, bot-guard,
|
|
145
|
+
* sealed storage, encrypted sessions, fetch-metadata enforcement,
|
|
146
|
+
* cookie prefixes (`__Host-` / `__Secure-`), DNS-over-HTTPS, and
|
|
147
|
+
* Trusted Types are wired into `b.createApp()` — not behind config
|
|
148
|
+
* flags an operator might forget to set.
|
|
149
|
+
*
|
|
150
|
+
* @section Why defaults, not config?
|
|
151
|
+
* Frameworks that ship insecure defaults rely on operators reading
|
|
152
|
+
* docs, copying the right snippet, and never breaking that snippet
|
|
153
|
+
* during refactors. Real codebases drift. A bot-guard that ships
|
|
154
|
+
* disabled in the example app gets copied disabled into production.
|
|
155
|
+
*
|
|
156
|
+
* blamejs inverts this: every defense ships ON, and the operator
|
|
157
|
+
* must explicitly disable each with an audited reason. The audit
|
|
158
|
+
* chain captures every disable so a future reviewer can see exactly
|
|
159
|
+
* what was loosened and why.
|
|
160
|
+
*
|
|
161
|
+
* @section If a default trips a test, fix the test
|
|
162
|
+
* The temptation to disable a security default to make a test pass
|
|
163
|
+
* is the single largest source of long-term drift. blamejs's
|
|
164
|
+
* example apps and integration tests run with the production
|
|
165
|
+
* default chain enabled. When CSRF / origin / bot-guard / rate-
|
|
166
|
+
* limit blocks a fixture: send realistic browser headers (Origin,
|
|
167
|
+
* Sec-Fetch-Site, User-Agent) instead of disabling the middleware.
|
|
168
|
+
*
|
|
169
|
+
* @section Strict CSP, no `unsafe-inline`
|
|
170
|
+
* The default Content-Security-Policy drops `'unsafe-inline'` from
|
|
171
|
+
* `style-src` and `script-src`. Inline elements opt in via
|
|
172
|
+
* `cspNonce`; pages with no inline elements need no nonce at all.
|
|
173
|
+
* The default applies to every example app the framework ships.
|
|
174
|
+
*/
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @concept envelope-versioning
|
|
178
|
+
* @title Envelope versioning
|
|
179
|
+
* @nav Concepts
|
|
180
|
+
* @related b.crypto, b.vault, b.audit, b.session
|
|
181
|
+
*
|
|
182
|
+
* Every ciphertext, every signed audit row, every persisted session
|
|
183
|
+
* ships inside a versioned envelope. The version byte is the
|
|
184
|
+
* framework's lever for rolling crypto algorithms forward without
|
|
185
|
+
* breaking a single piece of legacy data on disk.
|
|
186
|
+
*
|
|
187
|
+
* Every primitive that emits crypto bytes (`b.crypto.encryptEnvelope`,
|
|
188
|
+
* `b.vault.seal`, `b.audit.sign`, `b.session.encrypt`, …) writes the
|
|
189
|
+
* same envelope shape: `{ v, alg, kid, fixedInfo, ct, aad }`. Decrypt
|
|
190
|
+
* paths route on `v` + `alg` — old envelopes keep working when the
|
|
191
|
+
* framework rolls forward.
|
|
192
|
+
*
|
|
193
|
+
* @section Key rotation without re-encryption
|
|
194
|
+
* The `kid` field references the key by id, not by value. Operators
|
|
195
|
+
* add a new key (`vault-2026-06`); new envelopes get the new `kid`;
|
|
196
|
+
* old envelopes keep their old `kid` and decrypt against the
|
|
197
|
+
* historical key in the keyring. Background re-encryption is a
|
|
198
|
+
* deliberate operator action, not a hidden migration.
|
|
199
|
+
*
|
|
200
|
+
* @section Algorithm rollover
|
|
201
|
+
* When a new KEM/cipher pair is added (e.g. `x-wing+xchacha`
|
|
202
|
+
* alongside `ml-kem-1024+xchacha`), the new pair becomes the
|
|
203
|
+
* default for fresh envelopes. Decrypt paths still route on `alg`
|
|
204
|
+
* — old envelopes resolve to the old pair via the keyring. The
|
|
205
|
+
* framework refuses to drop a registered algorithm until every
|
|
206
|
+
* on-disk envelope has been re-encrypted to a newer version.
|
|
207
|
+
*
|
|
208
|
+
* @section Why AAD matters
|
|
209
|
+
* Every envelope binds AAD (additional authenticated data) to the
|
|
210
|
+
* ciphertext. The AAD is the row id, the user id, the table name,
|
|
211
|
+
* the request method — whatever context determines whether this
|
|
212
|
+
* ciphertext was meant to be read here. An attacker who copies a
|
|
213
|
+
* ciphertext from row A to row B can't decrypt at row B because
|
|
214
|
+
* the AAD doesn't match. This defends the entire class of replay-
|
|
215
|
+
* style attacks where one user's ciphertext is reused as another's.
|
|
216
|
+
*/
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @concept validation-discipline
|
|
220
|
+
* @title Validation discipline
|
|
221
|
+
* @nav Concepts
|
|
222
|
+
* @related b.audit, b.observability, b.requestHelpers, b.frameworkError
|
|
223
|
+
*
|
|
224
|
+
* Different layers of the framework treat bad input differently — on
|
|
225
|
+
* purpose. A boot-time misconfiguration must crash the process; a
|
|
226
|
+
* hot-path observability sink must drop silent rather than crash the
|
|
227
|
+
* request that triggered it; a defensive request-shape reader must
|
|
228
|
+
* return a sensible default. blamejs picks one of three behaviors per
|
|
229
|
+
* primitive and documents the choice.
|
|
230
|
+
*
|
|
231
|
+
* @section Config-time / entry-point: throw
|
|
232
|
+
* Primitives that receive operator input at boot or app
|
|
233
|
+
* construction throw a `TypeError` on bad input. The operator
|
|
234
|
+
* catches the typo at deploy time, never at request time. Examples:
|
|
235
|
+
* `b.constants.TIME.minutes(n)`, `b.protocolDispatcher.create(opts)`,
|
|
236
|
+
* `b.frameworkError.defineClass(opts)`.
|
|
237
|
+
*
|
|
238
|
+
* @section Hot-path observability sinks: drop silent
|
|
239
|
+
* Primitives that emit on every request — audit, observability,
|
|
240
|
+
* metrics — must never crash the request that triggered them. They
|
|
241
|
+
* wrap their internal validation in `try/catch` and drop the bad
|
|
242
|
+
* call silently. Each is marked "drop-silent — by design" in its
|
|
243
|
+
* docstring. Operators who need to surface drops set
|
|
244
|
+
* `BLAMEJS_OBSERVABILITY_STRICT=1` to promote drops to errors.
|
|
245
|
+
*
|
|
246
|
+
* @section Request-shape readers: return defaults
|
|
247
|
+
* Primitives that read per-request shape (route, headers, query)
|
|
248
|
+
* return a defaulted sensible value rather than throwing on missing
|
|
249
|
+
* or garbage input. A request with no `Origin` header must still
|
|
250
|
+
* resolve *some* answer; throwing here means a request crash for a
|
|
251
|
+
* header the client legitimately omitted.
|
|
252
|
+
*
|
|
253
|
+
* @section Picking consciously
|
|
254
|
+
* Every new primitive picks one tier and documents it. The choice
|
|
255
|
+
* surfaces in the source comment + the JSDoc + the wiki page.
|
|
256
|
+
* Default-by-accident is the bug class this discipline closes.
|
|
257
|
+
*/
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* @concept compliance-postures
|
|
261
|
+
* @title Compliance postures
|
|
262
|
+
* @nav Concepts
|
|
263
|
+
* @related b.compliance, b.dora, b.retention, b.audit
|
|
264
|
+
*
|
|
265
|
+
* Compliance regimes (HIPAA, PCI-DSS, GDPR, SOC 2, DORA, NIS 2, CRA,
|
|
266
|
+
* etc.) overlap heavily — they share retention floors, encryption
|
|
267
|
+
* floors, audit floors, breach-notification windows. blamejs collapses
|
|
268
|
+
* the overlap into a **union-of-bars** strategy: pick every regime
|
|
269
|
+
* that applies, and the framework computes the strictest setting
|
|
270
|
+
* that satisfies all of them.
|
|
271
|
+
*
|
|
272
|
+
* @section Setting a posture
|
|
273
|
+
* `b.compliance.set({ postures: ["hipaa", "pci-dss", "gdpr",
|
|
274
|
+
* "soc2"] })`. The call cascades into every framework primitive
|
|
275
|
+
* that exposes a posture-aware default: retention floors, audit
|
|
276
|
+
* signing requirements, password complexity, session lifetimes,
|
|
277
|
+
* log redaction, mTLS profiles, TLS minimums.
|
|
278
|
+
*
|
|
279
|
+
* @section Conflict resolution
|
|
280
|
+
* When two postures disagree, the strictest setting wins. SOC 2's
|
|
281
|
+
* 1-year audit-retention floor is shorter than HIPAA's 6-year, so
|
|
282
|
+
* joint posture takes 6 years. Documented exceptions list the
|
|
283
|
+
* specific cases where strictest-wins doesn't apply.
|
|
284
|
+
*
|
|
285
|
+
* @section Reading the resolved posture
|
|
286
|
+
* `b.compliance.current()` returns the resolved bundle:
|
|
287
|
+
* `{ active: ["hipaa","pci-dss"], retentionFloorDays: 2190,
|
|
288
|
+
* auditSigningRequired: true, … }`. Every primitive reads this at
|
|
289
|
+
* boot to compute its tightened defaults. Operators inspect the
|
|
290
|
+
* resolved bundle to confirm the cascade matches expectations.
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* @concept modernity-posture
|
|
295
|
+
* @title Modernity posture
|
|
296
|
+
* @nav Concepts
|
|
297
|
+
* @related b.crypto, b.network, b.auth, b.middleware
|
|
298
|
+
*
|
|
299
|
+
* blamejs anchors its defaults to the *current* bar — the active
|
|
300
|
+
* LTS, the current TLS minimum, the post-quantum primitives
|
|
301
|
+
* standardized today — not the broadest-compatible older option.
|
|
302
|
+
* Frameworks that pin to "what most people support" entrench
|
|
303
|
+
* yesterday's posture as tomorrow's default.
|
|
304
|
+
*
|
|
305
|
+
* @section Node.js: Active LTS, no transpilation
|
|
306
|
+
* The framework runs on Node Active LTS as shipped — currently
|
|
307
|
+
* Node 24+. No Babel, no TypeScript build, no transpilation step.
|
|
308
|
+
* Every transpilation hop is a supply-chain hop and a debug-loss
|
|
309
|
+
* hop. CommonJS, `var`, `node:`-prefixed builtins.
|
|
310
|
+
*
|
|
311
|
+
* @section TLS 1.3 minimum, no fallbacks
|
|
312
|
+
* Inbound and outbound TLS both refuse anything below 1.3. ALPN
|
|
313
|
+
* announces `h2` first; HTTP/1.1 only on opt-in. ECH is enabled
|
|
314
|
+
* when the OS / Node version supports it; SVCB / HTTPS records
|
|
315
|
+
* are honored on outbound DNS. OCSP stapling is required on
|
|
316
|
+
* inbound listeners; CT SCTs are validated on outbound dialing.
|
|
317
|
+
*
|
|
318
|
+
* @section Post-quantum first
|
|
319
|
+
* Default symmetric: **XChaCha20-Poly1305** (extended-nonce, 256-
|
|
320
|
+
* bit key). Default KEM: **ML-KEM-1024 hybridized with X25519**
|
|
321
|
+
* (FIPS 203 + classical safety net). Default KDF: **SHAKE256**.
|
|
322
|
+
* Default signature: **SLH-DSA-SHAKE-256f** for audit; **ML-DSA**
|
|
323
|
+
* for outbound where size matters. No AES-GCM, SHA-256, P-256,
|
|
324
|
+
* or classical-only ECDH as defaults.
|
|
325
|
+
*
|
|
326
|
+
* @section Passwords: Argon2id only
|
|
327
|
+
* The framework refuses to verify a hash that doesn't start with
|
|
328
|
+
* `$argon2id$`. No PBKDF2 or bcrypt fallback. Operators with
|
|
329
|
+
* legacy hashes migrate at first login (the verify path detects +
|
|
330
|
+
* re-hashes).
|
|
331
|
+
*
|
|
332
|
+
* @section LTS calendar
|
|
333
|
+
* Every major version ships with a 24-month security-only patch
|
|
334
|
+
* calendar. The calendar is published at blamejs.com/lts with the
|
|
335
|
+
* next-major's breaking-change list visible during the deprecation
|
|
336
|
+
* window. Deprecation warnings ship at least one minor before
|
|
337
|
+
* removal. No silent breaking changes in minor versions.
|
|
338
|
+
*/
|