@blamejs/exceptd-skills 0.16.28 → 0.16.30

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/sbom.cdx.json CHANGED
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "bomFormat": "CycloneDX",
3
3
  "specVersion": "1.6",
4
- "serialNumber": "urn:uuid:2eefe0b3-a311-474a-9600-c6f1d3c9189f",
4
+ "serialNumber": "urn:uuid:a7c95fa5-56fc-47e1-9190-3c7136d591ca",
5
5
  "version": 1,
6
6
  "metadata": {
7
- "timestamp": "2050-12-15T06:22:43.000Z",
7
+ "timestamp": "2115-03-16T22:18:13.000Z",
8
8
  "tools": [
9
9
  {
10
10
  "vendor": "blamejs",
11
11
  "name": "scripts/refresh-sbom.js",
12
- "version": "0.16.28"
12
+ "version": "0.16.30"
13
13
  }
14
14
  ],
15
15
  "component": {
16
- "bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.16.28",
16
+ "bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.16.30",
17
17
  "type": "application",
18
18
  "name": "@blamejs/exceptd-skills",
19
- "version": "0.16.28",
19
+ "version": "0.16.30",
20
20
  "description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation. 51 skills, 11 catalogs (439 CVEs / 177 CWEs / 805 ATT&CK + ICS / 170 ATLAS / 468 D3FEND / 8888 RFCs), 35 jurisdictions, 10-class catalog gap detector + budget gate, real XML parser + canonical-form diff + content-pattern regression detection, Ed25519-signed.",
21
21
  "licenses": [
22
22
  {
@@ -25,17 +25,17 @@
25
25
  }
26
26
  }
27
27
  ],
28
- "purl": "pkg:npm/%40blamejs/exceptd-skills@0.16.28",
28
+ "purl": "pkg:npm/%40blamejs/exceptd-skills@0.16.30",
29
29
  "hashes": [
30
30
  {
31
31
  "alg": "SHA-256",
32
- "content": "f57896f38f87ddfbf94c435d4231c4101c7803acad61487eea8b1161045876a5"
32
+ "content": "c1bd30e9ed811a98d591a42f6afbfbaa84fd44ef183e7897ad80551fc28b9736"
33
33
  }
34
34
  ],
35
35
  "externalReferences": [
36
36
  {
37
37
  "type": "distribution",
38
- "url": "https://www.npmjs.com/package/@blamejs/exceptd-skills/v/0.16.28"
38
+ "url": "https://www.npmjs.com/package/@blamejs/exceptd-skills/v/0.16.30"
39
39
  },
40
40
  {
41
41
  "type": "vcs",
@@ -116,11 +116,11 @@
116
116
  "hashes": [
117
117
  {
118
118
  "alg": "SHA-256",
119
- "content": "615a8b962b2fbcefafc27353e90490d437c93ea5929fda0ad08764f3c8579674"
119
+ "content": "673ca71c12d4d15633bb8aef96c9894e153d2ef878c51ace03de99e3ef59e924"
120
120
  },
121
121
  {
122
122
  "alg": "SHA3-512",
123
- "content": "7500cd8b9dae1b4e967d0489cddfb7afdb461d00e956dd411f044e7f302327a23d6ab2d9315d784082c3a6eba9bbe9cfa6e09b935ef31f4e30983cf9ba169e89"
123
+ "content": "ae11ee07cfeff030fa9cab9d3a668b160a8859d27fa15abad8c2fa9f63f39eaeb45806cd64cc45f23b919a74b682ca0122df10270b3bc10cdb3c56c470f0da5e"
124
124
  }
125
125
  ]
126
126
  },
@@ -176,11 +176,11 @@
176
176
  "hashes": [
177
177
  {
178
178
  "alg": "SHA-256",
179
- "content": "6e9322e4eaf27c972ff06508673b3e5bd161cf86f407c0c5c9d953a2f6b2da9b"
179
+ "content": "e7b854e7db9a364a1b368b5084b4f0c2a8282f0459ce39800ac1d1dabdc06074"
180
180
  },
181
181
  {
182
182
  "alg": "SHA3-512",
183
- "content": "9bd89f3abf9b68844dfec01694de45fcdb70e9ae0225d17c1a31839d0d0512a87f5b305ec1890357d0625b2feafb6dc292c3c6d3454cabbb7dc05f43fce07a0d"
183
+ "content": "8c0af6e6ca9c5753f726b940b5a0cf948abd61c552c3779d4c3b3ee6950657a4713815926c5cda3d743256b8f580865986de9992167ce1f476b3dd0bd5557ee1"
184
184
  }
185
185
  ]
186
186
  },
@@ -281,11 +281,11 @@
281
281
  "hashes": [
282
282
  {
283
283
  "alg": "SHA-256",
284
- "content": "669897636b4b0e4ea13d0ebd0fba261c09188a0b3a1a06d4596fa77f24ea497a"
284
+ "content": "17553af5707a5bf163f76eb28c62bca472d7d9cb74c5d2fb5eb7bf18ab63bde8"
285
285
  },
286
286
  {
287
287
  "alg": "SHA3-512",
288
- "content": "a8770edb4e20e5d1995aad8ba73cdf22db9f476012238d750dd4bf3008a557e75d70333b6c4993b653201469557af18a59286d8a3c268c8bdda06f6ea535b900"
288
+ "content": "05a98e18e6e13d94ee77b95bcb5e22288b5780c1279d89549e9683fce3661165c2e9578ac08ef0732543fb51f59e9588fe6a0141a498a5e91e9afa07766f21f0"
289
289
  }
290
290
  ]
291
291
  },
