@skillsmith/mcp-server 0.3.1 → 0.3.2

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 (314) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/src/__tests__/get-skill.test.d.ts +6 -0
  3. package/dist/src/__tests__/get-skill.test.d.ts.map +1 -0
  4. package/dist/src/__tests__/get-skill.test.js +88 -0
  5. package/dist/src/__tests__/get-skill.test.js.map +1 -0
  6. package/dist/src/__tests__/middleware/errorFormatter.test.d.ts +7 -0
  7. package/dist/src/__tests__/middleware/errorFormatter.test.d.ts.map +1 -0
  8. package/dist/src/__tests__/middleware/errorFormatter.test.js +304 -0
  9. package/dist/src/__tests__/middleware/errorFormatter.test.js.map +1 -0
  10. package/dist/src/__tests__/middleware/license.test.d.ts +7 -0
  11. package/dist/src/__tests__/middleware/license.test.d.ts.map +1 -0
  12. package/dist/src/__tests__/middleware/license.test.js +500 -0
  13. package/dist/src/__tests__/middleware/license.test.js.map +1 -0
  14. package/dist/src/__tests__/search.test.d.ts +6 -0
  15. package/dist/src/__tests__/search.test.d.ts.map +1 -0
  16. package/dist/src/__tests__/search.test.js +86 -0
  17. package/dist/src/__tests__/search.test.js.map +1 -0
  18. package/dist/src/__tests__/test-utils.d.ts +20 -0
  19. package/dist/src/__tests__/test-utils.d.ts.map +1 -0
  20. package/dist/src/__tests__/test-utils.js +91 -0
  21. package/dist/src/__tests__/test-utils.js.map +1 -0
  22. package/dist/src/context/index.d.ts +19 -0
  23. package/dist/src/context/index.d.ts.map +1 -0
  24. package/dist/src/context/index.js +25 -0
  25. package/dist/src/context/index.js.map +1 -0
  26. package/dist/src/context/project-detector.d.ts +145 -0
  27. package/dist/src/context/project-detector.d.ts.map +1 -0
  28. package/dist/src/context/project-detector.js +321 -0
  29. package/dist/src/context/project-detector.js.map +1 -0
  30. package/dist/src/context.d.ts +157 -0
  31. package/dist/src/context.d.ts.map +1 -0
  32. package/dist/src/context.js +231 -0
  33. package/dist/src/context.js.map +1 -0
  34. package/dist/src/core-shim.d.ts +7 -0
  35. package/dist/src/core-shim.d.ts.map +1 -0
  36. package/dist/src/core-shim.js +9 -0
  37. package/dist/src/core-shim.js.map +1 -0
  38. package/dist/src/health/healthCheck.d.ts +88 -0
  39. package/dist/src/health/healthCheck.d.ts.map +1 -0
  40. package/dist/src/health/healthCheck.js +117 -0
  41. package/dist/src/health/healthCheck.js.map +1 -0
  42. package/dist/src/health/index.d.ts +21 -0
  43. package/dist/src/health/index.d.ts.map +1 -0
  44. package/dist/src/health/index.js +21 -0
  45. package/dist/src/health/index.js.map +1 -0
  46. package/dist/src/health/readinessCheck.d.ts +139 -0
  47. package/dist/src/health/readinessCheck.d.ts.map +1 -0
  48. package/dist/src/health/readinessCheck.js +266 -0
  49. package/dist/src/health/readinessCheck.js.map +1 -0
  50. package/dist/src/index.d.ts +10 -0
  51. package/dist/src/index.d.ts.map +1 -0
  52. package/dist/src/index.js +237 -0
  53. package/dist/src/index.js.map +1 -0
  54. package/dist/src/index.test.d.ts +2 -0
  55. package/dist/src/index.test.d.ts.map +1 -0
  56. package/dist/src/index.test.js +43 -0
  57. package/dist/src/index.test.js.map +1 -0
  58. package/dist/src/logger.d.ts +26 -0
  59. package/dist/src/logger.d.ts.map +1 -0
  60. package/dist/src/logger.js +179 -0
  61. package/dist/src/logger.js.map +1 -0
  62. package/dist/src/middleware/__tests__/csp.test.d.ts +2 -0
  63. package/dist/src/middleware/__tests__/csp.test.d.ts.map +1 -0
  64. package/dist/src/middleware/__tests__/csp.test.js +390 -0
  65. package/dist/src/middleware/__tests__/csp.test.js.map +1 -0
  66. package/dist/src/middleware/csp.d.ts +103 -0
  67. package/dist/src/middleware/csp.d.ts.map +1 -0
  68. package/dist/src/middleware/csp.js +273 -0
  69. package/dist/src/middleware/csp.js.map +1 -0
  70. package/dist/src/middleware/degradation.d.ts +105 -0
  71. package/dist/src/middleware/degradation.d.ts.map +1 -0
  72. package/dist/src/middleware/degradation.js +319 -0
  73. package/dist/src/middleware/degradation.js.map +1 -0
  74. package/dist/src/middleware/errorFormatter.d.ts +119 -0
  75. package/dist/src/middleware/errorFormatter.d.ts.map +1 -0
  76. package/dist/src/middleware/errorFormatter.js +294 -0
  77. package/dist/src/middleware/errorFormatter.js.map +1 -0
  78. package/dist/src/middleware/index.d.ts +11 -0
  79. package/dist/src/middleware/index.d.ts.map +1 -0
  80. package/dist/src/middleware/index.js +16 -0
  81. package/dist/src/middleware/index.js.map +1 -0
  82. package/dist/src/middleware/license.d.ts +169 -0
  83. package/dist/src/middleware/license.d.ts.map +1 -0
  84. package/dist/src/middleware/license.js +292 -0
  85. package/dist/src/middleware/license.js.map +1 -0
  86. package/dist/src/middleware/quota.d.ts +182 -0
  87. package/dist/src/middleware/quota.d.ts.map +1 -0
  88. package/dist/src/middleware/quota.js +309 -0
  89. package/dist/src/middleware/quota.js.map +1 -0
  90. package/dist/src/middleware/toolFeatureMapping.d.ts +36 -0
  91. package/dist/src/middleware/toolFeatureMapping.d.ts.map +1 -0
  92. package/dist/src/middleware/toolFeatureMapping.js +96 -0
  93. package/dist/src/middleware/toolFeatureMapping.js.map +1 -0
  94. package/dist/src/onboarding/first-run.d.ts +65 -0
  95. package/dist/src/onboarding/first-run.d.ts.map +1 -0
  96. package/dist/src/onboarding/first-run.js +79 -0
  97. package/dist/src/onboarding/first-run.js.map +1 -0
  98. package/dist/src/onboarding/index.d.ts +7 -0
  99. package/dist/src/onboarding/index.d.ts.map +1 -0
  100. package/dist/src/onboarding/index.js +7 -0
  101. package/dist/src/onboarding/index.js.map +1 -0
  102. package/dist/src/onboarding/install-assets.d.ts +27 -0
  103. package/dist/src/onboarding/install-assets.d.ts.map +1 -0
  104. package/dist/src/onboarding/install-assets.js +128 -0
  105. package/dist/src/onboarding/install-assets.js.map +1 -0
  106. package/dist/src/suggestions/index.d.ts +21 -0
  107. package/dist/src/suggestions/index.d.ts.map +1 -0
  108. package/dist/src/suggestions/index.js +20 -0
  109. package/dist/src/suggestions/index.js.map +1 -0
  110. package/dist/src/suggestions/suggestion-engine.d.ts +185 -0
  111. package/dist/src/suggestions/suggestion-engine.d.ts.map +1 -0
  112. package/dist/src/suggestions/suggestion-engine.js +352 -0
  113. package/dist/src/suggestions/suggestion-engine.js.map +1 -0
  114. package/dist/src/suggestions/types.d.ts +88 -0
  115. package/dist/src/suggestions/types.d.ts.map +1 -0
  116. package/dist/src/suggestions/types.js +21 -0
  117. package/dist/src/suggestions/types.js.map +1 -0
  118. package/dist/src/tools/analyze.d.ts +151 -0
  119. package/dist/src/tools/analyze.d.ts.map +1 -0
  120. package/dist/src/tools/analyze.js +205 -0
  121. package/dist/src/tools/analyze.js.map +1 -0
  122. package/dist/src/tools/compare.d.ts +149 -0
  123. package/dist/src/tools/compare.d.ts.map +1 -0
  124. package/dist/src/tools/compare.js +464 -0
  125. package/dist/src/tools/compare.js.map +1 -0
  126. package/dist/src/tools/get-skill.d.ts +107 -0
  127. package/dist/src/tools/get-skill.d.ts.map +1 -0
  128. package/dist/src/tools/get-skill.js +260 -0
  129. package/dist/src/tools/get-skill.js.map +1 -0
  130. package/dist/src/tools/index.d.ts +20 -0
  131. package/dist/src/tools/index.d.ts.map +1 -0
  132. package/dist/src/tools/index.js +20 -0
  133. package/dist/src/tools/index.js.map +1 -0
  134. package/dist/src/tools/install.d.ts +122 -0
  135. package/dist/src/tools/install.d.ts.map +1 -0
  136. package/dist/src/tools/install.js +326 -0
  137. package/dist/src/tools/install.js.map +1 -0
  138. package/dist/src/tools/recommend.d.ts +169 -0
  139. package/dist/src/tools/recommend.d.ts.map +1 -0
  140. package/dist/src/tools/recommend.js +357 -0
  141. package/dist/src/tools/recommend.js.map +1 -0
  142. package/dist/src/tools/search.d.ts +114 -0
  143. package/dist/src/tools/search.d.ts.map +1 -0
  144. package/dist/src/tools/search.js +247 -0
  145. package/dist/src/tools/search.js.map +1 -0
  146. package/dist/src/tools/suggest.d.ts +181 -0
  147. package/dist/src/tools/suggest.d.ts.map +1 -0
  148. package/dist/src/tools/suggest.js +310 -0
  149. package/dist/src/tools/suggest.js.map +1 -0
  150. package/dist/src/tools/uninstall.d.ts +123 -0
  151. package/dist/src/tools/uninstall.d.ts.map +1 -0
  152. package/dist/src/tools/uninstall.js +250 -0
  153. package/dist/src/tools/uninstall.js.map +1 -0
  154. package/dist/src/tools/validate.d.ts +122 -0
  155. package/dist/src/tools/validate.d.ts.map +1 -0
  156. package/dist/src/tools/validate.js +497 -0
  157. package/dist/src/tools/validate.js.map +1 -0
  158. package/dist/src/utils/installed-skills.d.ts +101 -0
  159. package/dist/src/utils/installed-skills.d.ts.map +1 -0
  160. package/dist/src/utils/installed-skills.js +220 -0
  161. package/dist/src/utils/installed-skills.js.map +1 -0
  162. package/dist/src/utils/validation.d.ts +95 -0
  163. package/dist/src/utils/validation.d.ts.map +1 -0
  164. package/dist/src/utils/validation.js +186 -0
  165. package/dist/src/utils/validation.js.map +1 -0
  166. package/dist/src/webhooks/index.d.ts +8 -0
  167. package/dist/src/webhooks/index.d.ts.map +1 -0
  168. package/dist/src/webhooks/index.js +9 -0
  169. package/dist/src/webhooks/index.js.map +1 -0
  170. package/dist/src/webhooks/webhook-endpoint.d.ts +149 -0
  171. package/dist/src/webhooks/webhook-endpoint.d.ts.map +1 -0
  172. package/dist/src/webhooks/webhook-endpoint.js +339 -0
  173. package/dist/src/webhooks/webhook-endpoint.js.map +1 -0
  174. package/dist/tests/compare.test.d.ts +6 -0
  175. package/dist/tests/compare.test.d.ts.map +1 -0
  176. package/dist/tests/compare.test.js +225 -0
  177. package/dist/tests/compare.test.js.map +1 -0
  178. package/dist/tests/context/project-detector.test.d.ts +6 -0
  179. package/dist/tests/context/project-detector.test.d.ts.map +1 -0
  180. package/dist/tests/context/project-detector.test.js +719 -0
  181. package/dist/tests/context/project-detector.test.js.map +1 -0
  182. package/dist/tests/e2e/compare.e2e.test.d.ts +10 -0
  183. package/dist/tests/e2e/compare.e2e.test.d.ts.map +1 -0
  184. package/dist/tests/e2e/compare.e2e.test.js +296 -0
  185. package/dist/tests/e2e/compare.e2e.test.js.map +1 -0
  186. package/dist/tests/e2e/install-flow.e2e.test.d.ts +10 -0
  187. package/dist/tests/e2e/install-flow.e2e.test.d.ts.map +1 -0
  188. package/dist/tests/e2e/install-flow.e2e.test.js +229 -0
  189. package/dist/tests/e2e/install-flow.e2e.test.js.map +1 -0
  190. package/dist/tests/e2e/recommend.e2e.test.d.ts +12 -0
  191. package/dist/tests/e2e/recommend.e2e.test.d.ts.map +1 -0
  192. package/dist/tests/e2e/recommend.e2e.test.js +357 -0
  193. package/dist/tests/e2e/recommend.e2e.test.js.map +1 -0
  194. package/dist/tests/e2e/skill-flow.e2e.test.d.ts +10 -0
  195. package/dist/tests/e2e/skill-flow.e2e.test.d.ts.map +1 -0
  196. package/dist/tests/e2e/skill-flow.e2e.test.js +311 -0
  197. package/dist/tests/e2e/skill-flow.e2e.test.js.map +1 -0
  198. package/dist/tests/e2e/suggest.e2e.test.d.ts +13 -0
  199. package/dist/tests/e2e/suggest.e2e.test.d.ts.map +1 -0
  200. package/dist/tests/e2e/suggest.e2e.test.js +367 -0
  201. package/dist/tests/e2e/suggest.e2e.test.js.map +1 -0
  202. package/dist/tests/e2e/utils/baseline-collector.d.ts +107 -0
  203. package/dist/tests/e2e/utils/baseline-collector.d.ts.map +1 -0
  204. package/dist/tests/e2e/utils/baseline-collector.js +211 -0
  205. package/dist/tests/e2e/utils/baseline-collector.js.map +1 -0
  206. package/dist/tests/e2e/utils/hardcoded-detector.d.ts +46 -0
  207. package/dist/tests/e2e/utils/hardcoded-detector.d.ts.map +1 -0
  208. package/dist/tests/e2e/utils/hardcoded-detector.js +255 -0
  209. package/dist/tests/e2e/utils/hardcoded-detector.js.map +1 -0
  210. package/dist/tests/e2e/utils/index.d.ts +7 -0
  211. package/dist/tests/e2e/utils/index.d.ts.map +1 -0
  212. package/dist/tests/e2e/utils/index.js +7 -0
  213. package/dist/tests/e2e/utils/index.js.map +1 -0
  214. package/dist/tests/e2e/utils/linear-reporter.d.ts +60 -0
  215. package/dist/tests/e2e/utils/linear-reporter.d.ts.map +1 -0
  216. package/dist/tests/e2e/utils/linear-reporter.js +232 -0
  217. package/dist/tests/e2e/utils/linear-reporter.js.map +1 -0
  218. package/dist/tests/health.test.d.ts +9 -0
  219. package/dist/tests/health.test.d.ts.map +1 -0
  220. package/dist/tests/health.test.js +308 -0
  221. package/dist/tests/health.test.js.map +1 -0
  222. package/dist/tests/integration/analyze.integration.test.d.ts +2 -0
  223. package/dist/tests/integration/analyze.integration.test.d.ts.map +1 -0
  224. package/dist/tests/integration/analyze.integration.test.js +244 -0
  225. package/dist/tests/integration/analyze.integration.test.js.map +1 -0
  226. package/dist/tests/integration/compare.integration.test.d.ts +2 -0
  227. package/dist/tests/integration/compare.integration.test.d.ts.map +1 -0
  228. package/dist/tests/integration/compare.integration.test.js +120 -0
  229. package/dist/tests/integration/compare.integration.test.js.map +1 -0
  230. package/dist/tests/integration/fixtures/test-skills.d.ts +62 -0
  231. package/dist/tests/integration/fixtures/test-skills.d.ts.map +1 -0
  232. package/dist/tests/integration/fixtures/test-skills.js +644 -0
  233. package/dist/tests/integration/fixtures/test-skills.js.map +1 -0
  234. package/dist/tests/integration/get-skill.integration.test.d.ts +6 -0
  235. package/dist/tests/integration/get-skill.integration.test.d.ts.map +1 -0
  236. package/dist/tests/integration/get-skill.integration.test.js +203 -0
  237. package/dist/tests/integration/get-skill.integration.test.js.map +1 -0
  238. package/dist/tests/integration/github-api.integration.test.d.ts +14 -0
  239. package/dist/tests/integration/github-api.integration.test.d.ts.map +1 -0
  240. package/dist/tests/integration/github-api.integration.test.js +190 -0
  241. package/dist/tests/integration/github-api.integration.test.js.map +1 -0
  242. package/dist/tests/integration/install.integration.test.d.ts +6 -0
  243. package/dist/tests/integration/install.integration.test.d.ts.map +1 -0
  244. package/dist/tests/integration/install.integration.test.js +282 -0
  245. package/dist/tests/integration/install.integration.test.js.map +1 -0
  246. package/dist/tests/integration/recommend.integration.test.d.ts +2 -0
  247. package/dist/tests/integration/recommend.integration.test.d.ts.map +1 -0
  248. package/dist/tests/integration/recommend.integration.test.js +217 -0
  249. package/dist/tests/integration/recommend.integration.test.js.map +1 -0
  250. package/dist/tests/integration/search.integration.test.d.ts +6 -0
  251. package/dist/tests/integration/search.integration.test.d.ts.map +1 -0
  252. package/dist/tests/integration/search.integration.test.js +229 -0
  253. package/dist/tests/integration/search.integration.test.js.map +1 -0
  254. package/dist/tests/integration/setup.d.ts +74 -0
  255. package/dist/tests/integration/setup.d.ts.map +1 -0
  256. package/dist/tests/integration/setup.js +131 -0
  257. package/dist/tests/integration/setup.js.map +1 -0
  258. package/dist/tests/integration/uninstall.integration.test.d.ts +6 -0
  259. package/dist/tests/integration/uninstall.integration.test.d.ts.map +1 -0
  260. package/dist/tests/integration/uninstall.integration.test.js +296 -0
  261. package/dist/tests/integration/uninstall.integration.test.js.map +1 -0
  262. package/dist/tests/integration/validate.integration.test.d.ts +2 -0
  263. package/dist/tests/integration/validate.integration.test.d.ts.map +1 -0
  264. package/dist/tests/integration/validate.integration.test.js +181 -0
  265. package/dist/tests/integration/validate.integration.test.js.map +1 -0
  266. package/dist/tests/onboarding/first-run.test.d.ts +7 -0
  267. package/dist/tests/onboarding/first-run.test.d.ts.map +1 -0
  268. package/dist/tests/onboarding/first-run.test.js +264 -0
  269. package/dist/tests/onboarding/first-run.test.js.map +1 -0
  270. package/dist/tests/performance/search-performance.test.d.ts +10 -0
  271. package/dist/tests/performance/search-performance.test.d.ts.map +1 -0
  272. package/dist/tests/performance/search-performance.test.js +222 -0
  273. package/dist/tests/performance/search-performance.test.js.map +1 -0
  274. package/dist/tests/recommend.test.d.ts +6 -0
  275. package/dist/tests/recommend.test.d.ts.map +1 -0
  276. package/dist/tests/recommend.test.js +210 -0
  277. package/dist/tests/recommend.test.js.map +1 -0
  278. package/dist/tests/suggestions/suggestion-engine.test.d.ts +6 -0
  279. package/dist/tests/suggestions/suggestion-engine.test.d.ts.map +1 -0
  280. package/dist/tests/suggestions/suggestion-engine.test.js +448 -0
  281. package/dist/tests/suggestions/suggestion-engine.test.js.map +1 -0
  282. package/dist/tests/test-utils.d.ts +74 -0
  283. package/dist/tests/test-utils.d.ts.map +1 -0
  284. package/dist/tests/test-utils.js +98 -0
  285. package/dist/tests/test-utils.js.map +1 -0
  286. package/dist/tests/tools.test.d.ts +5 -0
  287. package/dist/tests/tools.test.d.ts.map +1 -0
  288. package/dist/tests/tools.test.js +138 -0
  289. package/dist/tests/tools.test.js.map +1 -0
  290. package/dist/tests/unit/installed-skills.test.d.ts +6 -0
  291. package/dist/tests/unit/installed-skills.test.d.ts.map +1 -0
  292. package/dist/tests/unit/installed-skills.test.js +285 -0
  293. package/dist/tests/unit/installed-skills.test.js.map +1 -0
  294. package/dist/tests/unit/logger.test.d.ts +6 -0
  295. package/dist/tests/unit/logger.test.d.ts.map +1 -0
  296. package/dist/tests/unit/logger.test.js +281 -0
  297. package/dist/tests/unit/logger.test.js.map +1 -0
  298. package/dist/tests/validate.test.d.ts +5 -0
  299. package/dist/tests/validate.test.d.ts.map +1 -0
  300. package/dist/tests/validate.test.js +303 -0
  301. package/dist/tests/validate.test.js.map +1 -0
  302. package/dist/tests/webhooks/proxy-trust.security.test.d.ts +8 -0
  303. package/dist/tests/webhooks/proxy-trust.security.test.d.ts.map +1 -0
  304. package/dist/tests/webhooks/proxy-trust.security.test.js +145 -0
  305. package/dist/tests/webhooks/proxy-trust.security.test.js.map +1 -0
  306. package/dist/tests/webhooks/rate-limiter.security.test.d.ts +8 -0
  307. package/dist/tests/webhooks/rate-limiter.security.test.d.ts.map +1 -0
  308. package/dist/tests/webhooks/rate-limiter.security.test.js +122 -0
  309. package/dist/tests/webhooks/rate-limiter.security.test.js.map +1 -0
  310. package/dist/vitest.config.d.ts +6 -0
  311. package/dist/vitest.config.d.ts.map +1 -0
  312. package/dist/vitest.config.js +13 -0
  313. package/dist/vitest.config.js.map +1 -0
  314. package/package.json +1 -1
