@skillsmith/core 0.5.3 → 0.5.5

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 (276) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/activation/ActivationManager.d.ts +7 -0
  4. package/dist/src/activation/ActivationManager.d.ts.map +1 -1
  5. package/dist/src/activation/ActivationManager.js +13 -4
  6. package/dist/src/activation/ActivationManager.js.map +1 -1
  7. package/dist/src/analysis/adapters/python.d.ts +16 -11
  8. package/dist/src/analysis/adapters/python.d.ts.map +1 -1
  9. package/dist/src/analysis/adapters/python.js +46 -61
  10. package/dist/src/analysis/adapters/python.js.map +1 -1
  11. package/dist/src/analysis/router.test.d.ts +2 -0
  12. package/dist/src/analysis/router.test.d.ts.map +1 -0
  13. package/dist/src/analysis/router.test.js +411 -0
  14. package/dist/src/analysis/router.test.js.map +1 -0
  15. package/dist/src/analysis/tree-sitter/manager.d.ts.map +1 -1
  16. package/dist/src/analysis/tree-sitter/manager.js +12 -5
  17. package/dist/src/analysis/tree-sitter/manager.js.map +1 -1
  18. package/dist/src/analysis/tree-sitter/pythonExtractor.d.ts +45 -0
  19. package/dist/src/analysis/tree-sitter/pythonExtractor.d.ts.map +1 -0
  20. package/dist/src/analysis/tree-sitter/pythonExtractor.js +264 -0
  21. package/dist/src/analysis/tree-sitter/pythonExtractor.js.map +1 -0
  22. package/dist/src/analysis/tree-sitter/pythonExtractor.test.d.ts +12 -0
  23. package/dist/src/analysis/tree-sitter/pythonExtractor.test.d.ts.map +1 -0
  24. package/dist/src/analysis/tree-sitter/pythonExtractor.test.js +74 -0
  25. package/dist/src/analysis/tree-sitter/pythonExtractor.test.js.map +1 -0
  26. package/dist/src/analysis/tree-sitter/pythonIncremental.d.ts +93 -0
  27. package/dist/src/analysis/tree-sitter/pythonIncremental.d.ts.map +1 -0
  28. package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.d.ts +22 -0
  29. package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.d.ts.map +1 -0
  30. package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.js +229 -0
  31. package/dist/src/analysis/tree-sitter/pythonIncremental.hardening.test.js.map +1 -0
  32. package/dist/src/analysis/tree-sitter/pythonIncremental.js +287 -0
  33. package/dist/src/analysis/tree-sitter/pythonIncremental.js.map +1 -0
  34. package/dist/src/analysis/tree-sitter/pythonIncremental.test.d.ts +17 -0
  35. package/dist/src/analysis/tree-sitter/pythonIncremental.test.d.ts.map +1 -0
  36. package/dist/src/analysis/tree-sitter/pythonIncremental.test.js +142 -0
  37. package/dist/src/analysis/tree-sitter/pythonIncremental.test.js.map +1 -0
  38. package/dist/src/analysis/tree-sitter/queries/python.d.ts +43 -0
  39. package/dist/src/analysis/tree-sitter/queries/python.d.ts.map +1 -0
  40. package/dist/src/analysis/tree-sitter/queries/python.js +88 -0
  41. package/dist/src/analysis/tree-sitter/queries/python.js.map +1 -0
  42. package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.d.ts +13 -0
  43. package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.d.ts.map +1 -0
  44. package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.js +174 -0
  45. package/dist/src/analysis/tree-sitter/queryExtractionMatchesOrExceedsRegex.test.js.map +1 -0
  46. package/dist/src/analytics/ROIDashboardService.csv.d.ts +11 -0
  47. package/dist/src/analytics/ROIDashboardService.csv.d.ts.map +1 -0
  48. package/dist/src/analytics/ROIDashboardService.csv.js +43 -0
  49. package/dist/src/analytics/ROIDashboardService.csv.js.map +1 -0
  50. package/dist/src/analytics/ROIDashboardService.d.ts +64 -3
  51. package/dist/src/analytics/ROIDashboardService.d.ts.map +1 -1
  52. package/dist/src/analytics/ROIDashboardService.js +116 -45
  53. package/dist/src/analytics/ROIDashboardService.js.map +1 -1
  54. package/dist/src/api/client.d.ts +4 -66
  55. package/dist/src/api/client.d.ts.map +1 -1
  56. package/dist/src/api/client.events.d.ts.map +1 -1
  57. package/dist/src/api/client.events.js +10 -1
  58. package/dist/src/api/client.events.js.map +1 -1
  59. package/dist/src/api/client.js +40 -66
  60. package/dist/src/api/client.js.map +1 -1
  61. package/dist/src/api/client.token-refresh.d.ts +3 -0
  62. package/dist/src/api/client.token-refresh.d.ts.map +1 -0
  63. package/dist/src/api/client.token-refresh.js +19 -0
  64. package/dist/src/api/client.token-refresh.js.map +1 -0
  65. package/dist/src/api/client.token-refresh.test.d.ts +2 -0
  66. package/dist/src/api/client.token-refresh.test.d.ts.map +1 -0
  67. package/dist/src/api/client.token-refresh.test.js +73 -0
  68. package/dist/src/api/client.token-refresh.test.js.map +1 -0
  69. package/dist/src/api/client.types.d.ts +2 -0
  70. package/dist/src/api/client.types.d.ts.map +1 -1
  71. package/dist/src/api/index.d.ts +1 -1
  72. package/dist/src/api/index.d.ts.map +1 -1
  73. package/dist/src/api/index.js +1 -1
  74. package/dist/src/api/index.js.map +1 -1
  75. package/dist/src/api/schemas.d.ts +60 -60
  76. package/dist/src/api/schemas.d.ts.map +1 -1
  77. package/dist/src/benchmarks/incrementalParseBenchmark.d.ts +18 -0
  78. package/dist/src/benchmarks/incrementalParseBenchmark.d.ts.map +1 -0
  79. package/dist/src/benchmarks/incrementalParseBenchmark.js +121 -0
  80. package/dist/src/benchmarks/incrementalParseBenchmark.js.map +1 -0
  81. package/dist/src/billing/GDPRComplianceService.test.d.ts +2 -0
  82. package/dist/src/billing/GDPRComplianceService.test.d.ts.map +1 -0
  83. package/dist/src/billing/GDPRComplianceService.test.js +405 -0
  84. package/dist/src/billing/GDPRComplianceService.test.js.map +1 -0
  85. package/dist/src/config/index.d.ts +4 -0
  86. package/dist/src/config/index.d.ts.map +1 -1
  87. package/dist/src/config/index.js +6 -0
  88. package/dist/src/config/index.js.map +1 -1
  89. package/dist/src/config/token-credentials.d.ts +13 -0
  90. package/dist/src/config/token-credentials.d.ts.map +1 -0
  91. package/dist/src/config/token-credentials.js +126 -0
  92. package/dist/src/config/token-credentials.js.map +1 -0
  93. package/dist/src/config/token-credentials.test.d.ts +10 -0
  94. package/dist/src/config/token-credentials.test.d.ts.map +1 -0
  95. package/dist/src/config/token-credentials.test.js +91 -0
  96. package/dist/src/config/token-credentials.test.js.map +1 -0
  97. package/dist/src/index.d.ts +7 -4
  98. package/dist/src/index.d.ts.map +1 -1
  99. package/dist/src/index.js +6 -3
  100. package/dist/src/index.js.map +1 -1
  101. package/dist/src/indexer/SkillParser.coverage.test.d.ts +10 -0
  102. package/dist/src/indexer/SkillParser.coverage.test.d.ts.map +1 -0
  103. package/dist/src/indexer/SkillParser.coverage.test.js +76 -0
  104. package/dist/src/indexer/SkillParser.coverage.test.js.map +1 -0
  105. package/dist/src/indexer/SkillParser.test.d.ts +2 -0
  106. package/dist/src/indexer/SkillParser.test.d.ts.map +1 -0
  107. package/dist/src/indexer/SkillParser.test.js +375 -0
  108. package/dist/src/indexer/SkillParser.test.js.map +1 -0
  109. package/dist/src/scripts/__tests__/scan-imported-skills.test.js +34 -5
  110. package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
  111. package/dist/src/scripts/github-import/blocklist.d.ts +65 -0
  112. package/dist/src/scripts/github-import/blocklist.d.ts.map +1 -0
  113. package/dist/src/scripts/github-import/blocklist.js +124 -0
  114. package/dist/src/scripts/github-import/blocklist.js.map +1 -0
  115. package/dist/src/scripts/github-import/index.d.ts +1 -0
  116. package/dist/src/scripts/github-import/index.d.ts.map +1 -1
  117. package/dist/src/scripts/github-import/index.js +3 -0
  118. package/dist/src/scripts/github-import/index.js.map +1 -1
  119. package/dist/src/scripts/github-import/signal-of-intent.d.ts +87 -0
  120. package/dist/src/scripts/github-import/signal-of-intent.d.ts.map +1 -0
  121. package/dist/src/scripts/github-import/signal-of-intent.js +213 -0
  122. package/dist/src/scripts/github-import/signal-of-intent.js.map +1 -0
  123. package/dist/src/scripts/github-import/types.d.ts +22 -0
  124. package/dist/src/scripts/github-import/types.d.ts.map +1 -1
  125. package/dist/src/scripts/github-import/types.js.map +1 -1
  126. package/dist/src/scripts/import-github-skills.js +73 -3
  127. package/dist/src/scripts/import-github-skills.js.map +1 -1
  128. package/dist/src/scripts/skill-scanner/allowlist.d.ts +38 -0
  129. package/dist/src/scripts/skill-scanner/allowlist.d.ts.map +1 -0
  130. package/dist/src/scripts/skill-scanner/allowlist.js +178 -0
  131. package/dist/src/scripts/skill-scanner/allowlist.js.map +1 -0
  132. package/dist/src/scripts/skill-scanner/scanner.d.ts +10 -2
  133. package/dist/src/scripts/skill-scanner/scanner.d.ts.map +1 -1
  134. package/dist/src/scripts/skill-scanner/scanner.js +15 -3
  135. package/dist/src/scripts/skill-scanner/scanner.js.map +1 -1
  136. package/dist/src/scripts/skill-scanner/trust-scorer.d.ts +20 -6
  137. package/dist/src/scripts/skill-scanner/trust-scorer.d.ts.map +1 -1
  138. package/dist/src/scripts/skill-scanner/trust-scorer.js +28 -9
  139. package/dist/src/scripts/skill-scanner/trust-scorer.js.map +1 -1
  140. package/dist/src/scripts/skill-scanner/types.d.ts +50 -0
  141. package/dist/src/scripts/skill-scanner/types.d.ts.map +1 -1
  142. package/dist/src/scripts/validation/types.d.ts +14 -24
  143. package/dist/src/scripts/validation/types.d.ts.map +1 -1
  144. package/dist/src/security/scanner/SecurityScanner.helpers.d.ts +18 -0
  145. package/dist/src/security/scanner/SecurityScanner.helpers.d.ts.map +1 -1
  146. package/dist/src/security/scanner/SecurityScanner.helpers.js +54 -6
  147. package/dist/src/security/scanner/SecurityScanner.helpers.js.map +1 -1
  148. package/dist/src/security/scanner/patterns.d.ts.map +1 -1
  149. package/dist/src/security/scanner/patterns.js +45 -5
  150. package/dist/src/security/scanner/patterns.js.map +1 -1
  151. package/dist/src/services/skill-config-schema.d.ts +4 -36
  152. package/dist/src/services/skill-config-schema.d.ts.map +1 -1
  153. package/dist/src/sources/LocalFilesystemAdapter.d.ts +104 -10
  154. package/dist/src/sources/LocalFilesystemAdapter.d.ts.map +1 -1
  155. package/dist/src/sources/LocalFilesystemAdapter.helpers.d.ts +92 -0
  156. package/dist/src/sources/LocalFilesystemAdapter.helpers.d.ts.map +1 -0
  157. package/dist/src/sources/LocalFilesystemAdapter.helpers.js +157 -0
  158. package/dist/src/sources/LocalFilesystemAdapter.helpers.js.map +1 -0
  159. package/dist/src/sources/LocalFilesystemAdapter.js +218 -159
  160. package/dist/src/sources/LocalFilesystemAdapter.js.map +1 -1
  161. package/dist/src/sources/LocalFilesystemAdapter.scan.d.ts +78 -0
  162. package/dist/src/sources/LocalFilesystemAdapter.scan.d.ts.map +1 -0
  163. package/dist/src/sources/LocalFilesystemAdapter.scan.js +118 -0
  164. package/dist/src/sources/LocalFilesystemAdapter.scan.js.map +1 -0
  165. package/dist/src/sources/index.d.ts +1 -1
  166. package/dist/src/sources/index.d.ts.map +1 -1
  167. package/dist/src/sources/index.js.map +1 -1
  168. package/dist/src/sources/types.d.ts +28 -0
  169. package/dist/src/sources/types.d.ts.map +1 -1
  170. package/dist/src/telemetry/tracer-imports.d.ts +13 -0
  171. package/dist/src/telemetry/tracer-imports.d.ts.map +1 -0
  172. package/dist/src/telemetry/tracer-imports.js +26 -0
  173. package/dist/src/telemetry/tracer-imports.js.map +1 -0
  174. package/dist/src/telemetry/tracer.d.ts.map +1 -1
  175. package/dist/src/telemetry/tracer.js +18 -21
  176. package/dist/src/telemetry/tracer.js.map +1 -1
  177. package/dist/src/utils/rate-limit.d.ts +39 -0
  178. package/dist/src/utils/rate-limit.d.ts.map +1 -0
  179. package/dist/src/utils/rate-limit.js +48 -0
  180. package/dist/src/utils/rate-limit.js.map +1 -0
  181. package/dist/src/utils/rate-limit.test.d.ts +11 -0
  182. package/dist/src/utils/rate-limit.test.d.ts.map +1 -0
  183. package/dist/src/utils/rate-limit.test.js +86 -0
  184. package/dist/src/utils/rate-limit.test.js.map +1 -0
  185. package/dist/src/webhooks/WebhookDeadLetterRepository.d.ts +178 -0
  186. package/dist/src/webhooks/WebhookDeadLetterRepository.d.ts.map +1 -0
  187. package/dist/src/webhooks/WebhookDeadLetterRepository.js +196 -0
  188. package/dist/src/webhooks/WebhookDeadLetterRepository.js.map +1 -0
  189. package/dist/src/webhooks/WebhookQueue.d.ts +1 -0
  190. package/dist/src/webhooks/WebhookQueue.d.ts.map +1 -1
  191. package/dist/src/webhooks/WebhookQueue.js +19 -0
  192. package/dist/src/webhooks/WebhookQueue.js.map +1 -1
  193. package/dist/src/webhooks/WebhookQueue.types.d.ts +11 -0
  194. package/dist/src/webhooks/WebhookQueue.types.d.ts.map +1 -1
  195. package/dist/src/webhooks/index.d.ts +1 -0
  196. package/dist/src/webhooks/index.d.ts.map +1 -1
  197. package/dist/src/webhooks/index.js +2 -0
  198. package/dist/src/webhooks/index.js.map +1 -1
  199. package/dist/src/webhooks/webhook-schemas.d.ts +117 -1212
  200. package/dist/src/webhooks/webhook-schemas.d.ts.map +1 -1
  201. package/dist/tests/ActivationManager.test.d.ts +13 -0
  202. package/dist/tests/ActivationManager.test.d.ts.map +1 -0
  203. package/dist/tests/ActivationManager.test.js +218 -0
  204. package/dist/tests/ActivationManager.test.js.map +1 -0
  205. package/dist/tests/LocalFilesystemAdapter.coverage.test.d.ts +13 -0
  206. package/dist/tests/LocalFilesystemAdapter.coverage.test.d.ts.map +1 -0
  207. package/dist/tests/LocalFilesystemAdapter.coverage.test.js +314 -0
  208. package/dist/tests/LocalFilesystemAdapter.coverage.test.js.map +1 -0
  209. package/dist/tests/LocalFilesystemAdapter.security.test.d.ts +18 -0
  210. package/dist/tests/LocalFilesystemAdapter.security.test.d.ts.map +1 -0
  211. package/dist/tests/LocalFilesystemAdapter.security.test.js +344 -0
  212. package/dist/tests/LocalFilesystemAdapter.security.test.js.map +1 -0
  213. package/dist/tests/LocalFilesystemAdapter.test.d.ts +12 -0
  214. package/dist/tests/LocalFilesystemAdapter.test.d.ts.map +1 -0
  215. package/dist/tests/LocalFilesystemAdapter.test.js +301 -0
  216. package/dist/tests/LocalFilesystemAdapter.test.js.map +1 -0
  217. package/dist/tests/ROIDashboardService.coverage.test.d.ts +9 -0
  218. package/dist/tests/ROIDashboardService.coverage.test.d.ts.map +1 -0
  219. package/dist/tests/ROIDashboardService.coverage.test.js +118 -0
  220. package/dist/tests/ROIDashboardService.coverage.test.js.map +1 -0
  221. package/dist/tests/ROIDashboardService.test.js +87 -0
  222. package/dist/tests/ROIDashboardService.test.js.map +1 -1
  223. package/dist/tests/ScraperAdapters.gitlab-coverage.test.d.ts +14 -0
  224. package/dist/tests/ScraperAdapters.gitlab-coverage.test.d.ts.map +1 -0
  225. package/dist/tests/ScraperAdapters.gitlab-coverage.test.js +169 -0
  226. package/dist/tests/ScraperAdapters.gitlab-coverage.test.js.map +1 -0
  227. package/dist/tests/ScraperAdapters.test.d.ts +5 -1
  228. package/dist/tests/ScraperAdapters.test.d.ts.map +1 -1
  229. package/dist/tests/ScraperAdapters.test.js +6 -336
  230. package/dist/tests/ScraperAdapters.test.js.map +1 -1
  231. package/dist/tests/WebhookDeadLetterRepository.test.d.ts +2 -0
  232. package/dist/tests/WebhookDeadLetterRepository.test.d.ts.map +1 -0
  233. package/dist/tests/WebhookDeadLetterRepository.test.js +333 -0
  234. package/dist/tests/WebhookDeadLetterRepository.test.js.map +1 -0
  235. package/dist/tests/WebhookHandler.test.js +93 -1
  236. package/dist/tests/WebhookHandler.test.js.map +1 -1
  237. package/dist/tests/WebhookQueue.coverage.test.d.ts +19 -0
  238. package/dist/tests/WebhookQueue.coverage.test.d.ts.map +1 -0
  239. package/dist/tests/WebhookQueue.coverage.test.js +190 -0
  240. package/dist/tests/WebhookQueue.coverage.test.js.map +1 -0
  241. package/dist/tests/api/client.events.test.d.ts +10 -0
  242. package/dist/tests/api/client.events.test.d.ts.map +1 -0
  243. package/dist/tests/api/client.events.test.js +85 -0
  244. package/dist/tests/api/client.events.test.js.map +1 -0
  245. package/dist/tests/billing/GDPRCompliance.test.d.ts +2 -2
  246. package/dist/tests/billing/GDPRCompliance.test.js +221 -36
  247. package/dist/tests/billing/GDPRCompliance.test.js.map +1 -1
  248. package/dist/tests/github-import/blocklist.test.d.ts +15 -0
  249. package/dist/tests/github-import/blocklist.test.d.ts.map +1 -0
  250. package/dist/tests/github-import/blocklist.test.js +182 -0
  251. package/dist/tests/github-import/blocklist.test.js.map +1 -0
  252. package/dist/tests/github-import/signal-of-intent.test.d.ts +15 -0
  253. package/dist/tests/github-import/signal-of-intent.test.d.ts.map +1 -0
  254. package/dist/tests/github-import/signal-of-intent.test.js +171 -0
  255. package/dist/tests/github-import/signal-of-intent.test.js.map +1 -0
  256. package/dist/tests/security/scanner-regression-guard.test.d.ts +12 -0
  257. package/dist/tests/security/scanner-regression-guard.test.d.ts.map +1 -1
  258. package/dist/tests/security/scanner-regression-guard.test.js +15 -3
  259. package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
  260. package/dist/tests/security/scanner-wave2-fixtures.test.d.ts +12 -0
  261. package/dist/tests/security/scanner-wave2-fixtures.test.d.ts.map +1 -0
  262. package/dist/tests/security/scanner-wave2-fixtures.test.js +173 -0
  263. package/dist/tests/security/scanner-wave2-fixtures.test.js.map +1 -0
  264. package/dist/tests/security.test.js +1 -0
  265. package/dist/tests/security.test.js.map +1 -1
  266. package/dist/tests/skill-scanner/allowlist.test.d.ts +16 -0
  267. package/dist/tests/skill-scanner/allowlist.test.d.ts.map +1 -0
  268. package/dist/tests/skill-scanner/allowlist.test.js +332 -0
  269. package/dist/tests/skill-scanner/allowlist.test.js.map +1 -0
  270. package/dist/tests/telemetry.test.js +126 -0
  271. package/dist/tests/telemetry.test.js.map +1 -1
  272. package/dist/tests/webhooks/WebhookDeadLetterRepository.test.d.ts +10 -0
  273. package/dist/tests/webhooks/WebhookDeadLetterRepository.test.d.ts.map +1 -0
  274. package/dist/tests/webhooks/WebhookDeadLetterRepository.test.js +109 -0
  275. package/dist/tests/webhooks/WebhookDeadLetterRepository.test.js.map +1 -0
  276. package/package.json +8 -3