@@ -566,11 +566,11 @@
566
566
  "hashes": [
567
567
  {
568
568
  "alg": "SHA-256",
569
- "content": "1f5f749e6fbf82fedef78789dd90ead2bb5bb159a2c7723f67f26d977b4f1108"
569
+ "content": "68e5e75851ba4023585726e3c95c8eed651e0e35c8519edf9399addedbbef25b"
570
570
  },
571
571
  {
572
572
  "alg": "SHA3-512",
573
- "content": "6d425bc941f84d430392daad961ddba8f6d8c7fb1082fd8f117c3d3af6c8b8b0ab1e3b96ff86aaa5f8d1b2bc6dae19a517c90d78bafb092a8d70dc990efabfcc"
573
+ "content": "11b1935f75c8b77b50f73cf64ac5e8aafeeddae172d6cdd9e036c6e6348ad3587dd0a173243f0db4c579dae2fef9bf5eeaeb742271588b644ad5edc814ef5493"
574
574
  }
575
575
  ]
576
576
  },
@@ -986,11 +986,11 @@
986
986
  "hashes": [
987
987
  {
988
988
  "alg": "SHA-256",
989
- "content": "c84a7d815cba16b8cce07e782400853fb3e9adfe56fcb8cdfe4a6e784e8c619f"
989
+ "content": "081583535b98f300966c656ba007858127506f4d2853a62f8f5084984d99a3ef"
990
990
  },
991
991
  {
992
992
  "alg": "SHA3-512",
993
- "content": "d1c21684b8db41e278e58c7bbc80e79bbfbebcc6993e7527c3d6b32d83754c335647aa590fbf7f72d524f66e8366310c2157e030b1ddabbcf3bd29f63e3763e7"
993
+ "content": "1297d553949f1501518f9c8d4f2c133cb92a0ab49aacde2bd18b3f883809fb340036a960cc4ded99828a351a4756cba38fd37ba3688903049f17888af0f9c411"
994
994
  }
995
995
  ]
996
996
  },
@@ -1031,11 +1031,11 @@
1031
1031
  "hashes": [
1032
1032
  {
1033
1033
  "alg": "SHA-256",
1034
- "content": "92a4cf99ef6db17200871f911558b7cfb666cbefbabde4ea5e9617f9632efa3c"
1034
+ "content": "f8b834f2b9615aef61f2ab07c9ff4c1242c9634a3636eec166fbdcdca7c616f0"
1035
1035
  },
1036
1036
  {
1037
1037
  "alg": "SHA3-512",
1038
- "content": "b589b86776dbf88fe224239332e15728a92906fbae75efff844f2aeed1b3168cd6fb4f6e1a99b46fc1e09d29275dea308239905141cdb6409a44f829a932dd86"
1038
+ "content": "667b0cac8ce4d14ce648611de8696165fa64bdf6147d34144252c96edd4dfc6d01fce3be4825c6fabc00ba27a49a431da0a48e9cb4c69f50534ac7aabdc1053e"
1039
1039
  }
1040
1040
  ]
1041
1041
  },
@@ -1181,11 +1181,11 @@
1181
1181
  "hashes": [
1182
1182
  {
1183
1183
  "alg": "SHA-256",
1184
- "content": "a9b7fd5e3b4fae07ac1734d59dada55b904aac727197298efb3394c59feb9469"
1184
+ "content": "d5962bed4fda430834283e9ec557161ba7e2c4f5f964f8fd45f4a1723a8cd622"
1185
1185
  },
1186
1186
  {
1187
1187
  "alg": "SHA3-512",
1188
- "content": "6e4216872af0f849a64163ce9f8963b4ca875208a9868ba0f55cb6319362194bb6f5db657f11cd636c0da58ac9460ad8df638c5b5a8d34a5855dc07cf6d574a9"
1188
+ "content": "39006cdae4faf916cb1c05d729c29f5a7cb4c1535fedfc59a57a6ac5c38a449e195c05dc23aff1465cff0de720e2efa07a9e8dd5a2e573561b72d411da88e515"
1189
1189
  }
1190
1190
  ]
1191
1191
  },
@@ -1256,11 +1256,11 @@
1256
1256
  "hashes": [
1257
1257
  {
1258
1258
  "alg": "SHA-256",
1259
- "content": "9cc57e688ef2812e687db325264f9c1d7b57d7bcb907e697bbd98e02fa01e09d"
1259
+ "content": "0f2fadb970f21ee2c04573d97fd22857d26b39925d11ea1a9dff3f07b5c3d0ae"
1260
1260
  },
1261
1261
  {
1262
1262
  "alg": "SHA3-512",
1263
- "content": "337b7ce0afcf1fa521286d7f5506fc06db348ab6cabddfa5f20c4a72ac8b329e6be5d429119f550371709606f9fba7d88bec65c2643a579d334903c2f295e8ae"
1263
+ "content": "8a2b59dc57a5dad4e53420d465999b16d9ca949b95846293ee1dc088709df9dcabc7994e47385c0f1471039556f4e2d867c6e7d70f59c51b345c32f52f0e30fa"
1264
1264
  }
1265
1265
  ]
