@blamejs/core 0.14.26 → 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.
Files changed (150) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +2 -2
  3. package/index.js +4 -0
  4. package/lib/agent-envelope-mac.js +104 -0
  5. package/lib/agent-event-bus.js +105 -4
  6. package/lib/agent-posture-chain.js +8 -42
  7. package/lib/ai-content-detect.js +9 -10
  8. package/lib/api-key.js +107 -74
  9. package/lib/atomic-file.js +62 -4
  10. package/lib/audit-chain.js +47 -11
  11. package/lib/audit-sign.js +77 -2
  12. package/lib/audit-tools.js +79 -51
  13. package/lib/audit.js +249 -123
  14. package/lib/auth/openid-federation.js +108 -47
  15. package/lib/backup/index.js +13 -10
  16. package/lib/break-glass.js +202 -144
  17. package/lib/cache.js +174 -105
  18. package/lib/chain-writer.js +38 -16
  19. package/lib/cli.js +19 -14
  20. package/lib/cluster-provider-db.js +130 -104
  21. package/lib/cluster-storage.js +119 -22
  22. package/lib/cluster.js +119 -71
  23. package/lib/compliance.js +169 -4
  24. package/lib/consent.js +73 -24
  25. package/lib/constants.js +16 -11
  26. package/lib/crypto-field.js +474 -92
  27. package/lib/db-declare-row-policy.js +35 -22
  28. package/lib/db-file-lifecycle.js +3 -2
  29. package/lib/db-query.js +497 -255
  30. package/lib/db-schema.js +209 -44
  31. package/lib/db.js +176 -95
  32. package/lib/error-page.js +14 -1
  33. package/lib/external-db-migrate.js +229 -139
  34. package/lib/external-db.js +25 -15
  35. package/lib/file-upload.js +52 -7
  36. package/lib/framework-error.js +14 -1
  37. package/lib/framework-files.js +73 -0
  38. package/lib/framework-schema.js +695 -394
  39. package/lib/gate-contract.js +649 -1
  40. package/lib/guard-agent-registry.js +26 -44
  41. package/lib/guard-all.js +1 -0
  42. package/lib/guard-auth.js +42 -112
  43. package/lib/guard-cidr.js +33 -154
  44. package/lib/guard-csv.js +46 -113
  45. package/lib/guard-domain.js +34 -157
  46. package/lib/guard-dsn.js +27 -43
  47. package/lib/guard-email.js +47 -69
  48. package/lib/guard-envelope.js +19 -32
  49. package/lib/guard-event-bus-payload.js +24 -42
  50. package/lib/guard-event-bus-topic.js +25 -43
  51. package/lib/guard-filename.js +42 -106
  52. package/lib/guard-graphql.js +42 -123
  53. package/lib/guard-html.js +53 -108
  54. package/lib/guard-idempotency-key.js +24 -42
  55. package/lib/guard-image.js +46 -103
  56. package/lib/guard-imap-command.js +18 -32
  57. package/lib/guard-jmap.js +16 -30
  58. package/lib/guard-json.js +38 -108
  59. package/lib/guard-jsonpath.js +38 -171
  60. package/lib/guard-jwt.js +49 -179
  61. package/lib/guard-list-id.js +25 -41
  62. package/lib/guard-list-unsubscribe.js +27 -43
  63. package/lib/guard-mail-compose.js +24 -42
  64. package/lib/guard-mail-move.js +26 -44
  65. package/lib/guard-mail-query.js +28 -46
  66. package/lib/guard-mail-reply.js +24 -42
  67. package/lib/guard-mail-sieve.js +24 -42
  68. package/lib/guard-managesieve-command.js +17 -31
  69. package/lib/guard-markdown.js +37 -104
  70. package/lib/guard-message-id.js +26 -45
  71. package/lib/guard-mime.js +39 -151
  72. package/lib/guard-oauth.js +54 -135
  73. package/lib/guard-pdf.js +45 -101
  74. package/lib/guard-pop3-command.js +21 -31
  75. package/lib/guard-posture-chain.js +24 -42
  76. package/lib/guard-regex.js +33 -107
  77. package/lib/guard-saga-config.js +24 -42
  78. package/lib/guard-shell.js +42 -172
  79. package/lib/guard-smtp-command.js +48 -54
  80. package/lib/guard-snapshot-envelope.js +24 -42
  81. package/lib/guard-sql.js +1491 -0
  82. package/lib/guard-stream-args.js +24 -43
  83. package/lib/guard-svg.js +47 -65
  84. package/lib/guard-template.js +35 -172
  85. package/lib/guard-tenant-id.js +26 -45
  86. package/lib/guard-time.js +32 -154
  87. package/lib/guard-trace-context.js +25 -44
  88. package/lib/guard-uuid.js +32 -153
  89. package/lib/guard-xml.js +38 -113
  90. package/lib/guard-yaml.js +51 -163
  91. package/lib/http-client.js +37 -9
  92. package/lib/inbox.js +120 -107
  93. package/lib/legal-hold.js +107 -50
  94. package/lib/log-stream-cloudwatch.js +47 -31
  95. package/lib/log-stream-otlp.js +32 -18
  96. package/lib/mail-crypto-smime.js +2 -6
  97. package/lib/mail-greylist.js +2 -6
  98. package/lib/mail-helo.js +2 -6
  99. package/lib/mail-journal.js +85 -64
  100. package/lib/mail-rbl.js +2 -6
  101. package/lib/mail-scan.js +2 -6
  102. package/lib/mail-server-jmap.js +117 -12
  103. package/lib/mail-spam-score.js +2 -6
  104. package/lib/mail-store.js +287 -154
  105. package/lib/middleware/body-parser.js +71 -25
  106. package/lib/middleware/csrf-protect.js +19 -8
  107. package/lib/middleware/fetch-metadata.js +17 -7
  108. package/lib/middleware/idempotency-key.js +54 -38
  109. package/lib/middleware/rate-limit.js +102 -32
  110. package/lib/middleware/security-headers.js +21 -5
  111. package/lib/migrations.js +108 -66
  112. package/lib/network-heartbeat.js +7 -0
  113. package/lib/nonce-store.js +31 -9
  114. package/lib/object-store/azure-blob-bucket-ops.js +9 -4
  115. package/lib/object-store/azure-blob.js +57 -3
  116. package/lib/object-store/sigv4.js +10 -0
  117. package/lib/observability.js +87 -0
  118. package/lib/otel-export.js +25 -1
  119. package/lib/outbox.js +136 -82
  120. package/lib/parsers/safe-xml.js +47 -7
  121. package/lib/pqc-agent.js +44 -0
  122. package/lib/pubsub-cluster.js +42 -20
  123. package/lib/queue-local.js +202 -139
  124. package/lib/queue-redis.js +9 -1
  125. package/lib/queue-sqs.js +6 -0
  126. package/lib/redact.js +68 -11
  127. package/lib/redis-client.js +160 -31
  128. package/lib/retention.js +82 -39
  129. package/lib/router.js +212 -5
  130. package/lib/safe-dns.js +29 -45
  131. package/lib/safe-ical.js +18 -33
  132. package/lib/safe-icap.js +27 -43
  133. package/lib/safe-sieve.js +21 -40
  134. package/lib/safe-sql.js +124 -3
  135. package/lib/safe-vcard.js +18 -33
  136. package/lib/scheduler.js +35 -12
  137. package/lib/seeders.js +122 -74
  138. package/lib/session-stores.js +42 -14
  139. package/lib/session.js +109 -72
  140. package/lib/sql.js +3885 -0
  141. package/lib/ssrf-guard.js +51 -4
  142. package/lib/static.js +177 -34
  143. package/lib/subject.js +55 -17
  144. package/lib/vault/index.js +3 -2
  145. package/lib/vault/passphrase-ops.js +3 -2
  146. package/lib/vault/rotate.js +104 -64
  147. package/lib/vendor-data.js +2 -0
  148. package/lib/websocket.js +35 -5
  149. package/package.json +1 -1
  150. 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
