@blamejs/core 0.14.27 → 0.15.0
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/README.md +2 -2
- package/index.js +4 -0
- package/lib/ai-content-detect.js +9 -10
- package/lib/api-key.js +107 -74
- package/lib/atomic-file.js +29 -1
- package/lib/audit-chain.js +47 -11
- package/lib/audit-sign.js +77 -2
- package/lib/audit-tools.js +79 -51
- package/lib/audit.js +218 -100
- package/lib/backup/index.js +13 -10
- package/lib/break-glass.js +202 -144
- package/lib/cache.js +174 -105
- package/lib/chain-writer.js +38 -16
- package/lib/cli.js +19 -14
- package/lib/cluster-provider-db.js +130 -104
- package/lib/cluster-storage.js +119 -22
- package/lib/cluster.js +119 -71
- package/lib/compliance.js +22 -0
- package/lib/consent.js +73 -24
- package/lib/constants.js +16 -11
- package/lib/crypto-field.js +387 -91
- package/lib/db-declare-row-policy.js +35 -22
- package/lib/db-file-lifecycle.js +3 -2
- package/lib/db-query.js +497 -255
- package/lib/db-schema.js +209 -44
- package/lib/db.js +176 -95
- package/lib/external-db-migrate.js +229 -139
- package/lib/external-db.js +25 -15
- package/lib/framework-error.js +11 -0
- package/lib/framework-files.js +73 -0
- package/lib/framework-schema.js +695 -394
- package/lib/gate-contract.js +596 -1
- package/lib/guard-agent-registry.js +26 -44
- package/lib/guard-all.js +1 -0
- package/lib/guard-auth.js +42 -112
- package/lib/guard-cidr.js +33 -154
- package/lib/guard-csv.js +46 -113
- package/lib/guard-domain.js +34 -157
- package/lib/guard-dsn.js +27 -43
- package/lib/guard-email.js +47 -69
- package/lib/guard-envelope.js +19 -32
- package/lib/guard-event-bus-payload.js +24 -42
- package/lib/guard-event-bus-topic.js +25 -43
- package/lib/guard-filename.js +42 -106
- package/lib/guard-graphql.js +42 -123
- package/lib/guard-html.js +53 -108
- package/lib/guard-idempotency-key.js +24 -42
- package/lib/guard-image.js +46 -103
- package/lib/guard-imap-command.js +18 -32
- package/lib/guard-jmap.js +16 -30
- package/lib/guard-json.js +38 -108
- package/lib/guard-jsonpath.js +38 -171
- package/lib/guard-jwt.js +49 -179
- package/lib/guard-list-id.js +25 -41
- package/lib/guard-list-unsubscribe.js +27 -43
- package/lib/guard-mail-compose.js +24 -42
- package/lib/guard-mail-move.js +26 -44
- package/lib/guard-mail-query.js +28 -46
- package/lib/guard-mail-reply.js +24 -42
- package/lib/guard-mail-sieve.js +24 -42
- package/lib/guard-managesieve-command.js +17 -31
- package/lib/guard-markdown.js +37 -104
- package/lib/guard-message-id.js +26 -45
- package/lib/guard-mime.js +39 -151
- package/lib/guard-oauth.js +54 -135
- package/lib/guard-pdf.js +45 -101
- package/lib/guard-pop3-command.js +21 -31
- package/lib/guard-posture-chain.js +24 -42
- package/lib/guard-regex.js +33 -107
- package/lib/guard-saga-config.js +24 -42
- package/lib/guard-shell.js +42 -172
- package/lib/guard-smtp-command.js +48 -54
- package/lib/guard-snapshot-envelope.js +24 -42
- package/lib/guard-sql.js +1491 -0
- package/lib/guard-stream-args.js +24 -43
- package/lib/guard-svg.js +47 -65
- package/lib/guard-template.js +35 -172
- package/lib/guard-tenant-id.js +26 -45
- package/lib/guard-time.js +32 -154
- package/lib/guard-trace-context.js +25 -44
- package/lib/guard-uuid.js +32 -153
- package/lib/guard-xml.js +38 -113
- package/lib/guard-yaml.js +51 -163
- package/lib/http-client.js +14 -0
- package/lib/inbox.js +120 -107
- package/lib/legal-hold.js +107 -50
- package/lib/log-stream-cloudwatch.js +47 -31
- package/lib/log-stream-otlp.js +32 -18
- package/lib/mail-crypto-smime.js +2 -6
- package/lib/mail-greylist.js +2 -6
- package/lib/mail-helo.js +2 -6
- package/lib/mail-journal.js +85 -64
- package/lib/mail-rbl.js +2 -6
- package/lib/mail-scan.js +2 -6
- package/lib/mail-spam-score.js +2 -6
- package/lib/mail-store.js +287 -154
- package/lib/middleware/fetch-metadata.js +17 -7
- package/lib/middleware/idempotency-key.js +54 -38
- package/lib/middleware/rate-limit.js +102 -32
- package/lib/middleware/security-headers.js +21 -5
- package/lib/migrations.js +108 -66
- package/lib/network-heartbeat.js +7 -0
- package/lib/nonce-store.js +31 -9
- package/lib/object-store/azure-blob-bucket-ops.js +9 -4
- package/lib/object-store/azure-blob.js +31 -3
- package/lib/object-store/sigv4.js +10 -0
- package/lib/outbox.js +136 -82
- package/lib/pqc-agent.js +44 -0
- package/lib/pubsub-cluster.js +42 -20
- package/lib/queue-local.js +202 -139
- package/lib/queue-redis.js +9 -1
- package/lib/queue-sqs.js +6 -0
- package/lib/retention.js +82 -39
- package/lib/safe-dns.js +29 -45
- package/lib/safe-ical.js +18 -33
- package/lib/safe-icap.js +27 -43
- package/lib/safe-sieve.js +21 -40
- package/lib/safe-sql.js +124 -3
- package/lib/safe-vcard.js +18 -33
- package/lib/scheduler.js +35 -12
- package/lib/seeders.js +122 -74
- package/lib/session-stores.js +42 -14
- package/lib/session.js +109 -72
- package/lib/sql.js +3885 -0
- package/lib/static.js +45 -7
- package/lib/subject.js +55 -17
- package/lib/vault/index.js +3 -2
- package/lib/vault/passphrase-ops.js +3 -2
- package/lib/vault/rotate.js +104 -64
- package/lib/vendor-data.js +2 -0
- package/lib/websocket.js +16 -0
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/guard-pdf.js
CHANGED
|
@@ -384,12 +384,7 @@ function sanitize(input, opts) {
|
|
|
384
384
|
throw _err("pdf.bad-input", "sanitize requires metadata object");
|
|
385
385
|
}
|
|
386
386
|
var issues = _detectIssues(input, opts);
|
|
387
|
-
|
|
388
|
-
if (issues[i].severity === "critical" || issues[i].severity === "high") {
|
|
389
|
-
throw _err(issues[i].ruleId || "pdf.refused",
|
|
390
|
-
"guardPdf.sanitize: " + issues[i].snippet);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
387
|
+
gateContract.throwOnRefusalSeverity(issues, { errorClass: GuardPdfError, codePrefix: "pdf" });
|
|
393
388
|
return input;
|
|
394
389
|
}
|
|
395
390
|
|
|
@@ -449,69 +444,11 @@ function gate(opts) {
|
|
|
449
444
|
});
|
|
450
445
|
}
|
|
451
446
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
* @related b.guardPdf.compliancePosture, b.guardPdf.gate
|
|
458
|
-
*
|
|
459
|
-
* Resolve a named profile against the guard's PROFILES catalog and
|
|
460
|
-
* return the merged options bag. Throws
|
|
461
|
-
* `GuardPdfError("pdf.bad-profile")` on unknown name.
|
|
462
|
-
*
|
|
463
|
-
* @opts
|
|
464
|
-
* profile: "strict"|"balanced"|"permissive",
|
|
465
|
-
*
|
|
466
|
-
* @example
|
|
467
|
-
* var resolved = b.guardPdf.buildProfile({ profile: "strict" });
|
|
468
|
-
* resolved.javascriptPolicy; // → "reject"
|
|
469
|
-
* resolved.maxPageCount; // → 500
|
|
470
|
-
*/
|
|
471
|
-
var buildProfile = gateContract.makeProfileBuilder(PROFILES);
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* @primitive b.guardPdf.compliancePosture
|
|
475
|
-
* @signature b.guardPdf.compliancePosture(name)
|
|
476
|
-
* @since 0.7.13
|
|
477
|
-
* @status stable
|
|
478
|
-
* @compliance hipaa, pci-dss, gdpr, soc2
|
|
479
|
-
* @related b.guardPdf.gate, b.guardPdf.buildProfile
|
|
480
|
-
*
|
|
481
|
-
* Return the option overlay for a named compliance posture
|
|
482
|
-
* (`"hipaa"` / `"pci-dss"` / `"gdpr"` / `"soc2"`). Throws
|
|
483
|
-
* `GuardPdfError("pdf.bad-posture")` on unknown name.
|
|
484
|
-
*
|
|
485
|
-
* @example
|
|
486
|
-
* var posture = b.guardPdf.compliancePosture("hipaa");
|
|
487
|
-
* posture.javascriptPolicy; // → "reject"
|
|
488
|
-
* posture.forensicSnippetBytes; // → 512
|
|
489
|
-
*/
|
|
490
|
-
function compliancePosture(name) {
|
|
491
|
-
return gateContract.lookupCompliancePosture(name, COMPLIANCE_POSTURES,
|
|
492
|
-
_err, "pdf");
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
var _pdfRulePacks = gateContract.makeRulePackLoader(GuardPdfError, "pdf");
|
|
496
|
-
/**
|
|
497
|
-
* @primitive b.guardPdf.loadRulePack
|
|
498
|
-
* @signature b.guardPdf.loadRulePack(pack)
|
|
499
|
-
* @since 0.7.13
|
|
500
|
-
* @status stable
|
|
501
|
-
* @related b.guardPdf.gate
|
|
502
|
-
*
|
|
503
|
-
* Register an operator-supplied rule pack with the guard-pdf
|
|
504
|
-
* registry. Throws `GuardPdfError("pdf.bad-opt")` when `pack` is
|
|
505
|
-
* missing or `pack.id` is not a non-empty string.
|
|
506
|
-
*
|
|
507
|
-
* @example
|
|
508
|
-
* var pack = b.guardPdf.loadRulePack({
|
|
509
|
-
* id: "kb-2026-pdf",
|
|
510
|
-
* extraMaxPageCount: 200,
|
|
511
|
-
* });
|
|
512
|
-
* pack.id; // → "kb-2026-pdf"
|
|
513
|
-
*/
|
|
514
|
-
var loadRulePack = _pdfRulePacks.load;
|
|
447
|
+
// buildProfile / compliancePosture / loadRulePack are assembled by
|
|
448
|
+
// gateContract.defineGuard below (makeProfileBuilder(PROFILES) /
|
|
449
|
+
// lookupCompliancePosture(_, COMPLIANCE_POSTURES) / makeRulePackLoader).
|
|
450
|
+
// Their wiki sections render from the single-sourced @abiTemplate blocks
|
|
451
|
+
// in gate-contract.js, instantiated per guard by the page generator.
|
|
515
452
|
|
|
516
453
|
/**
|
|
517
454
|
* @primitive b.guardPdf.inspectMagic
|
|
@@ -535,35 +472,42 @@ function inspectMagic(bytes) {
|
|
|
535
472
|
return _hasPdfMagic(bytes);
|
|
536
473
|
}
|
|
537
474
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
475
|
+
// ---- adaptive integration-test fixtures (consumed by layer-5 host harness) ----
|
|
476
|
+
var INTEGRATION_FIXTURES = Object.freeze({
|
|
477
|
+
kind: "metadata",
|
|
478
|
+
benignBytes: Buffer.from([0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E, 0x37]), // %PDF-1.7
|
|
479
|
+
hostileBytes: Buffer.from([0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E, 0x37]),
|
|
480
|
+
benignMetadata: {
|
|
481
|
+
bytes: Buffer.from([0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E, 0x37]),
|
|
482
|
+
hasJavaScript: false, hasOpenAction: false, hasLaunchAction: false,
|
|
483
|
+
hasEmbeddedFiles: false, isEncrypted: false, pageCount: 1,
|
|
484
|
+
},
|
|
485
|
+
hostileMetadata: {
|
|
486
|
+
bytes: Buffer.from([0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E, 0x37]),
|
|
487
|
+
// Hostile: JavaScript action — universal refuse (RCE class).
|
|
488
|
+
hasJavaScript: true,
|
|
489
|
+
},
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// Assembled from the gate-contract guard factory: error class, registry
|
|
493
|
+
// exports (NAME / KIND / INTEGRATION_FIXTURES), buildProfile /
|
|
494
|
+
// compliancePosture / loadRulePack wiring, plus the per-guard inspection
|
|
495
|
+
// surface (validate / sanitize / gate) and the pdf extra (inspectMagic)
|
|
496
|
+
// passed through verbatim. KIND="metadata" is a custom kind, so the bespoke
|
|
497
|
+
// `gate` (operator-feeds-metadata ctx.metadata reader) is REQUIRED and
|
|
498
|
+
// carries the JavaScript / launch-action / embedded-file chain unchanged.
|
|
499
|
+
module.exports = gateContract.defineGuard({
|
|
500
|
+
name: "pdf",
|
|
501
|
+
kind: "metadata",
|
|
502
|
+
errorClass: GuardPdfError,
|
|
503
|
+
profiles: PROFILES,
|
|
504
|
+
defaults: DEFAULTS,
|
|
505
|
+
postures: COMPLIANCE_POSTURES,
|
|
506
|
+
integrationFixtures: INTEGRATION_FIXTURES,
|
|
507
|
+
validate: validate,
|
|
508
|
+
sanitize: sanitize,
|
|
509
|
+
gate: gate,
|
|
510
|
+
extra: {
|
|
511
|
+
inspectMagic: inspectMagic,
|
|
512
|
+
},
|
|
513
|
+
});
|
|
@@ -74,11 +74,16 @@
|
|
|
74
74
|
*/
|
|
75
75
|
|
|
76
76
|
var { defineClass } = require("./framework-error");
|
|
77
|
+
var gateContract = require("./gate-contract");
|
|
77
78
|
|
|
78
79
|
var GuardPop3CommandError = defineClass("GuardPop3CommandError", { alwaysPermanent: true });
|
|
79
80
|
|
|
80
81
|
var DEFAULT_PROFILE = "strict";
|
|
81
82
|
|
|
83
|
+
// COMPLIANCE_POSTURES is referenced by validate() below (posture → profile
|
|
84
|
+
// name) and re-exported through defineParser; declared up top so validate
|
|
85
|
+
// can read it before the module-exports assembly at the foot of the file.
|
|
86
|
+
|
|
82
87
|
var PROFILES = Object.freeze({
|
|
83
88
|
strict: {
|
|
84
89
|
maxLineBytes: 255, // RFC 2449 §4 cap
|
|
@@ -103,12 +108,7 @@ var PROFILES = Object.freeze({
|
|
|
103
108
|
},
|
|
104
109
|
});
|
|
105
110
|
|
|
106
|
-
var COMPLIANCE_POSTURES =
|
|
107
|
-
hipaa: "strict",
|
|
108
|
-
"pci-dss": "strict",
|
|
109
|
-
gdpr: "strict",
|
|
110
|
-
soc2: "strict",
|
|
111
|
-
});
|
|
111
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
112
112
|
|
|
113
113
|
// POP3 verbs per RFC 1939 §6 + RFC 2449 §5 + RFC 2595 §4 + RFC 5034.
|
|
114
114
|
var KNOWN_VERBS = Object.freeze({
|
|
@@ -290,28 +290,18 @@ function validate(line, opts) {
|
|
|
290
290
|
return { verb: verb, args: args };
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
module.exports = {
|
|
310
|
-
validate: validate,
|
|
311
|
-
compliancePosture: compliancePosture,
|
|
312
|
-
PROFILES: PROFILES,
|
|
313
|
-
COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
|
|
314
|
-
KNOWN_VERBS: KNOWN_VERBS,
|
|
315
|
-
ZERO_ARG_VERBS: ZERO_ARG_VERBS,
|
|
316
|
-
GuardPop3CommandError: GuardPop3CommandError,
|
|
317
|
-
};
|
|
293
|
+
// compliancePosture is assembled by gateContract.defineParser below; its
|
|
294
|
+
// wiki section renders from the single-sourced @abiTemplate (defineParser)
|
|
295
|
+
// block in gate-contract.js, instantiated for this guard by the page
|
|
296
|
+
// generator.
|
|
297
|
+
module.exports = gateContract.defineParser({
|
|
298
|
+
name: "pop3-command",
|
|
299
|
+
entry: validate,
|
|
300
|
+
errorClass: GuardPop3CommandError,
|
|
301
|
+
profiles: PROFILES,
|
|
302
|
+
postures: COMPLIANCE_POSTURES,
|
|
303
|
+
extra: {
|
|
304
|
+
KNOWN_VERBS: KNOWN_VERBS,
|
|
305
|
+
ZERO_ARG_VERBS: ZERO_ARG_VERBS,
|
|
306
|
+
},
|
|
307
|
+
});
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
var { defineClass } = require("./framework-error");
|
|
29
|
+
var gateContract = require("./gate-contract");
|
|
29
30
|
|
|
30
31
|
var GuardPostureChainError = defineClass("GuardPostureChainError", { alwaysPermanent: true });
|
|
31
32
|
|
|
@@ -37,11 +38,14 @@ var PROFILES = Object.freeze({
|
|
|
37
38
|
permissive: { maxHops: 128, maxHopBytes: 256, maxRegimes: 64 },
|
|
38
39
|
});
|
|
39
40
|
|
|
40
|
-
var COMPLIANCE_POSTURES =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
42
|
+
|
|
43
|
+
var _resolveProfile = gateContract.makeProfileResolver({
|
|
44
|
+
profiles: PROFILES,
|
|
45
|
+
postures: COMPLIANCE_POSTURES,
|
|
46
|
+
defaults: DEFAULT_PROFILE,
|
|
47
|
+
errorClass: GuardPostureChainError,
|
|
48
|
+
codePrefix: "posture-chain",
|
|
45
49
|
});
|
|
46
50
|
|
|
47
51
|
/**
|
|
@@ -161,41 +165,19 @@ function validate(envelope, opts) {
|
|
|
161
165
|
return envelope;
|
|
162
166
|
}
|
|
163
167
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
* @status stable
|
|
169
|
-
*
|
|
170
|
-
* Return the effective profile for a given compliance posture name.
|
|
171
|
-
* Returns `null` for unknown posture names so operator typos surface
|
|
172
|
-
* here instead of silently falling through to the default profile.
|
|
173
|
-
*
|
|
174
|
-
* @example
|
|
175
|
-
* b.guardPostureChain.compliancePosture("hipaa"); // → "strict"
|
|
176
|
-
*/
|
|
177
|
-
function compliancePosture(posture) {
|
|
178
|
-
return COMPLIANCE_POSTURES[posture] || null;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function _resolveProfile(opts) {
|
|
182
|
-
if (opts.posture && COMPLIANCE_POSTURES[opts.posture]) {
|
|
183
|
-
return COMPLIANCE_POSTURES[opts.posture];
|
|
184
|
-
}
|
|
185
|
-
var p = opts.profile || DEFAULT_PROFILE;
|
|
186
|
-
if (!PROFILES[p]) {
|
|
187
|
-
throw new GuardPostureChainError("posture-chain/bad-profile",
|
|
188
|
-
"guardPostureChain: unknown profile '" + p + "'");
|
|
189
|
-
}
|
|
190
|
-
return p;
|
|
191
|
-
}
|
|
168
|
+
// compliancePosture is assembled by gateContract.defineParser below; its
|
|
169
|
+
// wiki section renders from the single-sourced @abiTemplate (defineParser)
|
|
170
|
+
// block in gate-contract.js, instantiated for this guard by the page
|
|
171
|
+
// generator.
|
|
192
172
|
|
|
193
|
-
module.exports = {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
173
|
+
module.exports = gateContract.defineParser({
|
|
174
|
+
name: "posture-chain",
|
|
175
|
+
entry: validate,
|
|
176
|
+
errorClass: GuardPostureChainError,
|
|
177
|
+
profiles: PROFILES,
|
|
178
|
+
postures: COMPLIANCE_POSTURES,
|
|
179
|
+
extra: {
|
|
180
|
+
NAME: "postureChain",
|
|
181
|
+
KIND: "posture-chain",
|
|
182
|
+
},
|
|
183
|
+
});
|
package/lib/guard-regex.js
CHANGED
|
@@ -450,12 +450,9 @@ function sanitize(input, opts) {
|
|
|
450
450
|
throw _err("regex.bad-input", "sanitize requires string input");
|
|
451
451
|
}
|
|
452
452
|
var issues = _detectIssues(input, opts);
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
"guardRegex.sanitize: " + issues[i].snippet);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
453
|
+
gateContract.throwOnRefusalSeverity(issues, {
|
|
454
|
+
errorClass: GuardRegexError, codePrefix: "regex",
|
|
455
|
+
});
|
|
459
456
|
return input;
|
|
460
457
|
}
|
|
461
458
|
|
|
@@ -527,106 +524,35 @@ function gate(opts) {
|
|
|
527
524
|
});
|
|
528
525
|
}
|
|
529
526
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
* @related b.guardRegex.gate, b.guardRegex.compliancePosture
|
|
536
|
-
*
|
|
537
|
-
* Compose a derived guardRegex profile from one or more named
|
|
538
|
-
* bases plus inline overrides. `opts.extends` is a profile name
|
|
539
|
-
* (`"strict"` / `"balanced"` / `"permissive"`) or an array of
|
|
540
|
-
* names; later entries shadow earlier ones. Inline `opts` keys win
|
|
541
|
-
* last. Used to keep operator-defined profiles traceable to a
|
|
542
|
-
* baseline rather than re-typing every key.
|
|
543
|
-
*
|
|
544
|
-
* @opts
|
|
545
|
-
* extends: string|string[], // base profile name(s) to compose
|
|
546
|
-
* ...: any guardRegex key, // inline override of resolved keys
|
|
547
|
-
*
|
|
548
|
-
* @example
|
|
549
|
-
* var custom = b.guardRegex.buildProfile({
|
|
550
|
-
* extends: "balanced",
|
|
551
|
-
* maxBoundedRepeat: 50,
|
|
552
|
-
* boundedRepeatPolicy: "reject",
|
|
553
|
-
* });
|
|
554
|
-
* custom.maxBoundedRepeat; // → 50
|
|
555
|
-
* custom.nestedQuantPolicy; // → "reject"
|
|
556
|
-
*/
|
|
557
|
-
var buildProfile = gateContract.makeProfileBuilder(PROFILES);
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* @primitive b.guardRegex.compliancePosture
|
|
561
|
-
* @signature b.guardRegex.compliancePosture(name)
|
|
562
|
-
* @since 0.7.13
|
|
563
|
-
* @status stable
|
|
564
|
-
* @compliance hipaa, pci-dss, gdpr, soc2
|
|
565
|
-
* @related b.guardRegex.gate, b.guardRegex.buildProfile
|
|
566
|
-
*
|
|
567
|
-
* Look up a compliance-posture overlay by name (`"hipaa"` /
|
|
568
|
-
* `"pci-dss"` / `"gdpr"` / `"soc2"`). Returns a shallow clone of
|
|
569
|
-
* the posture object — the caller may mutate freely. Throws
|
|
570
|
-
* `GuardRegexError("regex.bad-posture")` on unknown name.
|
|
571
|
-
*
|
|
572
|
-
* @example
|
|
573
|
-
* var posture = b.guardRegex.compliancePosture("hipaa");
|
|
574
|
-
* posture.nestedQuantPolicy; // → "reject"
|
|
575
|
-
* posture.forensicSnippetBytes; // → 256
|
|
576
|
-
*/
|
|
577
|
-
function compliancePosture(name) {
|
|
578
|
-
return gateContract.lookupCompliancePosture(name, COMPLIANCE_POSTURES,
|
|
579
|
-
_err, "regex");
|
|
580
|
-
}
|
|
527
|
+
// buildProfile / compliancePosture / loadRulePack are assembled by
|
|
528
|
+
// gateContract.defineGuard below (makeProfileBuilder(PROFILES) /
|
|
529
|
+
// lookupCompliancePosture(_, COMPLIANCE_POSTURES) / makeRulePackLoader).
|
|
530
|
+
// Their wiki sections render from the single-sourced @abiTemplate blocks
|
|
531
|
+
// in gate-contract.js, instantiated per guard by the page generator.
|
|
581
532
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
* Register an operator-supplied rule pack with the guardRegex
|
|
591
|
-
* registry. The pack is identified by `pack.id` (non-empty string)
|
|
592
|
-
* and stored for later inspection / dispatch by gates that opt in
|
|
593
|
-
* via `opts.rulePackId`. Returns the pack object unchanged on
|
|
594
|
-
* success; throws `GuardRegexError("regex.bad-opt")` when `pack`
|
|
595
|
-
* is missing or `pack.id` is not a non-empty string.
|
|
596
|
-
*
|
|
597
|
-
* @example
|
|
598
|
-
* var pack = b.guardRegex.loadRulePack({
|
|
599
|
-
* id: "no-empty-alternation",
|
|
600
|
-
* rules: [
|
|
601
|
-
* { id: "empty-alt", severity: "high",
|
|
602
|
-
* detect: function (pattern) { return /\(\|/.test(pattern); },
|
|
603
|
-
* reason: "alternation with empty branch" },
|
|
604
|
-
* ],
|
|
605
|
-
* });
|
|
606
|
-
* pack.id; // → "no-empty-alternation"
|
|
607
|
-
*/
|
|
608
|
-
var loadRulePack = _regexRulePacks.load;
|
|
533
|
+
// ---- adaptive integration-test fixtures (consumed by layer-5 host harness) ----
|
|
534
|
+
var INTEGRATION_FIXTURES = Object.freeze({
|
|
535
|
+
kind: "identifier",
|
|
536
|
+
benignBytes: Buffer.from("^[a-z]+$", "utf8"),
|
|
537
|
+
hostileBytes: Buffer.from("(a+)+b", "utf8"),
|
|
538
|
+
benignIdentifier: "^[a-z]+$",
|
|
539
|
+
hostileIdentifier: "(a+)+b",
|
|
540
|
+
});
|
|
609
541
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
loadRulePack: loadRulePack,
|
|
628
|
-
PROFILES: PROFILES,
|
|
629
|
-
DEFAULTS: DEFAULTS,
|
|
630
|
-
COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
|
|
631
|
-
GuardRegexError: GuardRegexError,
|
|
632
|
-
};
|
|
542
|
+
// Assembled from the gate-contract guard factory: error class, registry
|
|
543
|
+
// exports (NAME / KIND / INTEGRATION_FIXTURES), buildProfile /
|
|
544
|
+
// compliancePosture / loadRulePack wiring, plus the per-guard inspection
|
|
545
|
+
// surface (validate / sanitize / gate). The bespoke `gate` carries
|
|
546
|
+
// guardRegex's ctx.identifier || ctx.pattern dispatch unchanged.
|
|
547
|
+
module.exports = gateContract.defineGuard({
|
|
548
|
+
name: "regex",
|
|
549
|
+
kind: "identifier",
|
|
550
|
+
errorClass: GuardRegexError,
|
|
551
|
+
profiles: PROFILES,
|
|
552
|
+
defaults: DEFAULTS,
|
|
553
|
+
postures: COMPLIANCE_POSTURES,
|
|
554
|
+
integrationFixtures: INTEGRATION_FIXTURES,
|
|
555
|
+
validate: validate,
|
|
556
|
+
sanitize: sanitize,
|
|
557
|
+
gate: gate,
|
|
558
|
+
});
|
package/lib/guard-saga-config.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
var { defineClass } = require("./framework-error");
|
|
19
|
+
var gateContract = require("./gate-contract");
|
|
19
20
|
|
|
20
21
|
var GuardSagaConfigError = defineClass("GuardSagaConfigError", { alwaysPermanent: true });
|
|
21
22
|
|
|
@@ -27,11 +28,14 @@ var PROFILES = Object.freeze({
|
|
|
27
28
|
permissive: { maxSteps: 512, maxNameBytes: 256 },
|
|
28
29
|
});
|
|
29
30
|
|
|
30
|
-
var COMPLIANCE_POSTURES =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
32
|
+
|
|
33
|
+
var _resolveProfile = gateContract.makeProfileResolver({
|
|
34
|
+
profiles: PROFILES,
|
|
35
|
+
postures: COMPLIANCE_POSTURES,
|
|
36
|
+
defaults: DEFAULT_PROFILE,
|
|
37
|
+
errorClass: GuardSagaConfigError,
|
|
38
|
+
codePrefix: "saga-config",
|
|
35
39
|
});
|
|
36
40
|
|
|
37
41
|
/**
|
|
@@ -117,41 +121,19 @@ function validate(config, opts) {
|
|
|
117
121
|
return config;
|
|
118
122
|
}
|
|
119
123
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
* @status stable
|
|
125
|
-
*
|
|
126
|
-
* Return the effective profile for a given compliance posture name.
|
|
127
|
-
* Returns `null` for unknown posture names so operator typos surface
|
|
128
|
-
* here instead of silently falling through to the default profile.
|
|
129
|
-
*
|
|
130
|
-
* @example
|
|
131
|
-
* b.guardSagaConfig.compliancePosture("hipaa"); // → "strict"
|
|
132
|
-
*/
|
|
133
|
-
function compliancePosture(posture) {
|
|
134
|
-
return COMPLIANCE_POSTURES[posture] || null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function _resolveProfile(opts) {
|
|
138
|
-
if (opts.posture && COMPLIANCE_POSTURES[opts.posture]) {
|
|
139
|
-
return COMPLIANCE_POSTURES[opts.posture];
|
|
140
|
-
}
|
|
141
|
-
var p = opts.profile || DEFAULT_PROFILE;
|
|
142
|
-
if (!PROFILES[p]) {
|
|
143
|
-
throw new GuardSagaConfigError("saga-config/bad-profile",
|
|
144
|
-
"guardSagaConfig: unknown profile '" + p + "'");
|
|
145
|
-
}
|
|
146
|
-
return p;
|
|
147
|
-
}
|
|
124
|
+
// compliancePosture is assembled by gateContract.defineParser below; its
|
|
125
|
+
// wiki section renders from the single-sourced @abiTemplate (defineParser)
|
|
126
|
+
// block in gate-contract.js, instantiated for this guard by the page
|
|
127
|
+
// generator.
|
|
148
128
|
|
|
149
|
-
module.exports = {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
129
|
+
module.exports = gateContract.defineParser({
|
|
130
|
+
name: "saga-config",
|
|
131
|
+
entry: validate,
|
|
132
|
+
errorClass: GuardSagaConfigError,
|
|
133
|
+
profiles: PROFILES,
|
|
134
|
+
postures: COMPLIANCE_POSTURES,
|
|
135
|
+
extra: {
|
|
136
|
+
NAME: "sagaConfig",
|
|
137
|
+
KIND: "saga-config",
|
|
138
|
+
},
|
|
139
|
+
});
|