1266
1266
  },
@@ -1271,11 +1271,11 @@
1271
1271
  "hashes": [
1272
1272
  {
1273
1273
  "alg": "SHA-256",
1274
- "content": "30bf5cc91adfcdec053c1680aa4d54dff4d8c74d0f2b93b03cc4f7f5a76a47d8"
1274
+ "content": "503037e4f50d6fc4ff6ebb972b3b4c3663003c5d9902df52aec0c3f3408f9e47"
1275
1275
  },
1276
1276
  {
1277
1277
  "alg": "SHA3-512",
1278
- "content": "7ad94c3de7a88a6d1e1c4671235c3aece4c911e21c7b36e42514920814dd5191110e49eec3bd2f41fd329f5fd67832b101d40cbc031dbd274fb52b8d33446df0"
1278
+ "content": "c3dde0efa5762c8466eb45ebe93ba61f0f7c0772ec87731b9f7c7994b687ef8deacc5a952f9fd68b96c658b9fd21ee7418845fdbadd4df0228e8e6e22c46d9c7"
1279
1279
  }
1280
1280
  ]
1281
1281
  },
@@ -1451,11 +1451,11 @@
1451
1451
  "hashes": [
1452
1452
  {
1453
1453
  "alg": "SHA-256",
1454
- "content": "b6b3ac05cb9b5d0c86a1966656e4e0ea5b7d2b187c12f73853c2fedba1d61185"
1454
+ "content": "2a488a8dcbb25e0e46dd04e6c8294406f3f75833ff3b2e59fdc9ba3e589df5c8"
1455
1455
  },
1456
1456
  {
1457
1457
  "alg": "SHA3-512",
1458
- "content": "256ca28b696c261766f47c57328088dc87c89d56998064d10072ee6f1ffe597d8f4ff565e6599ca947d0ede47020a272e7ce5f565fa5ded54f1e95b11a5b4022"
1458
+ "content": "39ec71547e6c9c9823749ae0248f886af234358e6937da59001ae5cd3bb846a7134b0cbf15f5a086f80b2eec1d0a9ebee96d01568559930a5ac560235b19a246"
1459
1459
  }
1460
1460
  ]
1461
1461
  },
@@ -1466,11 +1466,11 @@
1466
1466
  "hashes": [
1467
1467
  {
1468
1468
  "alg": "SHA-256",
1469
- "content": "50efed9848abc76cc27b89f2d3ec1539e7945ead8f782dd6a50b8bd9e50aeea1"
1469
+ "content": "59179357f3ebc1cae07ca63f6e53441e1f5ce001491b0a71c03b00270403a7c7"
1470
1470
  },
1471
1471
  {
1472
1472
  "alg": "SHA3-512",
1473
- "content": "2cf21e6aaf8fd15d6ea64a25cc142c05d45919f670f324eb95ae47f6e8b07832d768e5c2c61946b5673678831fc5278f6b2e579159a264715c91865bf2191e6f"
1473
+ "content": "b2f8c4ebda7ada3125f8b6cb56fedf7b6072606130cba59c29679df22161162774d7a43e9c3a1b8860ada5320f18ee9d771cd20b48a324c4f2218afd42b0a03d"
1474
1474
  }
1475
1475
  ]
1476
1476
  },
@@ -1481,11 +1481,11 @@
1481
1481
  "hashes": [
1482
1482
  {
1483
1483
  "alg": "SHA-256",
1484
- "content": "114c882a96d57423de635cb22e965136e1045faa53068f8adb927a5a8bbf811b"
1484
+ "content": "f9c0e300bcce3371b036f7c578470ee80b6bcf33fc9e618e4377c527b889f0a0"
1485
1485
  },
1486
1486
  {
1487
1487
  "alg": "SHA3-512",
1488
- "content": "580512899a90461ad6e3ec4bd104e300a8aa48d2e6f30092de4b993ad2666616728d2abec0d8ac97c39d1b24917ead6ef76906b5113cc8fe3d64544951b7d0e7"
1488
+ "content": "045c5a90c33b7bff92f1fbfb783e573e1819ab8a5980a2bd2c9347502b0b02e87176aa1ac1238c030018cb8d50c4bd1484c434c82e2b3882e2826b45b976f000"
1489
1489
  }
1490
1490
  ]
1491
1491
  },
@@ -1496,11 +1496,11 @@
1496
1496
  "hashes": [
1497
1497
  {
1498
1498
  "alg": "SHA-256",
1499
- "content": "c344332e0b7650fe54e07041726c73395749c825906fc82e8fb8cc82105ab871"
1499
+ "content": "ad595c63a137b7bb85ff581897cfc8bbdf7e7f46a247e40245a14f564b8a1c07"
1500
1500
  },
1501
1501
  {
1502
1502
  "alg": "SHA3-512",
1503
- "content": "6f13b6997a326ef7e6b6435102b2c33d03016b4c5e27208971ae18215e96cc7093f56ae220a827e835c69a0c45533aa580205849e9425878ce6d9aef8625b4af"
1503
+ "content": "8cfd603e5d873730e393d678380568d29725e05d37f1d6cf876e54ea186c0912ad30aa0f5135a23fa959fe141b40034f08742e5aac07b0303e4a728e192b8070"
1504
1504
  }
1505
1505
  ]