@@ -0,0 +1,149 @@
1
+ /**
2
+ * SMI-645: Webhook Endpoint - HTTP server for GitHub webhooks
3
+ *
4
+ * Provides:
5
+ * - Express/Node.js HTTP server for receiving webhooks
6
+ * - Signature validation middleware
7
+ * - Rate limiting for security
8
+ * - Event routing to WebhookHandler
9
+ *
10
+ * Usage:
11
+ * import { createWebhookServer, startWebhookServer } from './webhooks/webhook-endpoint.js';
12
+ *
13
+ * const server = createWebhookServer({
14
+ * secret: process.env.GITHUB_WEBHOOK_SECRET,
15
+ * onIndexUpdate: (repoUrl, filePath) => { ... },
16
+ * });
17
+ *
18
+ * startWebhookServer(server, { port: 3000 });
19
+ */
20
+ import { IncomingMessage, Server } from 'http';
21
+ import { WebhookHandler, WebhookQueue, type WebhookQueueItem } from '@skillsmith/core';
22
+ /**
23
+ * Webhook server configuration (SMI-682: Added trust proxy options)
24
+ */
25
+ export interface WebhookServerConfig {
26
+ /**
27
+ * GitHub webhook secret for signature verification
28
+ */
29
+ secret: string;
30
+ /**
31
+ * Whether to trust X-Forwarded-For headers (default: false)
32
+ * SMI-682: Must be explicitly enabled for security
33
+ */
34
+ trustProxy?: boolean;
35
+ /**
36
+ * List of trusted proxy IPs (optional, for enhanced security)
37
+ * SMI-682: When set, X-Forwarded-For is only trusted from these IPs
38
+ */
39
+ trustedProxies?: string[];
40
+ }
41
+ /**
42
+ * Webhook server options
43
+ */
44
+ export interface WebhookServerOptions extends WebhookServerConfig {
45
+ /**
46
+ * Maximum request body size in bytes (default: 1MB)
47
+ */
48
+ maxBodySize?: number;
49
+ /**
50
+ * Rate limit: max requests per window (default: 100)
51
+ */
52
+ rateLimit?: number;
53
+ /**
54
+ * Rate limit window in ms (default: 60000 = 1 minute)
55
+ */
56
+ rateLimitWindow?: number;
57
+ /**
58
+ * Callback when a skill needs to be indexed/updated
59
+ */
60
+ onIndexUpdate?: (item: WebhookQueueItem) => Promise<void>;
61
+ /**
62
+ * Callback for logging
63
+ */
64
+ onLog?: (level: 'info' | 'warn' | 'error', message: string, data?: unknown) => void;
65
+ /**
66
+ * Queue options for debouncing and retry
67
+ */
68
+ queueOptions?: {
69
+ debounceMs?: number;
70
+ maxRetries?: number;
71
+ retryDelayMs?: number;
72
+ };
73
+ }
74
+ /**
75
+ * Server startup options
76
+ */
77
+ export interface ServerStartOptions {
78
+ /**
79
+ * Port to listen on (default: 3000)
80
+ */
81
+ port?: number;
82
+ /**
83
+ * Host to bind to (default: '0.0.0.0')
84
+ */
85
+ host?: string;
86
+ }
87
+ /**
88
+ * Rate limiter state (SMI-681: Added cleanup timer for memory leak prevention)
89
+ */
90
+ export interface RateLimiterState {
91
+ requests: Map<string, number[]>;
92
+ limit: number;
93
+ window: number;
94
+ cleanupTimer?: ReturnType<typeof setInterval>;
95
+ }
96
+ /**
97
+ * Create rate limiter with automatic cleanup (SMI-681)
98
+ * @param limit - Maximum requests per window
99
+ * @param windowMs - Window duration in milliseconds
100
+ */
101
+ export declare function createRateLimiter(limit: number, windowMs: number): RateLimiterState;
102
+ /**
103
+ * Destroy rate limiter and clean up resources (SMI-681)
104
+ */
105
+ export declare function destroyRateLimiter(state: RateLimiterState): void;
106
+ /**
107
+ * Check if request is rate limited
108
+ */
109
+ export declare function isRateLimited(limiter: RateLimiterState, ip: string): boolean;
110
+ /**
111
+ * Get client IP from request (SMI-682: Added trusted proxy validation)
112
+ * @param req - Incoming HTTP request
113
+ * @param config - Server configuration with trust proxy settings
114
+ */
115
+ export declare function getClientIp(req: IncomingMessage, config: WebhookServerConfig): string;
116
+ /**
117
+ * Webhook server instance
118
+ */
119
+ export interface WebhookServer {
120
+ /**
121
+ * The underlying HTTP server
122
+ */
123
+ server: Server;
124
+ /**
125
+ * The webhook handler
126
+ */
127
+ handler: WebhookHandler;
128
+ /**
129
+ * The webhook queue
130
+ */
131
+ queue: WebhookQueue;
132
+ }
133
+ /**
134
+ * Create a webhook server
135
+ */
136
+ export declare function createWebhookServer(options: WebhookServerOptions): WebhookServer;
137
+ /**
138
+ * Start the webhook server
139
+ */
140
+ export declare function startWebhookServer(webhookServer: WebhookServer, options?: ServerStartOptions): Promise<void>;
141
+ /**
142
+ * Stop the webhook server
143
+ */
144
+ export declare function stopWebhookServer(webhookServer: WebhookServer): Promise<void>;
145
+ /**
146
+ * Main entry point for standalone webhook server
147
+ */
148
+ export declare function main(): Promise<void>;
149
+ //# sourceMappingURL=webhook-endpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-endpoint.d.ts","sourceRoot":"","sources":["../../../src/webhooks/webhook-endpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAgB,eAAe,EAAkB,MAAM,EAAE,MAAM,MAAM,CAAA;AAC5E,OAAO,EACL,cAAc,EACd,YAAY,EACZ,KAAK,gBAAgB,EAEtB,MAAM,kBAAkB,CAAA;AAEzB;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;IAEd;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAEzD;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IAEnF;;OAEG;IACH,YAAY,CAAC,EAAE;QACb,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,YAAY,CAAC,EAAE,MAAM,CAAA;KACtB,CAAA;CACF;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;CAC9C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CA4BnF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAMhE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAoB5E;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAmCrF;AAoCD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,OAAO,EAAE,cAAc,CAAA;IAEvB;;OAEG;IACH,KAAK,EAAE,YAAY,CAAA;CACpB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CA0IhF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,aAAa,EAC5B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAW7E;AAED;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAuC1C"}
@@ -0,0 +1,339 @@
1
+ /**
2
+ * SMI-645: Webhook Endpoint - HTTP server for GitHub webhooks
3
+ *
4
+ * Provides:
5
+ * - Express/Node.js HTTP server for receiving webhooks
6
+ * - Signature validation middleware
7
+ * - Rate limiting for security
8
+ * - Event routing to WebhookHandler
9
+ *
10
+ * Usage:
11
+ * import { createWebhookServer, startWebhookServer } from './webhooks/webhook-endpoint.js';
12
+ *
13
+ * const server = createWebhookServer({
14
+ * secret: process.env.GITHUB_WEBHOOK_SECRET,
15
+ * onIndexUpdate: (repoUrl, filePath) => { ... },
16
+ * });
17
+ *
18
+ * startWebhookServer(server, { port: 3000 });
19
+ */
20
+ import { createServer } from 'http';
21
+ import { WebhookHandler, WebhookQueue, } from '@skillsmith/core';
22
+ /**
23
+ * Create rate limiter with automatic cleanup (SMI-681)
24
+ * @param limit - Maximum requests per window
25
+ * @param windowMs - Window duration in milliseconds
26
+ */
27
+ export function createRateLimiter(limit, windowMs) {
28
+ const state = {
29
+ requests: new Map(),
30
+ limit,
31
+ window: windowMs,
32
+ };
33
+ // SMI-681: Periodic cleanup to prevent memory leak
34
+ state.cleanupTimer = setInterval(() => {
35
+ const now = Date.now();
36
+ const windowStart = now - windowMs;
37
+ for (const [ip, timestamps] of state.requests.entries()) {
38
+ const valid = timestamps.filter((t) => t > windowStart);
39
+ if (valid.length === 0) {
40
+ state.requests.delete(ip);
41
+ }
42
+ else {
43
+ state.requests.set(ip, valid);
44
+ }
45
+ }
46
+ }, windowMs);
47
+ // Don't block process exit
48
+ if (state.cleanupTimer.unref) {
49
+ state.cleanupTimer.unref();
50
+ }
51
+ return state;
52
+ }
53
+ /**
54
+ * Destroy rate limiter and clean up resources (SMI-681)
55
+ */
56
+ export function destroyRateLimiter(state) {
57
+ if (state.cleanupTimer) {
58
+ clearInterval(state.cleanupTimer);
59
+ state.cleanupTimer = undefined;
60
+ }
61
+ state.requests.clear();
62
+ }
63
+ /**
64
+ * Check if request is rate limited
65
+ */
66
+ export function isRateLimited(limiter, ip) {
67
+ const now = Date.now();
68
+ const windowStart = now - limiter.window;
69
+ // Get existing requests for this IP
70
+ let requests = limiter.requests.get(ip) || [];
71
+ // Filter to only requests within the window
72
+ requests = requests.filter((time) => time > windowStart);
73
+ // Check if over limit
74
+ if (requests.length >= limiter.limit) {
75
+ return true;
76
+ }
77
+ // Add this request
78
+ requests.push(now);
79
+ limiter.requests.set(ip, requests);
80
+ return false;
81
+ }
82
+ /**
83
+ * Get client IP from request (SMI-682: Added trusted proxy validation)
84
+ * @param req - Incoming HTTP request
85
+ * @param config - Server configuration with trust proxy settings
86
+ */
87
+ export function getClientIp(req, config) {
88
+ // SMI-682: Only trust X-Forwarded-For if explicitly configured
89
+ if (config.trustProxy) {
90
+ const forwarded = req.headers['x-forwarded-for'];
91
+ if (typeof forwarded === 'string') {
92
+ const clientIp = forwarded.split(',')[0].trim();
93
+ // If trustedProxies specified, verify the request came from one
94
+ if (config.trustedProxies?.length) {
95
+ const remoteIp = req.socket.remoteAddress;
96
+ if (!config.trustedProxies.includes(remoteIp || '')) {
97
+ // Don't trust forwarded header from untrusted source
98
+ return remoteIp || 'unknown';
99
+ }
100
+ }
101
+ return clientIp;
102
+ }
103
+ if (Array.isArray(forwarded) && forwarded.length > 0) {
104
+ const clientIp = forwarded[0].split(',')[0].trim();
105
+ // If trustedProxies specified, verify the request came from one
106
+ if (config.trustedProxies?.length) {
107
+ const remoteIp = req.socket.remoteAddress;
108
+ if (!config.trustedProxies.includes(remoteIp || '')) {
109
+ return remoteIp || 'unknown';
110
+ }
111
+ }
112
+ return clientIp;
113
+ }
114
+ }
115
+ // Fall back to socket address
116
+ return req.socket.remoteAddress || 'unknown';
117
+ }
118
+ /**
119
+ * Read request body with size limit
120
+ */
121
+ async function readBody(req, maxSize) {
122
+ return new Promise((resolve, reject) => {
123
+ const chunks = [];
124
+ let size = 0;
125
+ req.on('data', (chunk) => {
126
+ size += chunk.length;
127
+ if (size > maxSize) {
128
+ req.destroy();
129
+ reject(new Error('Request body too large'));
130
+ return;
131
+ }
132
+ chunks.push(chunk);
133
+ });
134
+ req.on('end', () => {
135
+ resolve(Buffer.concat(chunks).toString('utf-8'));
136
+ });
137
+ req.on('error', reject);
138
+ });
139
+ }
140
+ /**
141
+ * Send JSON response
142
+ */
143
+ function sendJson(res, statusCode, data) {
144
+ res.writeHead(statusCode, { 'Content-Type': 'application/json' });
145
+ res.end(JSON.stringify(data));
146
+ }
147
+ /**
148
+ * Create a webhook server
149
+ */
150
+ export function createWebhookServer(options) {
151
+ const { secret, maxBodySize = 1024 * 1024, // 1MB
152
+ rateLimit = 100, rateLimitWindow = 60000, // 1 minute
153
+ trustProxy = false, // SMI-682: Default to not trusting proxy
154
+ trustedProxies, onIndexUpdate, onLog = () => { }, queueOptions = {}, } = options;
155
+ // SMI-682: Config for getClientIp
156
+ const serverConfig = {
157
+ secret,
158
+ trustProxy,
159
+ trustedProxies,
160
+ };
161
+ // Create rate limiter
162
+ const rateLimiter = createRateLimiter(rateLimit, rateLimitWindow);
163
+ // Create queue with processor
164
+ const queue = new WebhookQueue({
165
+ debounceMs: queueOptions.debounceMs ?? 5000,
166
+ maxRetries: queueOptions.maxRetries ?? 3,
167
+ retryDelayMs: queueOptions.retryDelayMs ?? 1000,
168
+ processor: onIndexUpdate,
169
+ onLog,
170
+ });
171
+ // Create handler
172
+ const handler = new WebhookHandler({
173
+ secret,
174
+ queue,
175
+ onLog,
176
+ });
177
+ // Create HTTP server
178
+ const server = createServer(async (req, res) => {
179
+ const url = req.url || '';
180
+ const method = req.method || 'GET';
181
+ // Health check endpoint
182
+ if (url === '/health' && method === 'GET') {
183
+ sendJson(res, 200, {
184
+ status: 'healthy',
185
+ queue: queue.getStats(),
186
+ });
187
+ return;
188
+ }
189
+ // Webhook endpoint
190
+ if (url === '/webhooks/github' && method === 'POST') {
191
+ // SMI-682: Use config for trusted proxy validation
192
+ const clientIp = getClientIp(req, serverConfig);
193
+ // Rate limiting
194
+ if (isRateLimited(rateLimiter, clientIp)) {
195
+ onLog('warn', 'Rate limit exceeded', { ip: clientIp });
196
+ sendJson(res, 429, {
197
+ error: 'Too many requests',
198
+ retryAfter: Math.ceil(rateLimitWindow / 1000),
199
+ });
200
+ return;
201
+ }
202
+ // Get event type from header
203
+ const eventType = req.headers['x-github-event'];
204
+ if (!eventType) {
205
+ sendJson(res, 400, { error: 'Missing X-GitHub-Event header' });
206
+ return;
207
+ }
208
+ // Get signature from header
209
+ const signature = req.headers['x-hub-signature-256'];
210
+ if (!signature) {
211
+ sendJson(res, 401, { error: 'Missing X-Hub-Signature-256 header' });
212
+ return;
213
+ }
214
+ // Get delivery ID for idempotency
215
+ const deliveryId = req.headers['x-github-delivery'];
216
+ // Read body
217
+ let body;
218
+ try {
219
+ body = await readBody(req, maxBodySize);
220
+ }
221
+ catch {
222
+ sendJson(res, 413, { error: 'Request body too large' });
223
+ return;
224
+ }
225
+ // Process webhook (pass delivery ID for idempotency)
226
+ let result;
227
+ try {
228
+ result = await handler.handleWebhook(eventType, body, signature, deliveryId);
229
+ }
230
+ catch (error) {
231
+ onLog('error', 'Webhook processing error', {
232
+ error: error instanceof Error ? error.message : String(error),
233
+ });
234
+ sendJson(res, 500, { error: 'Internal server error' });
235
+ return;
236
+ }
237
+ // Send response
238
+ if (result.success) {
239
+ sendJson(res, 200, {
240
+ success: true,
241
+ message: result.message,
242
+ changesDetected: result.changesDetected,
243
+ itemsQueued: result.itemsQueued,
244
+ });
245
+ }
246
+ else {
247
+ const statusCode = result.error?.includes('Signature') ? 401 : 400;
248
+ sendJson(res, statusCode, {
249
+ success: false,
250
+ error: result.error,
251
+ });
252
+ }
253
+ return;
254
+ }
255
+ // Queue status endpoint (for monitoring)
256
+ if (url === '/webhooks/status' && method === 'GET') {
257
+ sendJson(res, 200, {
258
+ queue: queue.getStats(),
259
+ hasPending: queue.hasPendingItems(),
260
+ });
261
+ return;
262
+ }
263
+ // 404 for unknown routes
264
+ sendJson(res, 404, { error: 'Not found' });
265
+ });
266
+ return { server, handler, queue };
267
+ }
268
+ /**
269
+ * Start the webhook server
270
+ */
271
+ export function startWebhookServer(webhookServer, options = {}) {
272
+ const { port = 3000, host = '0.0.0.0' } = options;
273
+ return new Promise((resolve) => {
274
+ webhookServer.server.listen(port, host, () => {
275
+ console.log(`Webhook server listening on http://${host}:${port}`);
276
+ console.log(`GitHub webhook URL: http://${host}:${port}/webhooks/github`);
277
+ resolve();
278
+ });
279
+ });
280
+ }
281
+ /**
282
+ * Stop the webhook server
283
+ */
284
+ export function stopWebhookServer(webhookServer) {
285
+ return new Promise((resolve, reject) => {
286
+ webhookServer.queue.clear();
287
+ webhookServer.server.close((err) => {
288
+ if (err) {
289
+ reject(err);
290
+ }
291
+ else {
292
+ resolve();
293
+ }
294
+ });
295
+ });
296
+ }
297
+ /**
298
+ * Main entry point for standalone webhook server
299
+ */
300
+ export async function main() {
301
+ const secret = process.env.GITHUB_WEBHOOK_SECRET;
302
+ if (!secret) {
303
+ console.error('Error: GITHUB_WEBHOOK_SECRET environment variable is required');
304
+ process.exit(1);
305
+ }
306
+ const port = parseInt(process.env.WEBHOOK_PORT || '3000', 10);
307
+ const host = process.env.WEBHOOK_HOST || '0.0.0.0';
308
+ const webhookServer = createWebhookServer({
309
+ secret,
310
+ onLog: (level, message, data) => {
311
+ const timestamp = new Date().toISOString();
312
+ console.log(`[${timestamp}] [${level.toUpperCase()}] ${message}`, data ? JSON.stringify(data) : '');
313
+ },
314
+ onIndexUpdate: async (item) => {
315
+ // In standalone mode, just log the update
316
+ // In production, this would trigger re-indexing
317
+ console.log(`[INDEX UPDATE] ${item.type}: ${item.repoFullName} - ${item.filePath}`);
318
+ },
319
+ });
320
+ await startWebhookServer(webhookServer, { port, host });
321
+ // Handle graceful shutdown
322
+ const shutdown = async () => {
323
+ console.log('\nShutting down webhook server...');
324
+ await stopWebhookServer(webhookServer);
325
+ console.log('Webhook server stopped');
326
+ process.exit(0);
327
+ };
328
+ process.on('SIGINT', shutdown);
329
+ process.on('SIGTERM', shutdown);
330
+ }
331
+ // Run if this is the main module
332
+ // Note: ESM doesn't have require.main === module, so we check for CLI flag
333
+ if (process.argv.includes('--standalone')) {
334
+ main().catch((error) => {
335
+ console.error('Failed to start webhook server:', error);
336
+ process.exit(1);
337
+ });
338
+ }
339
+ //# sourceMappingURL=webhook-endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-endpoint.js","sourceRoot":"","sources":["../../../src/webhooks/webhook-endpoint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tests for SMI-743: MCP Skill Compare Tool
3
+ * Updated for SMI-791: Wire to SkillRepository
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=compare.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.test.d.ts","sourceRoot":"","sources":["../../tests/compare.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}