@@ -1 +1 @@
1
- {"version":3,"file":"webhook-schemas.d.ts","sourceRoot":"","sources":["../../../src/webhooks/webhook-schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;gCAMV,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;gCAQlB,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAUpB,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;gCAQb,CAAA;AAEhB;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAQZ,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;gCAMhB,CAAA;AAEhB;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAMlB,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;gCAMpB,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCASd,CAAA;AAEhB;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAQZ,CAAA"}
1
+ {"version":3,"file":"webhook-schemas.d.ts","sourceRoot":"","sources":["../../../src/webhooks/webhook-schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB;;GAEG;AACH,eAAO,MAAM,aAAa;;;;iBAMV,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;iBAQlB,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;iBAUpB,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;iBAQb,CAAA;AAEhB;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAQZ,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;iBAMhB,CAAA;AAEhB;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMlB,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;iBAMpB,CAAA;AAEhB;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;iBASd,CAAA;AAEhB;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAQZ,CAAA"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * ActivationManager tests (SMI-4290 / closes #598)
3
+ *
4
+ * Covers the public API of `@skillsmith/core/activation/ActivationManager`:
5
+ * - activateSkill (validation, idempotency, force reinstall, filesystem state)
6
+ * - undo (rollback of fresh install, rollback of force reinstall via backup)
7
+ * - getUndoHistory / clearUndoHistory
8
+ * - Cross-instance persistence via shared `skillsDir`
9
+ *
10
+ * Uses real-tmpdir fixtures (no memfs, no msw — per Wave 3 plan).
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=ActivationManager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActivationManager.test.d.ts","sourceRoot":"","sources":["../../tests/ActivationManager.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,218 @@
1
+ /**
2
+ * ActivationManager tests (SMI-4290 / closes #598)
3
+ *
4
+ * Covers the public API of `@skillsmith/core/activation/ActivationManager`:
5
+ * - activateSkill (validation, idempotency, force reinstall, filesystem state)
6
+ * - undo (rollback of fresh install, rollback of force reinstall via backup)
7
+ * - getUndoHistory / clearUndoHistory
8
+ * - Cross-instance persistence via shared `skillsDir`
9
+ *
10
+ * Uses real-tmpdir fixtures (no memfs, no msw — per Wave 3 plan).
11
+ */
12
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
13
+ import * as fs from 'fs/promises';
14
+ import * as path from 'path';
15
+ import { tmpdir } from 'os';
16
+ import { ActivationManager } from '../src/activation/ActivationManager.js';
17
+ function makeTmpSkillsDir() {
18
+ return path.join(tmpdir(), `skillsmith-activation-${Date.now()}-${Math.floor(Math.random() * 1e9)}`);
19
+ }
20
+ async function exists(p) {
21
+ try {
22
+ await fs.access(p);
23
+ return true;
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ }
29
+ describe('ActivationManager', () => {
30
+ let skillsDir;
31
+ let manager;
32
+ beforeEach(() => {
33
+ skillsDir = makeTmpSkillsDir();
34
+ manager = new ActivationManager(skillsDir);
35
+ });
36
+ afterEach(async () => {
37
+ await fs.rm(skillsDir, { recursive: true, force: true }).catch(() => { });
38
+ });
39
+ describe('activateSkill — happy path', () => {
40
+ it('activates a valid skill, creates the install directory, and returns an undo token', async () => {
41
+ const result = await manager.activateSkill({ skill_id: 'anthropic/commit' });
42
+ expect(result.success).toBe(true);
43
+ expect(result.skill_id).toBe('anthropic/commit');
44
+ expect(result.undo_token).toBeTruthy();
45
+ expect(result.install_path).toBe(path.join(skillsDir, 'anthropic-commit'));
46
+ expect(result.activation_time_ms).toBeGreaterThanOrEqual(0);
47
+ // Filesystem side effects.
48
+ expect(await exists(result.install_path)).toBe(true);
49
+ const skillMd = await fs.readFile(path.join(result.install_path, 'SKILL.md'), 'utf-8');
50
+ expect(skillMd).toContain('anthropic/commit');
51
+ });
52
+ it('returns requires_restart: false when hot_reload succeeds', async () => {
53
+ const result = await manager.activateSkill({
54
+ skill_id: 'anthropic/commit',
55
+ hot_reload: true,
56
+ });
57
+ expect(result.success).toBe(true);
58
+ expect(result.requires_restart).toBe(false);
59
+ });
60
+ });
61
+ describe('activateSkill — already installed', () => {
62
+ it('is idempotent when the skill is already installed and force is false', async () => {
63
+ const first = await manager.activateSkill({ skill_id: 'anthropic/commit' });
64
+ expect(first.success).toBe(true);
65
+ const second = await manager.activateSkill({ skill_id: 'anthropic/commit' });
66
+ expect(second.success).toBe(true);
67
+ expect(second.requires_restart).toBe(false);
68
+ expect(second.install_path).toBe(first.install_path);
69
+ // Idempotent path returns no new undo token.
70
+ expect(second.undo_token).toBeUndefined();
71
+ });
72
+ it('creates a timestamped backup on force-reinstall; undo restores the original install from the backup', async () => {
73
+ const first = await manager.activateSkill({ skill_id: 'anthropic/commit' });
74
+ expect(first.success).toBe(true);
75
+ // Mark the original install with a sentinel so we can confirm a backup was made.
76
+ const sentinel = path.join(first.install_path, 'sentinel.txt');
77
+ await fs.writeFile(sentinel, 'original-install', 'utf-8');
78
+ const second = await manager.activateSkill({
79
+ skill_id: 'anthropic/commit',
80
+ force: true,
81
+ });
82
+ expect(second.success).toBe(true);
83
+ expect(second.undo_token).toBeTruthy();
84
+ // The fresh install has overwritten the sentinel.
85
+ expect(await exists(sentinel)).toBe(false);
86
+ // Sanity: a backup directory exists alongside the install, preserving the
87
+ // sentinel. This is the pre-undo state created by `createBackup`.
88
+ const entries = await fs.readdir(skillsDir);
89
+ const backupDir = entries.find((e) => e.startsWith('anthropic-commit.backup-'));
90
+ expect(backupDir).toBeTruthy();
91
+ expect(await exists(path.join(skillsDir, backupDir, 'sentinel.txt'))).toBe(true);
92
+ // Undo of a force-reinstall RESTORES the original install from the backup
93
+ // (SMI-4297). The snapshot now carries `backup_path`, so `undo()` renames
94
+ // the backup back over the install path instead of just deleting it.
95
+ const undone = await manager.undo(second.undo_token);
96
+ expect(undone).toBe(true);
97
+ // The original install path exists with the original sentinel content.
98
+ expect(await exists(second.install_path)).toBe(true);
99
+ expect(await exists(sentinel)).toBe(true);
100
+ const sentinelContent = await fs.readFile(sentinel, 'utf-8');
101
+ expect(sentinelContent).toBe('original-install');
102
+ // The backup dir has been consumed (renamed back into place).
103
+ const afterEntries = await fs.readdir(skillsDir);
104
+ expect(afterEntries.some((e) => e.startsWith('anthropic-commit.backup-'))).toBe(false);
105
+ });
106
+ it('undo of force-reinstall restores the original install from its backup', async () => {
107
+ const first = await manager.activateSkill({ skill_id: 'anthropic/commit' });
108
+ expect(first.success).toBe(true);
109
+ // Write an identifying marker in the original install.
110
+ const marker = path.join(first.install_path, 'marker.txt');
111
+ await fs.writeFile(marker, 'v1-original', 'utf-8');
112
+ const second = await manager.activateSkill({
113
+ skill_id: 'anthropic/commit',
114
+ force: true,
115
+ });
116
+ expect(second.success).toBe(true);
117
+ expect(second.undo_token).toBeTruthy();
118
+ // Fresh install has overwritten the marker.
119
+ expect(await exists(marker)).toBe(false);
120
+ // Undo restores the v1 marker by moving the backup back.
121
+ const ok = await manager.undo(second.undo_token);
122
+ expect(ok).toBe(true);
123
+ expect(await exists(marker)).toBe(true);
124
+ expect(await fs.readFile(marker, 'utf-8')).toBe('v1-original');
125
+ });
126
+ });
127
+ describe('activateSkill — validation failures', () => {
128
+ it('rejects an empty skill_id with a typed validation error', async () => {
129
+ const result = await manager.activateSkill({ skill_id: '' });
130
+ expect(result.success).toBe(false);
131
+ expect(result.error).toMatch(/Validation failed/i);
132
+ expect(result.requires_restart).toBe(false);
133
+ expect(result.undo_token).toBeUndefined();
134
+ });
135
+ it('rejects a skill_id missing the author/name separator', async () => {
136
+ const result = await manager.activateSkill({ skill_id: 'just-a-name' });
137
+ expect(result.success).toBe(false);
138
+ expect(result.error).toMatch(/format "author\/name"/i);
139
+ });
140
+ it('rejects a skill_id containing invalid characters', async () => {
141
+ const result = await manager.activateSkill({
142
+ skill_id: 'bad author/bad name',
143
+ });
144
+ expect(result.success).toBe(false);
145
+ expect(result.error).toMatch(/invalid characters/i);
146
+ });
147
+ it('skips validation when validate_first is false', async () => {
148
+ const result = await manager.activateSkill({
149
+ skill_id: 'anthropic/commit',
150
+ validate_first: false,
151
+ });
152
+ expect(result.success).toBe(true);
153
+ expect(result.install_path).toBeTruthy();
154
+ });
155
+ });
156
+ describe('undo — fresh install', () => {
157
+ it('removes the install directory and forgets the token', async () => {
158
+ const result = await manager.activateSkill({ skill_id: 'anthropic/commit' });
159
+ expect(result.success).toBe(true);
160
+ expect(await exists(result.install_path)).toBe(true);
161
+ const undone = await manager.undo(result.undo_token);
162
+ expect(undone).toBe(true);
163
+ expect(await exists(result.install_path)).toBe(false);
164
+ // Undoing a second time with the same token is a no-op (snapshot is gone).
165
+ const second = await manager.undo(result.undo_token);
166
+ expect(second).toBe(false);
167
+ });
168
+ it('returns false for an unknown undo token', async () => {
169
+ const undone = await manager.undo('does-not-exist');
170
+ expect(undone).toBe(false);
171
+ });
172
+ });
173
+ describe('undo history', () => {
174
+ it('tracks snapshots across activations and can be cleared', async () => {
175
+ const a = await manager.activateSkill({ skill_id: 'anthropic/commit' });
176
+ const b = await manager.activateSkill({ skill_id: 'anthropic/review' });
177
+ expect(a.success).toBe(true);
178
+ expect(b.success).toBe(true);
179
+ const history = manager.getUndoHistory();
180
+ expect(history.length).toBe(2);
181
+ const tokens = history.map((h) => h.token).sort();
182
+ expect(tokens).toContain(a.undo_token);
183
+ expect(tokens).toContain(b.undo_token);
184
+ manager.clearUndoHistory();
185
+ expect(manager.getUndoHistory()).toEqual([]);
186
+ // After clearing history, previously issued tokens are no longer redeemable.
187
+ const stale = await manager.undo(a.undo_token);
188
+ expect(stale).toBe(false);
189
+ });
190
+ });
191
+ describe('cross-instance persistence', () => {
192
+ it('sees activations performed by a separate manager sharing the same skillsDir', async () => {
193
+ const managerA = new ActivationManager(skillsDir);
194
+ const activate = await managerA.activateSkill({ skill_id: 'anthropic/commit' });
195
+ expect(activate.success).toBe(true);
196
+ // A brand-new manager on the same skillsDir must treat the skill as installed
197
+ // (idempotent path → success, no undo token).
198
+ const managerB = new ActivationManager(skillsDir);
199
+ const second = await managerB.activateSkill({ skill_id: 'anthropic/commit' });
200
+ expect(second.success).toBe(true);
201
+ expect(second.undo_token).toBeUndefined();
202
+ expect(await exists(path.join(skillsDir, 'anthropic-commit'))).toBe(true);
203
+ });
204
+ });
205
+ describe('concurrency', () => {
206
+ it('activates multiple distinct skills concurrently', async () => {
207
+ const ids = ['anthropic/commit', 'anthropic/review', 'team/lint'];
208
+ const results = await Promise.all(ids.map((id) => manager.activateSkill({ skill_id: id })));
209
+ expect(results.every((r) => r.success)).toBe(true);
210
+ for (const id of ids) {
211
+ const dir = path.join(skillsDir, id.replace('/', '-'));
212
+ expect(await exists(dir)).toBe(true);
213
+ }
214
+ expect(manager.getUndoHistory().length).toBe(3);
215
+ });
216
+ });
217
+ });
218
+ //# sourceMappingURL=ActivationManager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActivationManager.test.js","sourceRoot":"","sources":["../../tests/ActivationManager.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * LocalFilesystemAdapter coverage sidecar (SMI-4287)
3
+ *
4
+ * Split out of `LocalFilesystemAdapter.test.ts` so that file stays under the
5
+ * 500-line pre-commit ceiling (see memory feedback:
6
+ * "File-length enforcement asymmetry" — pre-commit does NOT exempt
7
+ * `.test.ts` even though `audit:standards` does). Covers symlink
8
+ * containment, permission handling, loop detection, case-insensitive
9
+ * normalisation, and frontmatter-tolerance cases introduced by SMI-4287
10
+ * (GitHub #600, #596).
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=LocalFilesystemAdapter.coverage.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalFilesystemAdapter.coverage.test.d.ts","sourceRoot":"","sources":["../../tests/LocalFilesystemAdapter.coverage.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,314 @@
1
+ /**
2
+ * LocalFilesystemAdapter coverage sidecar (SMI-4287)
3
+ *
4
+ * Split out of `LocalFilesystemAdapter.test.ts` so that file stays under the
5
+ * 500-line pre-commit ceiling (see memory feedback:
6
+ * "File-length enforcement asymmetry" — pre-commit does NOT exempt
7
+ * `.test.ts` even though `audit:standards` does). Covers symlink
8
+ * containment, permission handling, loop detection, case-insensitive
9
+ * normalisation, and frontmatter-tolerance cases introduced by SMI-4287
10
+ * (GitHub #600, #596).
11
+ */
12
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
13
+ import { LocalFilesystemAdapter } from '../src/sources/LocalFilesystemAdapter.js';
14
+ import { promises as fs, constants as fsConstants } from 'fs';
15
+ import { join } from 'path';
16
+ import { tmpdir, platform } from 'os';
17
+ describe('LocalFilesystemAdapter SMI-4287 coverage', () => {
18
+ let adapter;
19
+ let testDir;
20
+ beforeEach(async () => {
21
+ testDir = join(tmpdir(), `skillsmith-4287-${Date.now()}-${Math.random().toString(36).slice(2)}`);
22
+ await fs.mkdir(testDir, { recursive: true });
23
+ await fs.mkdir(join(testDir, 'skill-one'), { recursive: true });
24
+ await fs.writeFile(join(testDir, 'skill-one', 'SKILL.md'), '---\nname: Skill One\ndescription: First skill\n---\n# Skill One');
25
+ await fs.mkdir(join(testDir, 'skill-two'), { recursive: true });
26
+ await fs.writeFile(join(testDir, 'skill-two', 'SKILL.md'), '---\nname: Skill Two\n---\n# Skill Two');
27
+ adapter = new LocalFilesystemAdapter({
28
+ id: 'test-local',
29
+ name: 'Test Local',
30
+ type: 'local',
31
+ baseUrl: 'file://',
32
+ enabled: true,
33
+ rootDir: testDir,
34
+ rateLimit: { maxRequests: 100, windowMs: 60000, minDelayMs: 0 },
35
+ });
36
+ await adapter.initialize();
37
+ });
38
+ afterEach(async () => {
39
+ // Restore any chmod'd directories so rm can clean up.
40
+ for (const name of ['locked-dir', 'locked-skill']) {
41
+ const p = join(testDir, name);
42
+ try {
43
+ await fs.chmod(p, 0o755);
44
+ }
45
+ catch {
46
+ // ignore
47
+ }
48
+ }
49
+ try {
50
+ await fs.rm(testDir, { recursive: true, force: true });
51
+ }
52
+ catch {
53
+ // Ignore cleanup errors
54
+ }
55
+ });
56
+ describe('Symlink containment', () => {
57
+ it('should follow symlinks that stay inside rootDir when enabled', async () => {
58
+ // Target is a directory _inside_ rootDir, so containment passes without
59
+ // `allowSymlinksOutsideRoot`. SMI-4319 updates the semantics: a symlink
60
+ // whose target realpath is already visited is treated as a loop (the
61
+ // alias does NOT double-surface the same SKILL.md). The scan still
62
+ // succeeds and the original skills are reported.
63
+ const target = join(testDir, 'skill-two');
64
+ const link = join(testDir, 'alias-of-skill-two');
65
+ try {
66
+ await fs.symlink(target, link);
67
+ }
68
+ catch {
69
+ return;
70
+ }
71
+ const followAdapter = new LocalFilesystemAdapter({
72
+ id: 'test-follow-internal',
73
+ name: 'Test Follow Internal',
74
+ type: 'local',
75
+ baseUrl: 'file://',
76
+ enabled: true,
77
+ rootDir: testDir,
78
+ followSymlinks: true,
79
+ rateLimit: { maxRequests: 100, windowMs: 60000, minDelayMs: 0 },
80
+ });
81
+ await followAdapter.initialize();
82
+ // Post-SMI-4319: aliased directory is de-duplicated via the
83
+ // visited-realpath set. Only the two canonical skill dirs surface.
84
+ expect(followAdapter.skillCount).toBe(2);
85
+ const result = await followAdapter.search({});
86
+ // The alias traversal emits a `loop` warning (already-visited realpath).
87
+ // Non-loop warning categories must still be empty.
88
+ const nonLoop = (result.warnings ?? []).filter((w) => w.code !== 'loop');
89
+ expect(nonLoop).toEqual([]);
90
+ });
91
+ it('should reject symlinks escaping rootDir with a symlink-escape warning', async () => {
92
+ const externalDir = join(tmpdir(), `external-escape-${Date.now()}`);
93
+ await fs.mkdir(externalDir, { recursive: true });
94
+ await fs.writeFile(join(externalDir, 'SKILL.md'), '# Should not index');
95
+ try {
96
+ await fs.symlink(externalDir, join(testDir, 'escape-link'));
97
+ }
98
+ catch {
99
+ return;
100
+ }
101
+ const escapeAdapter = new LocalFilesystemAdapter({
102
+ id: 'test-escape',
103
+ name: 'Test Escape',
104
+ type: 'local',
105
+ baseUrl: 'file://',
106
+ enabled: true,
107
+ rootDir: testDir,
108
+ followSymlinks: true,
109
+ rateLimit: { maxRequests: 100, windowMs: 60000, minDelayMs: 0 },
110
+ });
111
+ await escapeAdapter.initialize();
112
+ // Escaping symlink must NOT be followed.
113
+ expect(escapeAdapter.skillCount).toBe(2);
114
+ const result = await escapeAdapter.search({});
115
+ const escapeWarnings = (result.warnings ?? []).filter((w) => w.code === 'symlink-escape');
116
+ expect(escapeWarnings.length).toBeGreaterThan(0);
117
+ expect(escapeWarnings[0].path).toContain('escape-link');
118
+ await fs.rm(externalDir, { recursive: true, force: true });
119
+ });
120
+ it('should permit escaping symlinks when allowSymlinksOutsideRoot is true', async () => {
121
+ const externalDir = join(tmpdir(), `external-allow-${Date.now()}`);
122
+ await fs.mkdir(externalDir, { recursive: true });
123
+ await fs.writeFile(join(externalDir, 'SKILL.md'), '# Permitted external');
124
+ try {
125
+ await fs.symlink(externalDir, join(testDir, 'allowed-link'));
126
+ }
127
+ catch {
128
+ return;
129
+ }
130
+ const allowAdapter = new LocalFilesystemAdapter({
131
+ id: 'test-allow',
132
+ name: 'Test Allow',
133
+ type: 'local',
134
+ baseUrl: 'file://',
135
+ enabled: true,
136
+ rootDir: testDir,
137
+ followSymlinks: true,
138
+ allowSymlinksOutsideRoot: true,
139
+ rateLimit: { maxRequests: 100, windowMs: 60000, minDelayMs: 0 },
140
+ });
141
+ await allowAdapter.initialize();
142
+ expect(allowAdapter.skillCount).toBe(3);
143
+ await fs.rm(externalDir, { recursive: true, force: true });
144
+ });
145
+ });
146
+ describe('Circular symlinks', () => {
147
+ it('should emit loop warning for circular symlinks', async () => {
148
+ const a = join(testDir, 'loop-a');
149
+ const b = join(testDir, 'loop-b');
150
+ try {
151
+ await fs.symlink(b, a);
152
+ await fs.symlink(a, b);
153
+ }
154
+ catch {
155
+ return;
156
+ }
157
+ const loopAdapter = new LocalFilesystemAdapter({
158
+ id: 'test-loop',
159
+ name: 'Test Loop',
160
+ type: 'local',
161
+ baseUrl: 'file://',
162
+ enabled: true,
163
+ rootDir: testDir,
164
+ followSymlinks: true,
165
+ rateLimit: { maxRequests: 100, windowMs: 60000, minDelayMs: 0 },
166
+ });
167
+ await loopAdapter.initialize();
168
+ const result = await loopAdapter.search({});
169
+ const loopWarnings = (result.warnings ?? []).filter((w) => w.code === 'loop');
170
+ expect(loopWarnings.length).toBeGreaterThan(0);
171
+ // Scan must still report the non-symlinked skills.
172
+ expect(loopAdapter.skillCount).toBe(2);
173
+ });
174
+ });
175
+ describe('Permission handling', () => {
176
+ it('should surface EACCES as a permission warning and continue scanning', async () => {
177
+ if (platform() === 'win32')
178
+ return;
179
+ const locked = join(testDir, 'locked-dir');
180
+ await fs.mkdir(locked, { recursive: true });
181
+ await fs.writeFile(join(locked, 'SKILL.md'), '# Locked skill');
182
+ await fs.chmod(locked, 0o000);
183
+ // Skip if root (chmod bypassed).
184
+ let canRead = false;
185
+ try {
186
+ await fs.readdir(locked);
187
+ canRead = true;
188
+ }
189
+ catch {
190
+ canRead = false;
191
+ }
192
+ try {
193
+ const permAdapter = new LocalFilesystemAdapter({
194
+ id: 'test-perm',
195
+ name: 'Test Perm',
196
+ type: 'local',
197
+ baseUrl: 'file://',
198
+ enabled: true,
199
+ rootDir: testDir,
200
+ rateLimit: { maxRequests: 100, windowMs: 60000, minDelayMs: 0 },
201
+ });
202
+ await permAdapter.initialize();
203
+ const result = await permAdapter.search({});
204
+ if (canRead) {
205
+ // Running as root or elevated — skip assertion path.
206
+ return;
207
+ }
208
+ expect(permAdapter.skillCount).toBe(2);
209
+ const permWarnings = (result.warnings ?? []).filter((w) => w.code === 'permission');
210
+ expect(permWarnings.length).toBeGreaterThan(0);
211
+ expect(permWarnings[0].path).toContain('locked-dir');
212
+ }
213
+ finally {
214
+ await fs.chmod(locked, 0o755).catch(() => undefined);
215
+ }
216
+ });
217
+ it('should surface typed message for chmod 000 root in checkHealth', async () => {
218
+ if (platform() === 'win32')
219
+ return;
220
+ const lockedRoot = join(testDir, 'locked-root');
221
+ await fs.mkdir(lockedRoot, { recursive: true });
222
+ await fs.chmod(lockedRoot, 0o000);
223
+ try {
224
+ const lockedAdapter = new LocalFilesystemAdapter({
225
+ id: 'locked',
226
+ name: 'Locked',
227
+ type: 'local',
228
+ baseUrl: 'file://',
229
+ enabled: true,
230
+ rootDir: join(lockedRoot, 'inner'),
231
+ rateLimit: { maxRequests: 100, windowMs: 60000, minDelayMs: 0 },
232
+ });
233
+ const health = await lockedAdapter.checkHealth();
234
+ expect(health.healthy).toBe(false);
235
+ expect(health.error).toBeTruthy();
236
+ }
237
+ finally {
238
+ await fs.chmod(lockedRoot, 0o755).catch(() => undefined);
239
+ }
240
+ });
241
+ it('should surface typed error for chmod 000 SKILL.md via fetchSkillContent', async () => {
242
+ if (platform() === 'win32')
243
+ return;
244
+ const lockedDir = join(testDir, 'locked-skill');
245
+ await fs.mkdir(lockedDir, { recursive: true });
246
+ const skillPath = join(lockedDir, 'SKILL.md');
247
+ await fs.writeFile(skillPath, '# Locked');
248
+ await fs.chmod(skillPath, 0o000);
249
+ try {
250
+ // Skip if running as root — chmod 000 is bypassed by root.
251
+ let canRead = false;
252
+ try {
253
+ await fs.access(skillPath, fsConstants.R_OK);
254
+ canRead = true;
255
+ }
256
+ catch {
257
+ canRead = false;
258
+ }
259
+ if (canRead)
260
+ return;
261
+ await expect(adapter.fetchSkillContent({ path: skillPath })).rejects.toThrow(/Failed to read skill file|Cannot read/);
262
+ }
263
+ finally {
264
+ await fs.chmod(skillPath, 0o644).catch(() => undefined);
265
+ }
266
+ });
267
+ it('should surface typed error for nonexistent path via getRepository', async () => {
268
+ if (platform() === 'win32')
269
+ return;
270
+ const nonexistent = join(testDir, 'never-created');
271
+ await expect(adapter.getRepository({ path: nonexistent })).rejects.toThrow(/Skill not found|Not found/);
272
+ });
273
+ });
274
+ describe('Frontmatter regressions', () => {
275
+ it('should not fail on malformed frontmatter', async () => {
276
+ await fs.mkdir(join(testDir, 'bad-yaml'), { recursive: true });
277
+ await fs.writeFile(join(testDir, 'bad-yaml', 'SKILL.md'), '---\nname: oops\n broken: [\n---\n# Broken');
278
+ const count = await adapter.rescan();
279
+ expect(count).toBe(3);
280
+ });
281
+ });
282
+ describe('Case-insensitive filesystem normalisation', () => {
283
+ it('should accept symlink targets that differ only in case on macOS/Windows', async () => {
284
+ // Only exercise on case-insensitive filesystems; Linux ext4 would
285
+ // genuinely treat these as distinct paths.
286
+ if (platform() !== 'darwin' && platform() !== 'win32')
287
+ return;
288
+ const target = join(testDir, 'skill-one');
289
+ const link = join(testDir, 'case-alias');
290
+ try {
291
+ // Build a target string with different casing than the actual dir.
292
+ // macOS APFS reports realpath with the original casing, so the
293
+ // containment check must normalise.
294
+ await fs.symlink(target.toUpperCase(), link);
295
+ }
296
+ catch {
297
+ return;
298
+ }
299
+ const caseAdapter = new LocalFilesystemAdapter({
300
+ id: 'test-case',
301
+ name: 'Test Case',
302
+ type: 'local',
303
+ baseUrl: 'file://',
304
+ enabled: true,
305
+ rootDir: testDir,
306
+ followSymlinks: true,
307
+ rateLimit: { maxRequests: 100, windowMs: 60000, minDelayMs: 0 },
308
+ });
309
+ // Should not error; target is inside rootDir regardless of casing.
310
+ await expect(caseAdapter.initialize()).resolves.not.toThrow();
311
+ });
312
+ });
313
+ });
314
+ //# sourceMappingURL=LocalFilesystemAdapter.coverage.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalFilesystemAdapter.coverage.test.js","sourceRoot":"","sources":["../../tests/LocalFilesystemAdapter.coverage.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * LocalFilesystemAdapter security sidecar (SMI-4319, SMI-4320)
3
+ *
4
+ * Covers:
5
+ * - SMI-4319 symlink loop detection via per-scan visited-realpath set
6
+ * (A↔B, self-loops, `allowSymlinksOutsideRoot` does NOT suppress the
7
+ * loop warning, per-scan isolation, happy deep tree).
8
+ * - SMI-4320 realpath-based containment for direct-access methods
9
+ * (`fetchSkillContent` / `getRepository` / `skillExists`), byte-wise
10
+ * `startsWith(root + sep)` correctness including the trailing-separator
11
+ * guard, and the `allowSymlinksOutsideRoot` regression guard.
12
+ *
13
+ * Kept in its own file because the pre-commit `check-file-length.mjs`
14
+ * enforces < 500 lines on `.test.ts` even though `audit:standards` exempts
15
+ * tests (see memory feedback: "File-length enforcement asymmetry").
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=LocalFilesystemAdapter.security.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalFilesystemAdapter.security.test.d.ts","sourceRoot":"","sources":["../../tests/LocalFilesystemAdapter.security.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}