1506
1506
  },
@@ -1601,11 +1601,11 @@
1601
1601
  "hashes": [
1602
1602
  {
1603
1603
  "alg": "SHA-256",
1604
- "content": "a8060a33a09bf90b1b9b8b212df217f7918f5edb7984e08071997e39b548716a"
1604
+ "content": "83d6e9b8afc4c9158ec49a641d6838e06d4189dd0b3e7e8e96ab013a54d05d97"
1605
1605
  },
1606
1606
  {
1607
1607
  "alg": "SHA3-512",
1608
- "content": "068c678005d8e020f09c36ca7f3207889e911b479ffd8d4f2115bb1dd910def25f6bbfd81d7f299853581096414625e3cdbb47260eff4f4ab50ba715ee891994"
1608
+ "content": "fe6a305dca12f5ee5c8f51f13aed88307a7ab87ec8f800fe4cf12e7aefe5e2db6a2efc25fc8297f61072d0af4f010fec813211e5cb0778fa7f8ce14a4e5c34af"
1609
1609
  }
1610
1610
  ]
1611
1611
  },
@@ -1736,11 +1736,11 @@
1736
1736
  "hashes": [
1737
1737
  {
1738
1738
  "alg": "SHA-256",
1739
- "content": "bc25508f8e773b64dd7ad575c7a7075cb25e5eae198605f228dbd8a40c7a0cd2"
1739
+ "content": "f5ec0535d2e0712654a6dff2952e66b7de2044afb03ab6422ba0b1597779d782"
1740
1740
  },
1741
1741
  {
1742
1742
  "alg": "SHA3-512",
1743
- "content": "5e7d78ab311e4f4de57793ace6065bfa9699d0aa3a35d70a0d1d629a96ab51bed4460e86e391eddf198151cdcd6c02491c64ad5a89ea3cbb905092e43a0782a1"
1743
+ "content": "17a5d85d096aa1744202eb076c72ac8f9ba61a595795d45a06ff9f4628a21f654b38752ee04beb13dc6048945fa9f89f9b204e386503bb200e4a31d93206ab99"
1744
1744
  }
1745
1745
  ]
1746
1746
  },
@@ -1751,11 +1751,11 @@
1751
1751
  "hashes": [
1752
1752
  {
1753
1753
  "alg": "SHA-256",
1754
- "content": "41a71d0bf1cff279a5b501a9a40a1874ab5a7c6a5e66ded23f8761899f24fc50"
1754
+ "content": "b574dffe09c2881e4cae3a4676aa0396950263e755349c677e94343945f435a9"
1755
1755
  },
1756
1756
  {
1757
1757
  "alg": "SHA3-512",
1758
- "content": "d3ee7b39c607f47b1172aee89bc99af55ba4342e609232005a540270ff88a2f1b7ff6852d00eb260560bbd88fad6ececf9fd78967ae32fecb949f66438cd4e1a"
1758
+ "content": "8cdea5fbb52cf82fd543d1333375359708ca1b7ce172bbaf81fc5cd6374715dedc62b3a2249da685808c02cf817086b795e1510c175b5ea33c25a54e8bdcb4b2"
1759
1759
  }
1760
1760
  ]
1761
1761
  },
@@ -1781,11 +1781,11 @@
1781
1781
  "hashes": [
1782
1782
  {
1783
1783
  "alg": "SHA-256",
1784
- "content": "9e034e2169c9d10a5fd46d7c0870a5df6982a07a674bd20442bd9b14e2dd4d0c"
1784
+ "content": "dd4c2bdee021c4a2c7f0b7c50dc287838e1be60d4e85bb7447ca4575bf0b93f1"
1785
1785
  },
1786
1786
  {
1787
1787
  "alg": "SHA3-512",
1788
- "content": "05e672ddfb4e0d21ac8d175fd9830a9e2dbd29d2b63c13da1c6db99a3b7fd2684c3deb2daabb7ca91023d8c4b7bf7aa755dbac6e8adc067577b185be453777fa"
1788
+ "content": "b52322b974b16541d67339a317a72e37c90b52b089776d55686e174de9075bbdb8543469533011446b1f04c46312bd1be438cacb1b3e3e6ec14d92900040bfcd"
1789
1789
  }
1790
1790
  ]
1791
1791
  },
@@ -1901,11 +1901,11 @@
1901
1901
  "hashes": [
1902
1902
  {
1903
1903
  "alg": "SHA-256",
1904
- "content": "21f2f84671301efb38afbaad51f8d06fa46137747d078d94c439defa669c114b"
1904
+ "content": "70fea689545e1145b6e4e55621b07083d54e657372d1293406697cbcdd216fbb"
1905
1905
  },
1906
1906
  {
1907
1907
  "alg": "SHA3-512",
1908
- "content": "d6794e16570d6739b56e4124598ad36b4f9c2057d138942e89d867f91479ba40064ed5ed186744afe1347e22b7aab464f3f61bdf92bce62d6714554379de2b85"
1908
+ "content": "1bf4b7ec8dfa0661f5219a20572816d8bfc9b3c4bb83651f4ba07959063d28099ea519ca0401fcc1d38d5fb7658699453ba1ed71fa6dfdaca7fd615b056ffadc"
1909
1909
  }
1910
1910
  ]
1911
1911
  },