- for (var i = 0; i < issues.length; i += 1) {
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
- * @primitive b.guardPdf.buildProfile
454
- * @signature b.guardPdf.buildProfile(opts)
455
- * @since 0.7.13
456
- * @status stable
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
- module.exports = {
539
- // ---- guard-* family registry exports ----
540
- NAME: "pdf",
541
- KIND: "metadata",
542
- INTEGRATION_FIXTURES: Object.freeze({
543
- kind: "metadata",
544
- benignBytes: Buffer.from([0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E, 0x37]), // %PDF-1.7
545
- hostileBytes: Buffer.from([0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E, 0x37]),
546
- benignMetadata: {
547
- bytes: Buffer.from([0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E, 0x37]),
548
- hasJavaScript: false, hasOpenAction: false, hasLaunchAction: false,
549
- hasEmbeddedFiles: false, isEncrypted: false, pageCount: 1,
550
- },
551
- hostileMetadata: {
552
- bytes: Buffer.from([0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E, 0x37]),
553
- // Hostile: JavaScript action — universal refuse (RCE class).
554
- hasJavaScript: true,
555
- },
556
- }),
557
- // ---- primitive surface ----
558
- validate: validate,
559
- sanitize: sanitize,
560
- gate: gate,
561
- inspectMagic: inspectMagic,
562
- buildProfile: buildProfile,
563
- compliancePosture: compliancePosture,
564
- loadRulePack: loadRulePack,
565
- PROFILES: PROFILES,
566
- DEFAULTS: DEFAULTS,
567
- COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
568
- GuardPdfError: GuardPdfError,
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 = Object.freeze({
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
- * @primitive b.guardPop3Command.compliancePosture
295
- * @signature b.guardPop3Command.compliancePosture(posture)
296
- * @since 0.9.52
297
- * @status stable
298
- *
299
- * Return the effective profile for a compliance posture, or `null`
300
- * for unknown names.
301
- *
302
- * @example
303
- * b.guardPop3Command.compliancePosture("hipaa"); // → "strict"
304
- */
305
- function compliancePosture(posture) {
306
- return COMPLIANCE_POSTURES[posture] || null;
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 = Object.freeze({
41
- hipaa: "strict",
42
- "pci-dss": "strict",
43
- gdpr: "strict",
44
- soc2: "strict",
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
- * @primitive b.guardPostureChain.compliancePosture
166
- * @signature b.guardPostureChain.compliancePosture(posture)
167
- * @since 0.9.28
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
- validate: validate,
195
- compliancePosture: compliancePosture,
196
- PROFILES: PROFILES,
197
- COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
198
- GuardPostureChainError: GuardPostureChainError,
199
- NAME: "postureChain",
200
- KIND: "posture-chain",
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
+ });
@@ -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
- for (var i = 0; i < issues.length; i += 1) {
454
- if (issues[i].severity === "critical" || issues[i].severity === "high") {
455
- throw _err(issues[i].ruleId || "regex.refused",
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
- * @primitive b.guardRegex.buildProfile
532
- * @signature b.guardRegex.buildProfile(opts)
533
- * @since 0.7.13
534
- * @status stable
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
- var _regexRulePacks = gateContract.makeRulePackLoader(GuardRegexError, "regex");
583
- /**
584
- * @primitive b.guardRegex.loadRulePack
585
- * @signature b.guardRegex.loadRulePack(pack)
586
- * @since 0.7.13
587
- * @status stable
588
- * @related b.guardRegex.gate
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
- module.exports = {
611
- // ---- guard-* family registry exports ----
612
- NAME: "regex",
613
- KIND: "identifier",
614
- INTEGRATION_FIXTURES: Object.freeze({
615
- kind: "identifier",
616
- benignBytes: Buffer.from("^[a-z]+$", "utf8"),
617
- hostileBytes: Buffer.from("(a+)+b", "utf8"),
618
- benignIdentifier: "^[a-z]+$",
619
- hostileIdentifier: "(a+)+b",
620
- }),
621
- // ---- primitive surface ----
622
- validate: validate,
623
- sanitize: sanitize,
624
- gate: gate,
625
- buildProfile: buildProfile,
626
- compliancePosture: compliancePosture,
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
+ });
@@ -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 = Object.freeze({
31
- hipaa: "strict",
32
- "pci-dss": "strict",
33
- gdpr: "strict",
34
- soc2: "strict",
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
- * @primitive b.guardSagaConfig.compliancePosture
122
- * @signature b.guardSagaConfig.compliancePosture(posture)
123
- * @since 0.9.27
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
- validate: validate,
151
- compliancePosture: compliancePosture,
152
- PROFILES: PROFILES,
153
- COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
154
- GuardSagaConfigError: GuardSagaConfigError,
155
- NAME: "sagaConfig",
156
- KIND: "saga-config",
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
+ });