@blamejs/exceptd-skills 0.9.1

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 (136) hide show
  1. package/AGENTS.md +232 -0
  2. package/ARCHITECTURE.md +267 -0
  3. package/CHANGELOG.md +616 -0
  4. package/CONTEXT.md +203 -0
  5. package/LICENSE +200 -0
  6. package/NOTICE +82 -0
  7. package/README.md +307 -0
  8. package/SECURITY.md +73 -0
  9. package/agents/README.md +81 -0
  10. package/agents/report-generator.md +156 -0
  11. package/agents/skill-updater.md +102 -0
  12. package/agents/source-validator.md +119 -0
  13. package/agents/threat-researcher.md +149 -0
  14. package/bin/exceptd.js +183 -0
  15. package/data/_indexes/_meta.json +88 -0
  16. package/data/_indexes/activity-feed.json +362 -0
  17. package/data/_indexes/catalog-summaries.json +229 -0
  18. package/data/_indexes/chains.json +7135 -0
  19. package/data/_indexes/currency.json +359 -0
  20. package/data/_indexes/did-ladders.json +451 -0
  21. package/data/_indexes/frequency.json +2072 -0
  22. package/data/_indexes/handoff-dag.json +476 -0
  23. package/data/_indexes/jurisdiction-clocks.json +967 -0
  24. package/data/_indexes/jurisdiction-map.json +536 -0
  25. package/data/_indexes/recipes.json +319 -0
  26. package/data/_indexes/section-offsets.json +3656 -0
  27. package/data/_indexes/stale-content.json +14 -0
  28. package/data/_indexes/summary-cards.json +1736 -0
  29. package/data/_indexes/theater-fingerprints.json +381 -0
  30. package/data/_indexes/token-budget.json +2137 -0
  31. package/data/_indexes/trigger-table.json +1374 -0
  32. package/data/_indexes/xref.json +818 -0
  33. package/data/atlas-ttps.json +282 -0
  34. package/data/cve-catalog.json +496 -0
  35. package/data/cwe-catalog.json +1017 -0
  36. package/data/d3fend-catalog.json +738 -0
  37. package/data/dlp-controls.json +1039 -0
  38. package/data/exploit-availability.json +67 -0
  39. package/data/framework-control-gaps.json +1255 -0
  40. package/data/global-frameworks.json +2913 -0
  41. package/data/rfc-references.json +324 -0
  42. package/data/zeroday-lessons.json +377 -0
  43. package/keys/public.pem +3 -0
  44. package/lib/framework-gap.js +328 -0
  45. package/lib/job-queue.js +195 -0
  46. package/lib/lint-skills.js +536 -0
  47. package/lib/prefetch.js +372 -0
  48. package/lib/refresh-external.js +713 -0
  49. package/lib/schemas/cve-catalog.schema.json +151 -0
  50. package/lib/schemas/manifest.schema.json +106 -0
  51. package/lib/schemas/skill-frontmatter.schema.json +113 -0
  52. package/lib/scoring.js +149 -0
  53. package/lib/sign.js +197 -0
  54. package/lib/ttp-mapper.js +80 -0
  55. package/lib/validate-catalog-meta.js +198 -0
  56. package/lib/validate-cve-catalog.js +213 -0
  57. package/lib/validate-indexes.js +83 -0
  58. package/lib/validate-package.js +162 -0
  59. package/lib/validate-vendor.js +85 -0
  60. package/lib/verify.js +216 -0
  61. package/lib/worker-pool.js +84 -0
  62. package/manifest-snapshot.json +1833 -0
  63. package/manifest.json +2108 -0
  64. package/orchestrator/README.md +124 -0
  65. package/orchestrator/dispatcher.js +140 -0
  66. package/orchestrator/event-bus.js +146 -0
  67. package/orchestrator/index.js +874 -0
  68. package/orchestrator/pipeline.js +201 -0
  69. package/orchestrator/scanner.js +327 -0
  70. package/orchestrator/scheduler.js +137 -0
  71. package/package.json +113 -0
  72. package/sbom.cdx.json +158 -0
  73. package/scripts/audit-cross-skill.js +261 -0
  74. package/scripts/audit-perf.js +160 -0
  75. package/scripts/bootstrap.js +205 -0
  76. package/scripts/build-indexes.js +721 -0
  77. package/scripts/builders/activity-feed.js +79 -0
  78. package/scripts/builders/catalog-summaries.js +67 -0
  79. package/scripts/builders/currency.js +109 -0
  80. package/scripts/builders/cwe-chains.js +105 -0
  81. package/scripts/builders/did-ladders.js +149 -0
  82. package/scripts/builders/frequency.js +89 -0
  83. package/scripts/builders/jurisdiction-clocks.js +126 -0
  84. package/scripts/builders/recipes.js +159 -0
  85. package/scripts/builders/section-offsets.js +162 -0
  86. package/scripts/builders/stale-content.js +171 -0
  87. package/scripts/builders/summary-cards.js +166 -0
  88. package/scripts/builders/theater-fingerprints.js +198 -0
  89. package/scripts/builders/token-budget.js +96 -0
  90. package/scripts/check-manifest-snapshot.js +217 -0
  91. package/scripts/predeploy.js +267 -0
  92. package/scripts/refresh-manifest-snapshot.js +57 -0
  93. package/scripts/refresh-sbom.js +222 -0
  94. package/skills/age-gates-child-safety/skill.md +456 -0
  95. package/skills/ai-attack-surface/skill.md +282 -0
  96. package/skills/ai-c2-detection/skill.md +440 -0
  97. package/skills/ai-risk-management/skill.md +311 -0
  98. package/skills/api-security/skill.md +287 -0
  99. package/skills/attack-surface-pentest/skill.md +381 -0
  100. package/skills/cloud-security/skill.md +384 -0
  101. package/skills/compliance-theater/skill.md +365 -0
  102. package/skills/container-runtime-security/skill.md +379 -0
  103. package/skills/coordinated-vuln-disclosure/skill.md +473 -0
  104. package/skills/defensive-countermeasure-mapping/skill.md +300 -0
  105. package/skills/dlp-gap-analysis/skill.md +337 -0
  106. package/skills/email-security-anti-phishing/skill.md +206 -0
  107. package/skills/exploit-scoring/skill.md +331 -0
  108. package/skills/framework-gap-analysis/skill.md +374 -0
  109. package/skills/fuzz-testing-strategy/skill.md +313 -0
  110. package/skills/global-grc/skill.md +564 -0
  111. package/skills/identity-assurance/skill.md +272 -0
  112. package/skills/incident-response-playbook/skill.md +546 -0
  113. package/skills/kernel-lpe-triage/skill.md +303 -0
  114. package/skills/mcp-agent-trust/skill.md +326 -0
  115. package/skills/mlops-security/skill.md +325 -0
  116. package/skills/ot-ics-security/skill.md +340 -0
  117. package/skills/policy-exception-gen/skill.md +437 -0
  118. package/skills/pqc-first/skill.md +546 -0
  119. package/skills/rag-pipeline-security/skill.md +294 -0
  120. package/skills/researcher/skill.md +310 -0
  121. package/skills/sector-energy/skill.md +409 -0
  122. package/skills/sector-federal-government/skill.md +302 -0
  123. package/skills/sector-financial/skill.md +398 -0
  124. package/skills/sector-healthcare/skill.md +373 -0
  125. package/skills/security-maturity-tiers/skill.md +464 -0
  126. package/skills/skill-update-loop/skill.md +463 -0
  127. package/skills/supply-chain-integrity/skill.md +318 -0
  128. package/skills/threat-model-currency/skill.md +404 -0
  129. package/skills/threat-modeling-methodology/skill.md +312 -0
  130. package/skills/webapp-security/skill.md +281 -0
  131. package/skills/zeroday-gap-learn/skill.md +350 -0
  132. package/vendor/blamejs/LICENSE +201 -0
  133. package/vendor/blamejs/README.md +54 -0
  134. package/vendor/blamejs/_PROVENANCE.json +54 -0
  135. package/vendor/blamejs/retry.js +335 -0
  136. package/vendor/blamejs/worker-pool.js +418 -0