@@ -1976,11 +1976,11 @@
1976
1976
  "hashes": [
1977
1977
  {
1978
1978
  "alg": "SHA-256",
1979
- "content": "5f403396c73e40ca6963fe3fe71d4a2dd5637710d2d72d616d3f2b76aa46a21a"
1979
+ "content": "515a7c8b3ec6814d45c35a8243b30e71c900dfc4016adb5201b9bbecb047d1fd"
1980
1980
  },
1981
1981
  {
1982
1982
  "alg": "SHA3-512",
1983
- "content": "8d4253e780b5a3a7a84185b4eee8ca5905303419445a669d8ed6c6a6a1531f17012af8f187f7a99620047276a7b5828679ecb37ada184515579b95a9a736f85e"
1983
+ "content": "58ef4fcb1a6d5cb7f9f75046dfa63fc7c732440932f76acc31981a7edc0f5dbfacea8f5d30709aecbcb05331332f39921ae5e766a068403913c6d753b2136de3"
1984
1984
  }
1985
1985
  ]
1986
1986
  },
@@ -2096,11 +2096,11 @@
2096
2096
  "hashes": [
2097
2097
  {
2098
2098
  "alg": "SHA-256",
2099
- "content": "6e2b39f275866812938a5e9b7105eb7dfb201a45c2cb6ea64ba60e5ad37600e6"
2099
+ "content": "9f54c09e25593d82ba36bffcf5ee6b8137eab9e1f5408b7cf6cb681a69806d4c"
2100
2100
  },
2101
2101
  {
2102
2102
  "alg": "SHA3-512",
2103
- "content": "4eaee5df87cc6565d8b4e708bd0219135a901f570f34bc8e15f37e9f42d7270a464ffee895743a05b9b4fd446b4147a6f8fd36de546342e5724e7dbed0536e8f"
2103
+ "content": "9711d20338cd19da03cb50d089aa42ce5c8f45513d92523a84572494337d88654a29bedc991009ba4522346d3b04506621974707a537c1e24ee1d985017d113f"
2104
2104
  }
2105
2105
  ]
2106
2106
  },
@@ -2396,11 +2396,11 @@
2396
2396
  "hashes": [
2397
2397
  {
2398
2398
  "alg": "SHA-256",
2399
- "content": "0dfd0589ba86278f1b04d1deb98429b64f5714e3a9d51c35b1bff1eca2e11ac5"
2399
+ "content": "3fcc2abf934ee1b70674856ba937833830d45346b4f146d613e500b9a9b4d163"
2400
2400
  },
2401
2401
  {
2402
2402
  "alg": "SHA3-512",
2403
- "content": "ee4b3a028a1b98c3a5d8071f25ff254cbe12c21d46292f3de42f2ac92b5e70ae2da1062a94cdf45ac0fd68d01e6641e824e6175aa5423d1f5957cdf9b83ec296"
2403
+ "content": "1cc3b832434aa188fc7136feadb286c68d528e1e35406572bbaaf29a1b21be90ca59f3a8ea96d7173e7365e6c7b9248fdb45dcb6c56bbeec93ede95341ca5720"
2404
2404
  }
2405
2405
  ]
2406
2406
  },
@@ -2606,11 +2606,11 @@
2606
2606
  "hashes": [
2607
2607
  {
2608
2608
  "alg": "SHA-256",
2609
- "content": "c70973d1c3ecf755361539423b6a41d9d598f25527c64a116c63a5bab240bcbd"
2609
+ "content": "bba34316450d9bb0e6aa60e75dfcb28bdc767487d13ca429dbc654772a18938b"
2610
2610
  },
2611
2611
  {
2612
2612
  "alg": "SHA3-512",
2613
- "content": "b5356776cd94758a64c4b8d7e66e2b8eaf027136c878fe0fe1a404e8ce22fd2826346b5b547e3db67e1c73c001e09be007a0a1b4c968ca6c8e58235a28032233"
2613
+ "content": "41e269280701ba73957c7d747f019568c23d5c5e6a19c6f7a5153c0211937a673df33e81b0f7efe286ebd36a50789bbbc45b8d145fb94f7800008021cb7f9530"
2614
2614
  }
2615
2615
  ]
2616
2616
  },
@@ -2651,11 +2651,11 @@
2651
2651
  "hashes": [
2652
2652
  {
2653
2653
  "alg": "SHA-256",
2654
- "content": "3e28efadd6ac999e3995b7722f3a1e54a9d173dc73f4dcd1de1454e4ed774020"
2654
+ "content": "fbf31669b2d177ae643e480f4fad5ea60b7af8ab32617add0350757bd9dcce9e"
2655
2655
  },
2656
2656
  {
2657
2657
  "alg": "SHA3-512",
2658
- "content": "809f89461ef89035f19bcee7df8fc42b5532a74039b9552fb025a1761f6e8f040ee3f6a6c67be1596d829246da5618c4ca859ac4980fdbb4d775dd2cb14650c6"
2658
+ "content": "5e6b83c43ae77337b7b600d54ce6ecc168ee6fe7401aa154f0da58d13b1f21cf784221dda481895c7721595160d6a8b59093fdb9ea2dccb2eed1fa34f1aaea46"
2659
2659
  }
2660
2660
  ]
2661
2661
  },
@@ -2674,6 +2674,21 @@
2674
2674
  }
2675
2675
  ]
2676
2676
  },
2677
+ {
2678
+ "bom-ref": "file:scripts/sync-package-description.js",
2679
+ "type": "file",
2680
+ "name": "scripts/sync-package-description.js",
2681
+ "hashes": [
2682
+ {
2683
+ "alg": "SHA-256",
2684
+ "content": "4110a273512bf43b9246f5ab4c196008c9043778b4137dca8a459df7ca6066de"
2685
+ },
2686
+ {
2687
+ "alg": "SHA3-512",
2688
+ "content": "427e94caa4b48f2a4f0421cc9924e7c9b626032a7d78df684e0e63743331caf16da65a345f88f90c316aa6c0ae95d29924d69d1cb8d92e582bf4e376629428a0"
2689
+ }
2690
+ ]
2691
+ },
2677
2692
  {
2678
2693
  "bom-ref": "file:scripts/validate-vendor-online.js",
2679
2694
  "type": "file",
@@ -2696,11 +2711,11 @@
2696
2711
  "hashes": [
2697
2712
  {
2698
2713
  "alg": "SHA-256",
2699
- "content": "fd04f3e4122b4f3ca7e9a266c763dd4e954710d496da8072f5c2e500a4dbe32c"
2714
+ "content": "7541cd702c57e7b966b4b1bfffed748dba16f5bb25ff9176be64a50a92fc8e65"
2700
2715
  },
2701
2716
  {
2702
2717
  "alg": "SHA3-512",
2703
- "content": "9b606b4d5afcc79a7a39650c3f425af0a8abb21f484e70e5469431a0be26b27969108bd51f167cab23b41d6e0ec7d14b8e6d82d597ca6166942605e15fc016c0"
2718
+ "content": "15c7bb7f853a04a615d247ff47ac53c1b282cfc56875fd0248843b069d71ce04e3731bb3890b01644d58f0f42e37d362016e4f8176e4dd64ba837043c46f5805"
2704
2719
  }
2705
2720
  ]
2706
2721
  },
@@ -3491,11 +3506,11 @@
3491
3506
  "hashes": [
3492
3507
  {
3493
3508
  "alg": "SHA-256",
3494
- "content": "722ac72d21a820786c1c4cf1d6f5c0838a30267f60ee973ae9b736f15aeebf78"
3509
+ "content": "5410a1ca1ebea4c3d7ff14a9ea5d69dde5d59490f9bae518d1d3b0440a457238"
3495
3510
  },
3496
3511
  {
3497
3512
  "alg": "SHA3-512",
3498
- "content": "105ae5fc896d58bc751fdb484a3a36cad9fa652e89ff27eb00b2877d336314c5f110e0b5ce88bb822915fce31792d71bd2cf8bbad7193bfd0efd77df57fe8d18"
3513
+ "content": "96872e1b74348e5be3d440e3e2265ab14ce35118a4226d7b2a698c36573374120bb663c8c852a67206169b715b7008944941a9a4ef890f7d1afa94e7d105be71"
3499
3514
  }
3500
3515
  ]
3501
3516
  },