@@ -0,0 +1,335 @@
1
+ "use strict";
2
+ /**
3
+ * vendor/blamejs/retry.js
4
+ *
5
+ * VENDORED — flattened and stripped from blamejs@1442f17 / lib/retry.js.
6
+ * Apache-2.0 (see vendor/blamejs/LICENSE). Provenance: vendor/blamejs/_PROVENANCE.json.
7
+ *
8
+ * Surface preserved:
9
+ * - withRetry(fn, opts) — exponential backoff + crypto jitter + AbortSignal honor
10
+ * - isRetryable(err) — default classifier (HTTP + Node net codes)
11
+ * - backoffDelay(attempt, opts) — pure helper
12
+ * - CircuitBreaker — failure-threshold / cooldown / half-open probe
13
+ * - DEFAULT_RETRY, DEFAULT_BREAKER
14
+ *
15
+ * Stripped vs. upstream:
16
+ * - observability event sink (every _emitEvent call → no-op)
17
+ * - audit hooks
18
+ * - lazy-require for safeAsync.sleep — replaced with a stdlib AbortSignal-aware sleep
19
+ * - numeric-checks dependency — replaced with two inline predicates
20
+ * - constants C.TIME.seconds(...) — replaced with literal ms values
21
+ *
22
+ * Behavior preserved verbatim:
23
+ * - backoff math: capped exponential * (1 - jitterFactor * U(0,1)) using crypto.randomInt
24
+ * - classifier semantics (HTTP 408/425/429/5xx, ECONNRESET et al)
25
+ * - permanent error short-circuit
26
+ * - signal-aware cancellation during the backoff sleep
27
+ *
28
+ * Do NOT hand-edit. To re-vendor, copy the upstream file, re-apply the
29
+ * strip rules above, refresh sha256 in _PROVENANCE.json, then re-run
30
+ * `npm run validate-vendor`.
31
+ */
32
+
33
+ var nodeCrypto = require("crypto");
34
+
35
+ // ---- Defaults ----
36
+
37
+ var DEFAULT_RETRY = Object.freeze({
38
+ maxAttempts: 5,
39
+ baseDelayMs: 100,
40
+ maxDelayMs: 10 * 1000, // 10s
41
+ jitterFactor: 0.5,
42
+ });
43
+
44
+ var HTTP = Object.freeze({
45
+ BAD_REQUEST: 0x190,
46
+ UNAUTHORIZED: 0x191,
47
+ FORBIDDEN: 0x193,
48
+ NOT_FOUND: 0x194,
49
+ METHOD_NOT_ALLOWED: 0x195,
50
+ REQUEST_TIMEOUT: 0x198,
51
+ CONFLICT: 0x199,
52
+ GONE: 0x19a,
53
+ LENGTH_REQUIRED: 0x19b,
54
+ PRECONDITION_FAILED: 0x19c,
55
+ PAYLOAD_TOO_LARGE: 0x19d,
56
+ URI_TOO_LONG: 0x19e,
57
+ UNSUPPORTED_MEDIA_TYPE: 0x19f,
58
+ RANGE_NOT_SATISFIABLE: 0x1a0,
59
+ EXPECTATION_FAILED: 0x1a1,
60
+ UNPROCESSABLE_ENTITY: 0x1a6,
61
+ TOO_EARLY: 0x1a9,
62
+ TOO_MANY_REQUESTS: 0x1ad,
63
+ UNAVAILABLE_FOR_LEGAL_REASONS: 0x1c3,
64
+ INTERNAL_SERVER_ERROR: 0x1f4,
65
+ NOT_IMPLEMENTED: 0x1f5,
66
+ BAD_GATEWAY: 0x1f6,
67
+ SERVICE_UNAVAILABLE: 0x1f7,
68
+ GATEWAY_TIMEOUT: 0x1f8,
69
+ HTTP_VERSION_NOT_SUPPORTED: 0x1f9,
70
+ });
71
+
72
+ var NON_RETRYABLE_HTTP_STATUS = new Set([
73
+ HTTP.BAD_REQUEST, HTTP.UNAUTHORIZED, HTTP.FORBIDDEN, HTTP.NOT_FOUND,
74
+ HTTP.METHOD_NOT_ALLOWED, HTTP.CONFLICT, HTTP.GONE, HTTP.LENGTH_REQUIRED,
75
+ HTTP.PRECONDITION_FAILED, HTTP.PAYLOAD_TOO_LARGE, HTTP.URI_TOO_LONG,
76
+ HTTP.UNSUPPORTED_MEDIA_TYPE, HTTP.RANGE_NOT_SATISFIABLE, HTTP.EXPECTATION_FAILED,
77
+ HTTP.UNPROCESSABLE_ENTITY, HTTP.UNAVAILABLE_FOR_LEGAL_REASONS,
78
+ HTTP.NOT_IMPLEMENTED, HTTP.HTTP_VERSION_NOT_SUPPORTED,
79
+ ]);
80
+
81
+ var RETRYABLE_HTTP_STATUS = new Set([
82
+ HTTP.REQUEST_TIMEOUT, HTTP.TOO_EARLY, HTTP.TOO_MANY_REQUESTS,
83
+ HTTP.INTERNAL_SERVER_ERROR, HTTP.BAD_GATEWAY, HTTP.SERVICE_UNAVAILABLE,
84
+ HTTP.GATEWAY_TIMEOUT,
85
+ ]);
86
+
87
+ var RETRYABLE_NET_ERRORS = new Set([
88
+ "ECONNRESET", "ECONNREFUSED", "ECONNABORTED", "ETIMEDOUT",
89
+ "EPIPE", "EAGAIN", "ENOTFOUND", "ENETUNREACH",
90
+ ]);
91
+
92
+ var STATE_CLOSED = "closed";
93
+ var STATE_OPEN = "open";
94
+ var STATE_HALF = "half-open";
95
+
96
+ var DEFAULT_BREAKER = Object.freeze({
97
+ failureThreshold: 10,
98
+ cooldownMs: 30 * 1000,
99
+ successThreshold: 2,
100
+ });
101
+
102
+ // ---- Inlined predicates (replaces numeric-checks dep) ----
103
+
104
+ function _isPositiveInt(v) {
105
+ return typeof v === "number" && Number.isFinite(v) && Number.isInteger(v) && v > 0;
106
+ }
107
+ function _isNonNegFinite(v) {
108
+ return typeof v === "number" && Number.isFinite(v) && v >= 0;
109
+ }
110
+ function _isAbortSignal(s) {
111
+ return s != null && typeof s === "object" &&
112
+ typeof s.aborted === "boolean" &&
113
+ typeof s.addEventListener === "function";
114
+ }
115
+
116
+ // ---- Signal-aware sleep (replaces safeAsync.sleep dep) ----
117
+
118
+ function _sleep(ms, opts) {
119
+ return new Promise(function (resolve, reject) {
120
+ var signal = opts && opts.signal;
121
+ if (signal && signal.aborted) {
122
+ var abErr = new Error("aborted");
123
+ abErr.name = "AbortError";
124
+ reject(abErr);
125
+ return;
126
+ }
127
+ var t = setTimeout(function () {
128
+ if (signal) signal.removeEventListener("abort", onAbort);
129
+ resolve();
130
+ }, ms);
131
+ // NOTE: deliberately do NOT unref the timer here. CLI callers
132
+ // (refresh-external, prefetch, build-indexes --parallel) rely on the
133
+ // retry sleep to keep the event loop alive; unref-ing causes the
134
+ // process to exit before the backoff completes when there are no
135
+ // other open handles.
136
+ function onAbort() {
137
+ clearTimeout(t);
138
+ var err = new Error("aborted");
139
+ err.name = "AbortError";
140
+ reject(err);
141
+ }
142
+ if (signal) signal.addEventListener("abort", onAbort, { once: true });
143
+ });
144
+ }
145
+
146
+ // ---- Validation ----
147
+
148
+ function _validateRetryOpts(opts) {
149
+ if (!_isPositiveInt(opts.maxAttempts)) {
150
+ throw new TypeError("retry.withRetry: maxAttempts must be a positive integer");
151
+ }
152
+ if (!_isNonNegFinite(opts.baseDelayMs)) {
153
+ throw new TypeError("retry.withRetry: baseDelayMs must be a non-negative finite number");
154
+ }
155
+ if (!_isNonNegFinite(opts.maxDelayMs)) {
156
+ throw new TypeError("retry.withRetry: maxDelayMs must be a non-negative finite number");
157
+ }
158
+ if (typeof opts.jitterFactor !== "number" || !isFinite(opts.jitterFactor) ||
159
+ opts.jitterFactor < 0 || opts.jitterFactor > 1) {
160
+ throw new TypeError("retry.withRetry: jitterFactor must be a finite number in [0, 1]");
161
+ }
162
+ if (opts.isRetryable !== undefined && typeof opts.isRetryable !== "function") {
163
+ throw new TypeError("retry.withRetry: isRetryable must be a function or undefined");
164
+ }
165
+ if (opts.onRetry !== undefined && typeof opts.onRetry !== "function") {
166
+ throw new TypeError("retry.withRetry: onRetry must be a function or undefined");
167
+ }
168
+ if (opts.signal !== undefined && opts.signal !== null && !_isAbortSignal(opts.signal)) {
169
+ throw new TypeError("retry.withRetry: signal must be an AbortSignal or undefined");
170
+ }
171
+ }
172
+
173
+ function _validateBreakerOpts(name, opts) {
174
+ if (typeof name !== "string" || name.length === 0) {
175
+ throw new TypeError("retry.CircuitBreaker: name must be a non-empty string");
176
+ }
177
+ if (!_isPositiveInt(opts.failureThreshold)) {
178
+ throw new TypeError("retry.CircuitBreaker: failureThreshold must be a positive integer");
179
+ }
180
+ if (!_isNonNegFinite(opts.cooldownMs)) {
181
+ throw new TypeError("retry.CircuitBreaker: cooldownMs must be a non-negative finite number");
182
+ }
183
+ if (!_isPositiveInt(opts.successThreshold)) {
184
+ throw new TypeError("retry.CircuitBreaker: successThreshold must be a positive integer");
185
+ }
186
+ }
187
+
188
+ // ---- Public surface ----
189
+
190
+ function isRetryable(err) {
191
+ if (!err) return false;
192
+ if (err.isObjectStoreError && err.permanent) return false;
193
+ if (err.permanent) return false;
194
+ if (typeof err.statusCode === "number") {
195
+ if (RETRYABLE_HTTP_STATUS.has(err.statusCode)) return true;
196
+ if (NON_RETRYABLE_HTTP_STATUS.has(err.statusCode)) return false;
197
+ if (err.statusCode >= 500) return true;
198
+ return false;
199
+ }
200
+ if (err.code && RETRYABLE_NET_ERRORS.has(err.code)) return true;
201
+ return false;
202
+ }
203
+
204
+ function backoffDelay(attempt, opts) {
205
+ if (!_isPositiveInt(attempt)) {
206
+ throw new TypeError("retry.backoffDelay: attempt must be a positive integer");
207
+ }
208
+ opts = opts || DEFAULT_RETRY;
209
+ var base = opts.baseDelayMs * Math.pow(2, attempt - 1);
210
+ var capped = Math.min(base, opts.maxDelayMs);
211
+ var jitterDenom = 1000000;
212
+ var jitter = capped * opts.jitterFactor * (nodeCrypto.randomInt(0, jitterDenom) / jitterDenom);
213
+ return Math.floor(capped - jitter);
214
+ }
215
+
216
+ async function withRetry(fn, opts) {
217
+ if (typeof fn !== "function") {
218
+ throw new TypeError("retry.withRetry: fn must be a function, got " + typeof fn);
219
+ }
220
+ opts = Object.assign({}, DEFAULT_RETRY, opts || {});
221
+ _validateRetryOpts(opts);
222
+ var classify = (typeof opts.isRetryable === "function") ? opts.isRetryable : isRetryable;
223
+ var lastErr = null;
224
+ for (var attempt = 1; attempt <= opts.maxAttempts; attempt++) {
225
+ try {
226
+ return await fn(attempt);
227
+ } catch (err) {
228
+ lastErr = err;
229
+ var retryable = classify(err);
230
+ if (!retryable || attempt === opts.maxAttempts) {
231
+ throw err;
232
+ }
233
+ var delay = backoffDelay(attempt, opts);
234
+ if (typeof opts.onRetry === "function") {
235
+ try { opts.onRetry({ attempt: attempt, delay: delay, error: err }); }
236
+ catch (_cbErr) { /* observer error never crashes the retry loop */ }
237
+ }
238
+ await _sleep(delay, { signal: opts.signal });
239
+ }
240
+ }
241
+ throw lastErr;
242
+ }
243
+
244
+ // ---- Circuit breaker ----
245
+
246
+ class CircuitBreaker {
247
+ constructor(name, opts) {
248
+ var merged = Object.assign({}, DEFAULT_BREAKER, opts || {});
249
+ _validateBreakerOpts(name || "", merged);
250
+ this.name = name;
251
+ this.opts = merged;
252
+ this.state = STATE_CLOSED;
253
+ this.consecutiveFailures = 0;
254
+ this.consecutiveSuccesses = 0;
255
+ this.openedAt = 0;
256
+ }
257
+
258
+ async wrap(fn) {
259
+ if (typeof fn !== "function") {
260
+ throw new TypeError("retry.CircuitBreaker.wrap: fn must be a function, got " + typeof fn);
261
+ }
262
+ if (this.state === STATE_OPEN) {
263
+ if (Date.now() - this.openedAt >= this.opts.cooldownMs) {
264
+ this._transition(STATE_OPEN, STATE_HALF);
265
+ } else {
266
+ var err = new Error("circuit breaker '" + this.name + "' is OPEN");
267
+ err.code = "CIRCUIT_OPEN";
268
+ err.permanent = false;
269
+ err.isObjectStoreError = true;
270
+ throw err;
271
+ }
272
+ }
273
+ try {
274
+ var result = await fn();
275
+ this._onSuccess();
276
+ return result;
277
+ } catch (e) {
278
+ this._onFailure(e);
279
+ throw e;
280
+ }
281
+ }
282
+
283
+ _transition(_from, to) {
284
+ this.state = to;
285
+ }
286
+
287
+ _onSuccess() {
288
+ if (this.state === STATE_HALF) {
289
+ this.consecutiveSuccesses += 1;
290
+ if (this.consecutiveSuccesses >= this.opts.successThreshold) {
291
+ this._transition(STATE_HALF, STATE_CLOSED);
292
+ this.consecutiveFailures = 0;
293
+ this.consecutiveSuccesses = 0;
294
+ }
295
+ } else {
296
+ this.consecutiveFailures = 0;
297
+ }
298
+ }
299
+
300
+ _onFailure(err) {
301
+ if (err && err.permanent) return;
302
+ if (err && err.isObjectStoreError && err.code === "CIRCUIT_OPEN") return;
303
+ this.consecutiveFailures += 1;
304
+ this.consecutiveSuccesses = 0;
305
+ if (this.state === STATE_HALF) {
306
+ this._transition(STATE_HALF, STATE_OPEN);
307
+ this.openedAt = Date.now();
308
+ } else if (this.state === STATE_CLOSED && this.consecutiveFailures >= this.opts.failureThreshold) {
309
+ this._transition(STATE_CLOSED, STATE_OPEN);
310
+ this.openedAt = Date.now();
311
+ }
312
+ }
313
+
314
+ getState() { return this.state; }
315
+
316
+ reset() {
317
+ this.state = STATE_CLOSED;
318
+ this.consecutiveFailures = 0;
319
+ this.consecutiveSuccesses = 0;
320
+ this.openedAt = 0;
321
+ }
322
+ }
323
+
324
+ module.exports = {
325
+ withRetry: withRetry,
326
+ isRetryable: isRetryable,
327
+ backoffDelay: backoffDelay,
328
+ CircuitBreaker: CircuitBreaker,
329
+ DEFAULT_RETRY: DEFAULT_RETRY,
330
+ DEFAULT_BREAKER: DEFAULT_BREAKER,
331
+ RETRYABLE_HTTP_STATUS: Array.from(RETRYABLE_HTTP_STATUS),
332
+ NON_RETRYABLE_HTTP_STATUS: Array.from(NON_RETRYABLE_HTTP_STATUS),
333
+ RETRYABLE_NET_ERRORS: Array.from(RETRYABLE_NET_ERRORS),
334
+ STATES: { CLOSED: STATE_CLOSED, OPEN: STATE_OPEN, HALF_OPEN: STATE_HALF },
335
+ };