@@ -266,6 +266,13 @@ const OUTPUTS = [
266
266
  for (const s of ctx.skills) {
267
267
  const body = ctx.skillBodies[s.name];
268
268
  for (const code of codes) {
269
+ // Skip bare 2-letter ISO codes in free-text matching. `\bID\b`,
270
+ // `\bCA\b`, `\bNO\b` etc. collide with prose words ("the ID",
271
+ // "US-based") and control/countermeasure id grammar (`\bCA\b` matches
272
+ // inside `D3-CA`, `\bSA\b` inside `SA-12`), polluting coverage
273
+ // (Indonesia landed on 41/51 skills). These jurisdictions are mapped
274
+ // via the curated NAME_TO_CODE regulation-name table below instead.
275
+ if (code.length <= 2) continue;
269
276
  const re = new RegExp("\\b" + code + "\\b");
270
277
  if (re.test(body) && !out[code].skills.includes(s.name)) out[code].skills.push(s.name);
271
278
  }
@@ -499,7 +506,7 @@ const OUTPUTS = [
499
506
  {
500
507
  name: "stale-content",
501
508
  file: "stale-content.json",
502
- deps: [isManifest, isAnySkillBody, isAnyCatalog],
509
+ deps: [isManifest, isAnySkillBody, isAnyCatalog, (p) => p === "README.md"],
503
510
  build: (ctx) => {
504
511
  const { buildStaleContent } = require("./builders/stale-content");
505
512
  return buildStaleContent({ root: ctx.root, manifest: ctx.manifest, skills: ctx.skills, catalogFiles: ctx.catalogFiles });
@@ -518,6 +525,10 @@ function loadPriorMeta() {
518
525
  function liveSourceSet(ctx) {
519
526
  const out = new Set();
520
527
  out.add("manifest.json");
528
+ // README.md is consumed by the stale-content builder (badge-count drift), so
529
+ // it must be a hashed source — otherwise a README edit is invisible to
530
+ // --changed and the validate-indexes freshness gate.
531
+ if (fs.existsSync(ABS("README.md"))) out.add("README.md");
521
532
  for (const c of ctx.catalogFiles) out.add(c);
522
533
  for (const s of ctx.skills) out.add(s.path);
523
534
  return out;
@@ -136,19 +136,42 @@ function checkSbomCurrency(root) {
136
136
  );
137
137
  }
138
138
 
139
- // component-level cross-check. A renamed or version-bumped
140
- // skill that never made it into the SBOM refresh will pass the count
141
- // check (the cardinality is unchanged) but the per-component name +
142
- // version comparison surfaces it. Two component classes are recognised:
143
- //
144
- // 1. Skill components bom-ref begins with "skill:" OR the component
145
- // name matches a manifest.skills[].name. Each one must exist in
146
- // manifest.skills with the same version.
147
- // 2. Vendor components — bom-ref begins with "vendor:". Validated
148
- // against vendor/blamejs/_PROVENANCE.json when present.
149
- //
150
- // Components that don't fit either pattern are surfaced as warnings
151
- // (not errors) so the gate isn't brittle against future component types.
139
+ // The "N catalogs" and "N jurisdictions" free-text counts in the same
140
+ // description string were never validated only the per-catalog entry tokens
141
+ // and the skill count were. Pin them to the live values so a stale
142
+ // description (e.g. after an auto-refresh changed a count) fails the gate.
143
+ const catalogMatch = description.match(/(\d+)\s+catalogs?\b/i);
144
+ if (catalogMatch && Number(catalogMatch[1]) !== liveCatalogs) {
145
+ errors.push(
146
+ `SBOM description catalog count is ${Number(catalogMatch[1])} but live data/ has ${liveCatalogs} catalogs — description is stale; update package.json.description and \`npm run refresh-sbom\``
147
+ );
148
+ }
149
+ const liveJurisdictions = (() => {
150
+ try {
151
+ const gf = JSON.parse(fs.readFileSync(path.join(dataDir, "global-frameworks.json"), "utf8"));
152
+ // Non-underscore top-level keys — the canonical jurisdiction count the
153
+ // README badge and catalog-summaries use.
154
+ return Object.keys(gf).filter((k) => !k.startsWith("_")).length;
155
+ } catch {
156
+ return null;
157
+ }
158
+ })();
159
+ const jurisdictionMatch = description.match(/(\d+)\s+jurisdictions?\b/i);
160
+ if (liveJurisdictions !== null && jurisdictionMatch && Number(jurisdictionMatch[1]) !== liveJurisdictions) {
161
+ errors.push(
162
+ `SBOM description jurisdiction count is ${Number(jurisdictionMatch[1])} but live global-frameworks.json has ${liveJurisdictions} — description is stale; update package.json.description and \`npm run refresh-sbom\``
163
+ );
164
+ }
165
+
166
+ // Component-level cross-check (defense-in-depth). In normal operation
167
+ // refresh-sbom emits NO per-skill "skill:" components — skill drift is caught
168
+ // by the file:skills/<name>/skill.md and file:manifest.json content hashes in
169
+ // the file: component pass below (a bumped or renamed skill changes those
170
+ // bytes). This branch is therefore not exercised by a clean SBOM, but it is
171
+ // retained as a tamper guard: a forged or buggy SBOM that injected a skill
172
+ // component with a stale version (or a skill name no longer in the manifest)
173
+ // is still caught here. Vendor components are validated against
174
+ // vendor/blamejs/_PROVENANCE.json.
152
175
  const components = Array.isArray(sbom.components) ? sbom.components : [];
153
176
  const skillByName = new Map(
154
177
  (manifest.skills || []).map((s) => [s.name, s])
@@ -281,6 +304,45 @@ function checkSbomCurrency(root) {
281
304
  fileComponentsChecked++;
282
305
  }
283
306
 
307
+ // Completeness + bundle-digest integrity. The per-file pass above verifies
308
+ // every RECORDED file: component, but never checked that every SHIPPED file
309
+ // (the package.json.files expansion) actually HAS a component — a
310
+ // newly-shipped file would ship unhashed and silent. And the aggregate
311
+ // bundle digest in metadata.component.hashes[] was never recomputed. Reuse
312
+ // refresh-sbom's exact allowlist expansion + digest so the gate can't drift
313
+ // from the generator.
314
+ try {
315
+ const { expandAllowlist, bundleDigest } = require("./refresh-sbom");
316
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
317
+ const expected = expandAllowlist(pkg.files || []);
318
+ const fileComps = components.filter(
319
+ (c) => typeof c["bom-ref"] === "string" && c["bom-ref"].startsWith("file:")
320
+ );
321
+ const fileCompNames = new Set(fileComps.map((c) => c.name));
322
+ for (const rel of expected) {
323
+ if (!fileCompNames.has(rel)) {
324
+ errors.push(
325
+ `Shipped file "${rel}" (package.json.files) has no file: component in the SBOM — run \`npm run refresh-sbom\``
326
+ );
327
+ }
328
+ }
329
+ // Recompute the aggregate bundle digest from the file: components' recorded
330
+ // SHA-256 hashes and compare to metadata.component.hashes[] (the per-file
331
+ // pass already tied each recorded hash to live bytes).
332
+ const compHashes = (sbom.metadata && sbom.metadata.component && sbom.metadata.component.hashes) || [];
333
+ const recorded = (compHashes.find((h) => h && h.alg === "SHA-256") || {}).content;
334
+ if (recorded && fileComps.length) {
335
+ const recomputed = bundleDigest(fileComps);
336
+ if (recomputed !== recorded) {
337
+ errors.push(
338
+ `SBOM bundle digest mismatch: metadata.component.hashes SHA-256 ${String(recorded).slice(0, 12)}… != recomputed ${recomputed.slice(0, 12)}… from file: components — run \`npm run refresh-sbom\``
339
+ );
340
+ }
341
+ }
342
+ } catch (e) {
343
+ errors.push(`SBOM completeness/bundle-digest check failed: ${e.message}`);
344
+ }
345
+
284
346
  return {
285
347
  ok: errors.length === 0,
286
348
  errors,
@@ -310,6 +372,6 @@ function main() {
310
372
  );
311
373
  }
312
374
 
313
- module.exports = { checkSbomCurrency, resolveRoot };
375
+ module.exports = { checkSbomCurrency, resolveRoot, DESCRIPTION_ENTRY_TOKENS, catalogEntryCount };
314
376
 
315
377
  if (require.main === module) main();
@@ -409,4 +409,4 @@ if (require.main === module) {
409
409
  main();
410
410
  }
411
411
 
412
- module.exports = { buildSbom };
412
+ module.exports = { buildSbom, expandAllowlist, bundleDigest };
@@ -55,6 +55,27 @@ function getJsonPath(obj, dotted) {
55
55
  return dotted.split(".").reduce((acc, key) => acc?.[key], obj);
56
56
  }
57
57
 
58
+ // Evaluate the negative stderr guard against raw stderr text. Lives here, NOT
59
+ // inside diffExpect, because the ban must hold regardless of whether stdout
60
+ // parsed as JSON — a scenario whose stdout is a human banner (no JSON body,
61
+ // only an expect_exit assertion) must still enforce a forbidden-token ban on
62
+ // stderr. evaluateScenario calls this unconditionally.
63
+ function stderrBanFailures(expect, stderr) {
64
+ const failures = [];
65
+ if (expect.stderr_must_not_match) {
66
+ for (const regex of expect.stderr_must_not_match) {
67
+ if (new RegExp(regex).test(stderr || "")) {
68
+ failures.push(`stderr_must_not_match /${regex}/: stderr contains it`);
69
+ }
70
+ }
71
+ }
72
+ return failures;
73
+ }
74
+
75
+ // Diff a parsed JSON body against the positive expect matchers. The negative
76
+ // stderr guard is NOT evaluated here (see stderrBanFailures); this function
77
+ // only inspects the JSON body so it cannot be silently skipped when stdout
78
+ // fails to parse.
58
79
  function diffExpect(jsonBody, expect, ctx) {
59
80
  const failures = [];
60
81
  if (expect.json_path_equals) {
@@ -89,23 +110,26 @@ function diffExpect(jsonBody, expect, ctx) {
89
110
  }
90
111
  }
91
112
  }
92
- if (expect.stderr_must_not_match) {
93
- for (const regex of expect.stderr_must_not_match) {
94
- if (new RegExp(regex).test(ctx.stderr)) {
95
- failures.push(`stderr_must_not_match /${regex}/: stderr contains it`);
96
- }
97
- }
98
- }
99
113
  return failures;
100
114
  }
101
115
 
102
116
  function tryParseJson(s) {
103
117
  if (!s) return null;
104
- try { return JSON.parse(s.trim()); } catch { /* ignore */ }
105
- // Some verbs may emit trailing logs; pick the LAST complete JSON object on stdout.
118
+ try {
119
+ const v = JSON.parse(s.trim());
120
+ if (v && typeof v === "object") return v;
121
+ } catch { /* ignore */ }
122
+ // Some verbs may emit trailing logs; pick the LAST complete JSON object or
123
+ // array on stdout. A verb envelope is always an object/array, so bare
124
+ // scalars (a trailing JSON-parseable "done"/42/true log line) are skipped —
125
+ // binding assertions against a trailing scalar would silently test the
126
+ // wrong value.
106
127
  const lines = s.trim().split("\n");
107
128
  for (let i = lines.length - 1; i >= 0; i--) {
108
- try { return JSON.parse(lines[i]); } catch { /* keep looking */ }
129
+ try {
130
+ const v = JSON.parse(lines[i]);
131
+ if (v && typeof v === "object") return v;
132
+ } catch { /* keep looking */ }
109
133
  }
110
134
  return null;
111
135
  }
@@ -148,6 +172,12 @@ function evaluateScenario(scenario, expect, res) {
148
172
  failures.push(`stdout did not parse as JSON; first 200 chars: ${stdout.slice(0, 200)}`);
149
173
  }
150
174
  if (body) failures.push(...diffExpect(body, expect, { stdout, stderr, status }));
175
+
176
+ // The forbidden-token ban on stderr runs unconditionally — it does not
177
+ // depend on stdout parsing as JSON. A scenario with only an expect_exit
178
+ // assertion (human-banner stdout) must still fail if stderr carries a banned
179
+ // token.
180
+ failures.push(...stderrBanFailures(expect, stderr));
151
181
  return failures;
152
182
  }
153
183
 
@@ -266,6 +296,6 @@ function main() {
266
296
  process.exit(failed.length === 0 ? 0 : 1);
267
297
  }
268
298
 
269
- module.exports = { evaluateScenario, diffExpect, runScenario };
299
+ module.exports = { evaluateScenario, diffExpect, tryParseJson, stderrBanFailures, runScenario, SCENARIO_DIR };
270
300
 
271
301
  if (require.main === module) main();