@generacy-ai/orchestrator 0.0.0-preview-20260304013206

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 (274) hide show
  1. package/LICENSE +191 -0
  2. package/dist/auth/api-key.d.ts +63 -0
  3. package/dist/auth/api-key.d.ts.map +1 -0
  4. package/dist/auth/api-key.js +102 -0
  5. package/dist/auth/api-key.js.map +1 -0
  6. package/dist/auth/github-oauth.d.ts +29 -0
  7. package/dist/auth/github-oauth.d.ts.map +1 -0
  8. package/dist/auth/github-oauth.js +136 -0
  9. package/dist/auth/github-oauth.js.map +1 -0
  10. package/dist/auth/index.d.ts +5 -0
  11. package/dist/auth/index.d.ts.map +1 -0
  12. package/dist/auth/index.js +9 -0
  13. package/dist/auth/index.js.map +1 -0
  14. package/dist/auth/jwt.d.ts +34 -0
  15. package/dist/auth/jwt.d.ts.map +1 -0
  16. package/dist/auth/jwt.js +74 -0
  17. package/dist/auth/jwt.js.map +1 -0
  18. package/dist/auth/middleware.d.ts +43 -0
  19. package/dist/auth/middleware.d.ts.map +1 -0
  20. package/dist/auth/middleware.js +101 -0
  21. package/dist/auth/middleware.js.map +1 -0
  22. package/dist/config/index.d.ts +3 -0
  23. package/dist/config/index.d.ts.map +1 -0
  24. package/dist/config/index.js +5 -0
  25. package/dist/config/index.js.map +1 -0
  26. package/dist/config/loader.d.ts +21 -0
  27. package/dist/config/loader.d.ts.map +1 -0
  28. package/dist/config/loader.js +295 -0
  29. package/dist/config/loader.js.map +1 -0
  30. package/dist/config/schema.d.ts +733 -0
  31. package/dist/config/schema.d.ts.map +1 -0
  32. package/dist/config/schema.js +174 -0
  33. package/dist/config/schema.js.map +1 -0
  34. package/dist/index.d.ts +24 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +33 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/middleware/error-handler.d.ts +30 -0
  39. package/dist/middleware/error-handler.d.ts.map +1 -0
  40. package/dist/middleware/error-handler.js +173 -0
  41. package/dist/middleware/error-handler.js.map +1 -0
  42. package/dist/middleware/index.d.ts +4 -0
  43. package/dist/middleware/index.d.ts.map +1 -0
  44. package/dist/middleware/index.js +4 -0
  45. package/dist/middleware/index.js.map +1 -0
  46. package/dist/middleware/rate-limit.d.ts +32 -0
  47. package/dist/middleware/rate-limit.d.ts.map +1 -0
  48. package/dist/middleware/rate-limit.js +92 -0
  49. package/dist/middleware/rate-limit.js.map +1 -0
  50. package/dist/middleware/request-logger.d.ts +31 -0
  51. package/dist/middleware/request-logger.d.ts.map +1 -0
  52. package/dist/middleware/request-logger.js +89 -0
  53. package/dist/middleware/request-logger.js.map +1 -0
  54. package/dist/routes/agents.d.ts +7 -0
  55. package/dist/routes/agents.d.ts.map +1 -0
  56. package/dist/routes/agents.js +78 -0
  57. package/dist/routes/agents.js.map +1 -0
  58. package/dist/routes/dispatch.d.ts +8 -0
  59. package/dist/routes/dispatch.d.ts.map +1 -0
  60. package/dist/routes/dispatch.js +46 -0
  61. package/dist/routes/dispatch.js.map +1 -0
  62. package/dist/routes/events.d.ts +14 -0
  63. package/dist/routes/events.d.ts.map +1 -0
  64. package/dist/routes/events.js +240 -0
  65. package/dist/routes/events.js.map +1 -0
  66. package/dist/routes/health.d.ts +14 -0
  67. package/dist/routes/health.d.ts.map +1 -0
  68. package/dist/routes/health.js +132 -0
  69. package/dist/routes/health.js.map +1 -0
  70. package/dist/routes/index.d.ts +36 -0
  71. package/dist/routes/index.d.ts.map +1 -0
  72. package/dist/routes/index.js +34 -0
  73. package/dist/routes/index.js.map +1 -0
  74. package/dist/routes/integrations.d.ts +34 -0
  75. package/dist/routes/integrations.d.ts.map +1 -0
  76. package/dist/routes/integrations.js +81 -0
  77. package/dist/routes/integrations.js.map +1 -0
  78. package/dist/routes/metrics.d.ts +31 -0
  79. package/dist/routes/metrics.d.ts.map +1 -0
  80. package/dist/routes/metrics.js +157 -0
  81. package/dist/routes/metrics.js.map +1 -0
  82. package/dist/routes/pr-webhooks.d.ts +15 -0
  83. package/dist/routes/pr-webhooks.d.ts.map +1 -0
  84. package/dist/routes/pr-webhooks.js +114 -0
  85. package/dist/routes/pr-webhooks.js.map +1 -0
  86. package/dist/routes/queue.d.ts +7 -0
  87. package/dist/routes/queue.d.ts.map +1 -0
  88. package/dist/routes/queue.js +94 -0
  89. package/dist/routes/queue.js.map +1 -0
  90. package/dist/routes/webhooks.d.ts +15 -0
  91. package/dist/routes/webhooks.d.ts.map +1 -0
  92. package/dist/routes/webhooks.js +117 -0
  93. package/dist/routes/webhooks.js.map +1 -0
  94. package/dist/routes/workflows.d.ts +7 -0
  95. package/dist/routes/workflows.d.ts.map +1 -0
  96. package/dist/routes/workflows.js +138 -0
  97. package/dist/routes/workflows.js.map +1 -0
  98. package/dist/server.d.ts +35 -0
  99. package/dist/server.d.ts.map +1 -0
  100. package/dist/server.js +264 -0
  101. package/dist/server.js.map +1 -0
  102. package/dist/services/agent-registry.d.ts +89 -0
  103. package/dist/services/agent-registry.d.ts.map +1 -0
  104. package/dist/services/agent-registry.js +173 -0
  105. package/dist/services/agent-registry.js.map +1 -0
  106. package/dist/services/epic-completion-monitor-service.d.ts +69 -0
  107. package/dist/services/epic-completion-monitor-service.d.ts.map +1 -0
  108. package/dist/services/epic-completion-monitor-service.js +200 -0
  109. package/dist/services/epic-completion-monitor-service.js.map +1 -0
  110. package/dist/services/identity.d.ts +41 -0
  111. package/dist/services/identity.d.ts.map +1 -0
  112. package/dist/services/identity.js +91 -0
  113. package/dist/services/identity.js.map +1 -0
  114. package/dist/services/index.d.ts +13 -0
  115. package/dist/services/index.d.ts.map +1 -0
  116. package/dist/services/index.js +13 -0
  117. package/dist/services/index.js.map +1 -0
  118. package/dist/services/label-monitor-service.d.ts +95 -0
  119. package/dist/services/label-monitor-service.d.ts.map +1 -0
  120. package/dist/services/label-monitor-service.js +414 -0
  121. package/dist/services/label-monitor-service.js.map +1 -0
  122. package/dist/services/label-sync-service.d.ts +76 -0
  123. package/dist/services/label-sync-service.d.ts.map +1 -0
  124. package/dist/services/label-sync-service.js +108 -0
  125. package/dist/services/label-sync-service.js.map +1 -0
  126. package/dist/services/phase-tracker-service.d.ts +32 -0
  127. package/dist/services/phase-tracker-service.d.ts.map +1 -0
  128. package/dist/services/phase-tracker-service.js +82 -0
  129. package/dist/services/phase-tracker-service.js.map +1 -0
  130. package/dist/services/pr-feedback-monitor-service.d.ts +86 -0
  131. package/dist/services/pr-feedback-monitor-service.d.ts.map +1 -0
  132. package/dist/services/pr-feedback-monitor-service.js +423 -0
  133. package/dist/services/pr-feedback-monitor-service.js.map +1 -0
  134. package/dist/services/queue-service.d.ts +62 -0
  135. package/dist/services/queue-service.d.ts.map +1 -0
  136. package/dist/services/queue-service.js +147 -0
  137. package/dist/services/queue-service.js.map +1 -0
  138. package/dist/services/redis-queue-adapter.d.ts +35 -0
  139. package/dist/services/redis-queue-adapter.d.ts.map +1 -0
  140. package/dist/services/redis-queue-adapter.js +218 -0
  141. package/dist/services/redis-queue-adapter.js.map +1 -0
  142. package/dist/services/smee-receiver.d.ts +87 -0
  143. package/dist/services/smee-receiver.d.ts.map +1 -0
  144. package/dist/services/smee-receiver.js +225 -0
  145. package/dist/services/smee-receiver.js.map +1 -0
  146. package/dist/services/webhook-setup-service.d.ts +253 -0
  147. package/dist/services/webhook-setup-service.d.ts.map +1 -0
  148. package/dist/services/webhook-setup-service.js +369 -0
  149. package/dist/services/webhook-setup-service.js.map +1 -0
  150. package/dist/services/worker-dispatcher.d.ts +57 -0
  151. package/dist/services/worker-dispatcher.d.ts.map +1 -0
  152. package/dist/services/worker-dispatcher.js +211 -0
  153. package/dist/services/worker-dispatcher.js.map +1 -0
  154. package/dist/services/workflow-service.d.ts +65 -0
  155. package/dist/services/workflow-service.d.ts.map +1 -0
  156. package/dist/services/workflow-service.js +164 -0
  157. package/dist/services/workflow-service.js.map +1 -0
  158. package/dist/sse/events.d.ts +50 -0
  159. package/dist/sse/events.d.ts.map +1 -0
  160. package/dist/sse/events.js +152 -0
  161. package/dist/sse/events.js.map +1 -0
  162. package/dist/sse/index.d.ts +4 -0
  163. package/dist/sse/index.d.ts.map +1 -0
  164. package/dist/sse/index.js +7 -0
  165. package/dist/sse/index.js.map +1 -0
  166. package/dist/sse/stream.d.ts +109 -0
  167. package/dist/sse/stream.d.ts.map +1 -0
  168. package/dist/sse/stream.js +239 -0
  169. package/dist/sse/stream.js.map +1 -0
  170. package/dist/sse/subscriptions.d.ts +91 -0
  171. package/dist/sse/subscriptions.d.ts.map +1 -0
  172. package/dist/sse/subscriptions.js +299 -0
  173. package/dist/sse/subscriptions.js.map +1 -0
  174. package/dist/types/api.d.ts +651 -0
  175. package/dist/types/api.d.ts.map +1 -0
  176. package/dist/types/api.js +169 -0
  177. package/dist/types/api.js.map +1 -0
  178. package/dist/types/index.d.ts +6 -0
  179. package/dist/types/index.d.ts.map +1 -0
  180. package/dist/types/index.js +27 -0
  181. package/dist/types/index.js.map +1 -0
  182. package/dist/types/monitor.d.ts +243 -0
  183. package/dist/types/monitor.d.ts.map +1 -0
  184. package/dist/types/monitor.js +2 -0
  185. package/dist/types/monitor.js.map +1 -0
  186. package/dist/types/problem-details.d.ts +63 -0
  187. package/dist/types/problem-details.d.ts.map +1 -0
  188. package/dist/types/problem-details.js +37 -0
  189. package/dist/types/problem-details.js.map +1 -0
  190. package/dist/types/sse.d.ts +224 -0
  191. package/dist/types/sse.d.ts.map +1 -0
  192. package/dist/types/sse.js +103 -0
  193. package/dist/types/sse.js.map +1 -0
  194. package/dist/types/webhook.d.ts +59 -0
  195. package/dist/types/webhook.d.ts.map +1 -0
  196. package/dist/types/webhook.js +2 -0
  197. package/dist/types/webhook.js.map +1 -0
  198. package/dist/utils/correlation.d.ts +30 -0
  199. package/dist/utils/correlation.d.ts.map +1 -0
  200. package/dist/utils/correlation.js +34 -0
  201. package/dist/utils/correlation.js.map +1 -0
  202. package/dist/utils/index.d.ts +3 -0
  203. package/dist/utils/index.d.ts.map +1 -0
  204. package/dist/utils/index.js +3 -0
  205. package/dist/utils/index.js.map +1 -0
  206. package/dist/utils/shutdown.d.ts +28 -0
  207. package/dist/utils/shutdown.d.ts.map +1 -0
  208. package/dist/utils/shutdown.js +86 -0
  209. package/dist/utils/shutdown.js.map +1 -0
  210. package/dist/worker/claude-cli-worker.d.ts +61 -0
  211. package/dist/worker/claude-cli-worker.d.ts.map +1 -0
  212. package/dist/worker/claude-cli-worker.js +330 -0
  213. package/dist/worker/claude-cli-worker.js.map +1 -0
  214. package/dist/worker/cli-spawner.d.ts +42 -0
  215. package/dist/worker/cli-spawner.d.ts.map +1 -0
  216. package/dist/worker/cli-spawner.js +183 -0
  217. package/dist/worker/cli-spawner.js.map +1 -0
  218. package/dist/worker/config.d.ts +76 -0
  219. package/dist/worker/config.d.ts.map +1 -0
  220. package/dist/worker/config.js +39 -0
  221. package/dist/worker/config.js.map +1 -0
  222. package/dist/worker/epic-post-tasks.d.ts +73 -0
  223. package/dist/worker/epic-post-tasks.d.ts.map +1 -0
  224. package/dist/worker/epic-post-tasks.js +266 -0
  225. package/dist/worker/epic-post-tasks.js.map +1 -0
  226. package/dist/worker/gate-checker.d.ts +22 -0
  227. package/dist/worker/gate-checker.d.ts.map +1 -0
  228. package/dist/worker/gate-checker.js +41 -0
  229. package/dist/worker/gate-checker.js.map +1 -0
  230. package/dist/worker/index.d.ts +13 -0
  231. package/dist/worker/index.d.ts.map +1 -0
  232. package/dist/worker/index.js +19 -0
  233. package/dist/worker/index.js.map +1 -0
  234. package/dist/worker/label-manager.d.ts +89 -0
  235. package/dist/worker/label-manager.d.ts.map +1 -0
  236. package/dist/worker/label-manager.js +200 -0
  237. package/dist/worker/label-manager.js.map +1 -0
  238. package/dist/worker/output-capture.d.ts +58 -0
  239. package/dist/worker/output-capture.d.ts.map +1 -0
  240. package/dist/worker/output-capture.js +153 -0
  241. package/dist/worker/output-capture.js.map +1 -0
  242. package/dist/worker/phase-loop.d.ts +64 -0
  243. package/dist/worker/phase-loop.d.ts.map +1 -0
  244. package/dist/worker/phase-loop.js +185 -0
  245. package/dist/worker/phase-loop.js.map +1 -0
  246. package/dist/worker/phase-resolver.d.ts +62 -0
  247. package/dist/worker/phase-resolver.d.ts.map +1 -0
  248. package/dist/worker/phase-resolver.js +144 -0
  249. package/dist/worker/phase-resolver.js.map +1 -0
  250. package/dist/worker/pr-feedback-handler.d.ts +105 -0
  251. package/dist/worker/pr-feedback-handler.d.ts.map +1 -0
  252. package/dist/worker/pr-feedback-handler.js +391 -0
  253. package/dist/worker/pr-feedback-handler.js.map +1 -0
  254. package/dist/worker/pr-linker.d.ts +69 -0
  255. package/dist/worker/pr-linker.d.ts.map +1 -0
  256. package/dist/worker/pr-linker.js +108 -0
  257. package/dist/worker/pr-linker.js.map +1 -0
  258. package/dist/worker/pr-manager.d.ts +61 -0
  259. package/dist/worker/pr-manager.d.ts.map +1 -0
  260. package/dist/worker/pr-manager.js +140 -0
  261. package/dist/worker/pr-manager.js.map +1 -0
  262. package/dist/worker/repo-checkout.d.ts +63 -0
  263. package/dist/worker/repo-checkout.d.ts.map +1 -0
  264. package/dist/worker/repo-checkout.js +160 -0
  265. package/dist/worker/repo-checkout.js.map +1 -0
  266. package/dist/worker/stage-comment-manager.d.ts +34 -0
  267. package/dist/worker/stage-comment-manager.d.ts.map +1 -0
  268. package/dist/worker/stage-comment-manager.js +114 -0
  269. package/dist/worker/stage-comment-manager.js.map +1 -0
  270. package/dist/worker/types.d.ts +192 -0
  271. package/dist/worker/types.d.ts.map +1 -0
  272. package/dist/worker/types.js +53 -0
  273. package/dist/worker/types.js.map +1 -0
  274. package/package.json +64 -0
@@ -0,0 +1,114 @@
1
+ import { createHmac, timingSafeEqual } from 'node:crypto';
2
+ /**
3
+ * Verify the HMAC-SHA256 signature from GitHub webhook.
4
+ * Returns true if signature is valid or if no secret is configured.
5
+ */
6
+ function verifySignature(secret, rawBody, signatureHeader) {
7
+ if (!secret) {
8
+ // No secret configured — skip verification (dev mode)
9
+ return true;
10
+ }
11
+ if (!signatureHeader) {
12
+ return false;
13
+ }
14
+ const expectedPrefix = 'sha256=';
15
+ if (!signatureHeader.startsWith(expectedPrefix)) {
16
+ return false;
17
+ }
18
+ const signature = signatureHeader.slice(expectedPrefix.length);
19
+ const hmac = createHmac('sha256', secret).update(rawBody).digest('hex');
20
+ // Use timing-safe comparison to prevent timing attacks
21
+ try {
22
+ return timingSafeEqual(Buffer.from(signature, 'hex'), Buffer.from(hmac, 'hex'));
23
+ }
24
+ catch {
25
+ return false;
26
+ }
27
+ }
28
+ /**
29
+ * Setup webhook routes for receiving GitHub PR review events.
30
+ * The webhook route bypasses global auth middleware — authentication
31
+ * is handled via HMAC-SHA256 signature verification.
32
+ */
33
+ export async function setupPrWebhookRoutes(server, options) {
34
+ const { monitorService, webhookSecret, watchedRepos } = options;
35
+ // Register a custom content type parser to capture raw body for signature verification
36
+ server.addContentTypeParser('application/json', { parseAs: 'string' }, (_req, body, done) => {
37
+ try {
38
+ const json = JSON.parse(body);
39
+ // Attach raw body for signature verification
40
+ done(null, { parsed: json, raw: body });
41
+ }
42
+ catch (err) {
43
+ done(err, undefined);
44
+ }
45
+ });
46
+ // Auth is skipped for /webhooks/github/pr-review via server.ts skipRoutes config.
47
+ // Authentication is handled via HMAC-SHA256 signature verification.
48
+ server.post('/webhooks/github/pr-review', {}, async (request, reply) => {
49
+ const body = request.body;
50
+ const rawBody = body.raw;
51
+ const payload = body.parsed;
52
+ // Verify webhook signature
53
+ const signatureHeader = request.headers['x-hub-signature-256'];
54
+ if (!verifySignature(webhookSecret, rawBody, signatureHeader)) {
55
+ server.log.warn('Invalid webhook signature for PR review event');
56
+ return reply.status(401).send({ error: 'Invalid signature' });
57
+ }
58
+ // Check the GitHub event type from the X-GitHub-Event header
59
+ const eventType = request.headers['x-github-event'];
60
+ // Only handle pull_request_review.submitted and pull_request_review_comment.created events
61
+ const validEvents = ['pull_request_review', 'pull_request_review_comment'];
62
+ if (!eventType || !validEvents.includes(eventType)) {
63
+ return reply.status(200).send({
64
+ status: 'ignored',
65
+ reason: `not a PR review event (got: ${eventType})`
66
+ });
67
+ }
68
+ // For pull_request_review events, only process "submitted" action
69
+ if (eventType === 'pull_request_review' && payload.action !== 'submitted') {
70
+ return reply.status(200).send({
71
+ status: 'ignored',
72
+ reason: `not a submitted review (got action: ${payload.action})`
73
+ });
74
+ }
75
+ // For pull_request_review_comment events, only process "created" action
76
+ if (eventType === 'pull_request_review_comment' && payload.action !== 'created') {
77
+ return reply.status(200).send({
78
+ status: 'ignored',
79
+ reason: `not a created comment (got action: ${payload.action})`
80
+ });
81
+ }
82
+ // Verify this is a watched repository
83
+ const repoKey = `${payload.repository.owner.login}/${payload.repository.name}`;
84
+ if (!watchedRepos.has(repoKey)) {
85
+ return reply.status(200).send({
86
+ status: 'ignored',
87
+ reason: 'not a watched repository'
88
+ });
89
+ }
90
+ // Build PrReviewEvent from webhook payload
91
+ const event = {
92
+ owner: payload.repository.owner.login,
93
+ repo: payload.repository.name,
94
+ prNumber: payload.pull_request.number,
95
+ prBody: payload.pull_request.body || '',
96
+ branchName: payload.pull_request.head.ref,
97
+ source: 'webhook',
98
+ };
99
+ // Record webhook event for adaptive polling health tracking
100
+ monitorService.recordWebhookEvent();
101
+ // Process the event
102
+ const processed = await monitorService.processPrReviewEvent(event);
103
+ return reply.status(200).send({
104
+ status: processed ? 'processed' : 'duplicate',
105
+ event: {
106
+ type: eventType,
107
+ action: payload.action,
108
+ pr: payload.pull_request.number,
109
+ repo: repoKey,
110
+ },
111
+ });
112
+ });
113
+ }
114
+ //# sourceMappingURL=pr-webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr-webhooks.js","sourceRoot":"","sources":["../../src/routes/pr-webhooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import { QueueService } from '../services/queue-service.js';
3
+ /**
4
+ * Setup queue routes
5
+ */
6
+ export declare function setupQueueRoutes(server: FastifyInstance, queueService: QueueService): Promise<void>;
7
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/routes/queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAO7E,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAK5D;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,IAAI,CAAC,CAuHf"}
@@ -0,0 +1,94 @@
1
+ import { QueueQuerySchema, DecisionIdParamSchema, DecisionResponseRequestSchema, CreateDecisionRequestSchema, } from '../types/index.js';
2
+ import { requireRead, requireWrite } from '../auth/middleware.js';
3
+ import { getSSESubscriptionManager } from '../sse/subscriptions.js';
4
+ import { createQueueEvent } from '../sse/events.js';
5
+ /**
6
+ * Setup queue routes
7
+ */
8
+ export async function setupQueueRoutes(server, queueService) {
9
+ // GET /queue - Get decision queue
10
+ server.get('/queue', {
11
+ preHandler: [requireRead('queue')],
12
+ schema: {
13
+ querystring: {
14
+ type: 'object',
15
+ properties: {
16
+ priority: {
17
+ type: 'string',
18
+ enum: ['blocking_now', 'blocking_soon', 'when_available'],
19
+ },
20
+ workflowId: { type: 'string' },
21
+ },
22
+ },
23
+ },
24
+ }, async (request, reply) => {
25
+ const query = QueueQuerySchema.parse(request.query);
26
+ const items = await queueService.getQueue(query);
27
+ return reply.send(items);
28
+ });
29
+ // POST /queue - Create a new decision
30
+ server.post('/queue', {
31
+ preHandler: [requireWrite('queue')],
32
+ // Body validation done by Zod in handler to support defaults and coercion
33
+ }, async (request, reply) => {
34
+ const body = CreateDecisionRequestSchema.parse(request.body);
35
+ const item = await queueService.createDecision(body);
36
+ // Broadcast queue:item:added SSE event
37
+ const queue = await queueService.getQueue();
38
+ const manager = getSSESubscriptionManager();
39
+ const event = createQueueEvent('added', [item], queue.length, 'internal', Date.now());
40
+ manager.broadcast('queue', event);
41
+ return reply.status(201).send(item);
42
+ });
43
+ // GET /queue/:id - Get specific decision
44
+ server.get('/queue/:id', {
45
+ preHandler: [requireRead('queue')],
46
+ schema: {
47
+ params: {
48
+ type: 'object',
49
+ properties: {
50
+ id: { type: 'string', format: 'uuid' },
51
+ },
52
+ required: ['id'],
53
+ },
54
+ },
55
+ }, async (request, reply) => {
56
+ const params = DecisionIdParamSchema.parse(request.params);
57
+ const decision = await queueService.getDecision(params.id);
58
+ return reply.send(decision);
59
+ });
60
+ // POST /queue/:id/respond - Submit decision response
61
+ server.post('/queue/:id/respond', {
62
+ preHandler: [requireWrite('queue')],
63
+ schema: {
64
+ params: {
65
+ type: 'object',
66
+ properties: {
67
+ id: { type: 'string', format: 'uuid' },
68
+ },
69
+ required: ['id'],
70
+ },
71
+ // Body validation done by Zod in handler to support complex union types
72
+ },
73
+ }, async (request, reply) => {
74
+ const params = DecisionIdParamSchema.parse(request.params);
75
+ const body = DecisionResponseRequestSchema.parse(request.body);
76
+ // Fetch the decision item before responding (respond removes it from the queue)
77
+ const item = await queueService.getDecision(params.id);
78
+ const response = await queueService.respond(params.id, body, request.auth.userId);
79
+ // Broadcast queue:item:removed SSE event with the response included
80
+ const queue = await queueService.getQueue();
81
+ const manager = getSSESubscriptionManager();
82
+ const event = createQueueEvent('removed', [item], queue.length, 'internal', Date.now(), response);
83
+ manager.broadcast('queue', event);
84
+ return reply.send(response);
85
+ });
86
+ // GET /queue/stats - Get queue statistics
87
+ server.get('/queue/stats', {
88
+ preHandler: [requireRead('queue')],
89
+ }, async (_request, reply) => {
90
+ const stats = await queueService.getQueueStats();
91
+ return reply.send(stats);
92
+ });
93
+ }
94
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/routes/queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import type { LabelMonitorService } from '../services/label-monitor-service.js';
3
+ export interface WebhookRouteOptions {
4
+ monitorService: LabelMonitorService;
5
+ webhookSecret?: string;
6
+ watchedRepos: Set<string>;
7
+ clusterGithubUsername?: string;
8
+ }
9
+ /**
10
+ * Setup webhook routes for receiving GitHub events.
11
+ * The webhook route bypasses global auth middleware — authentication
12
+ * is handled via HMAC-SHA256 signature verification.
13
+ */
14
+ export declare function setupWebhookRoutes(server: FastifyInstance, options: WebhookRouteOptions): Promise<void>;
15
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/routes/webhooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAE7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAiChF,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,mBAAmB,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CA2Hf"}
@@ -0,0 +1,117 @@
1
+ import { createHmac, timingSafeEqual } from 'node:crypto';
2
+ /**
3
+ * Verify the HMAC-SHA256 signature from GitHub webhook.
4
+ * Returns true if signature is valid or if no secret is configured.
5
+ */
6
+ function verifySignature(secret, rawBody, signatureHeader) {
7
+ if (!secret) {
8
+ // No secret configured — skip verification (dev mode)
9
+ return true;
10
+ }
11
+ if (!signatureHeader) {
12
+ return false;
13
+ }
14
+ const expectedPrefix = 'sha256=';
15
+ if (!signatureHeader.startsWith(expectedPrefix)) {
16
+ return false;
17
+ }
18
+ const signature = signatureHeader.slice(expectedPrefix.length);
19
+ const hmac = createHmac('sha256', secret).update(rawBody).digest('hex');
20
+ // Use timing-safe comparison to prevent timing attacks
21
+ try {
22
+ return timingSafeEqual(Buffer.from(signature, 'hex'), Buffer.from(hmac, 'hex'));
23
+ }
24
+ catch {
25
+ return false;
26
+ }
27
+ }
28
+ /**
29
+ * Setup webhook routes for receiving GitHub events.
30
+ * The webhook route bypasses global auth middleware — authentication
31
+ * is handled via HMAC-SHA256 signature verification.
32
+ */
33
+ export async function setupWebhookRoutes(server, options) {
34
+ const { monitorService, webhookSecret, watchedRepos, clusterGithubUsername } = options;
35
+ // Register a custom content type parser to capture raw body for signature verification
36
+ server.addContentTypeParser('application/json', { parseAs: 'string' }, (_req, body, done) => {
37
+ try {
38
+ const json = JSON.parse(body);
39
+ // Attach raw body for signature verification
40
+ done(null, { parsed: json, raw: body });
41
+ }
42
+ catch (err) {
43
+ done(err, undefined);
44
+ }
45
+ });
46
+ // Auth is skipped for /webhooks/github via server.ts skipRoutes config.
47
+ // Authentication is handled via HMAC-SHA256 signature verification.
48
+ server.post('/webhooks/github', {}, async (request, reply) => {
49
+ const body = request.body;
50
+ const rawBody = body.raw;
51
+ const payload = body.parsed;
52
+ // Verify webhook signature
53
+ const signatureHeader = request.headers['x-hub-signature-256'];
54
+ if (!verifySignature(webhookSecret, rawBody, signatureHeader)) {
55
+ server.log.warn('Invalid webhook signature');
56
+ return reply.status(401).send({ error: 'Invalid signature' });
57
+ }
58
+ // Only handle "labeled" events
59
+ if (payload.action !== 'labeled') {
60
+ return reply.status(200).send({ status: 'ignored', reason: 'not a labeled event' });
61
+ }
62
+ // Verify this is a watched repository
63
+ const repoKey = `${payload.repository.owner.login}/${payload.repository.name}`;
64
+ if (!watchedRepos.has(repoKey)) {
65
+ return reply.status(200).send({ status: 'ignored', reason: 'not a watched repository' });
66
+ }
67
+ // Assignee filtering: only process issues assigned to this cluster
68
+ if (clusterGithubUsername) {
69
+ const assigneeLogins = (payload.issue.assignees ?? []).map(a => a.login);
70
+ if (assigneeLogins.length === 0) {
71
+ server.log.warn({ issue: payload.issue.number, repo: repoKey }, 'Webhook: skipping issue with no assignees');
72
+ return reply.status(200).send({
73
+ status: 'ignored',
74
+ reason: 'issue has no assignees',
75
+ });
76
+ }
77
+ if (!assigneeLogins.includes(clusterGithubUsername)) {
78
+ server.log.debug({ issue: payload.issue.number, repo: repoKey, assignees: assigneeLogins }, 'Webhook: skipping issue not assigned to this cluster');
79
+ return reply.status(200).send({
80
+ status: 'ignored',
81
+ reason: 'not assigned to this cluster',
82
+ });
83
+ }
84
+ }
85
+ // Parse and process the label event
86
+ const issueLabels = payload.issue.labels.map(l => l.name);
87
+ const event = monitorService.parseLabelEvent(payload.label.name, payload.repository.owner.login, payload.repository.name, payload.issue.number, issueLabels, 'webhook');
88
+ if (!event) {
89
+ // For completed:* labels without matching waiting-for:*, re-fetch from GitHub
90
+ if (payload.label.name.startsWith('completed:')) {
91
+ server.log.info({ label: payload.label.name, repo: repoKey, issue: payload.issue.number }, 'Webhook completed:* label has no matching waiting-for:*, attempting re-fetch');
92
+ monitorService.recordWebhookEvent();
93
+ const refetchResult = await monitorService.verifyAndProcessCompletedLabel(payload.repository.owner.login, payload.repository.name, payload.issue.number, payload.label.name);
94
+ return reply.status(200).send({
95
+ status: refetchResult ? 'processed' : 'ignored',
96
+ reason: refetchResult
97
+ ? 'resume detected after label re-fetch'
98
+ : 'no matching waiting-for:* after re-fetch',
99
+ });
100
+ }
101
+ return reply.status(200).send({ status: 'ignored', reason: 'not a trigger label' });
102
+ }
103
+ // Record webhook event for adaptive polling health tracking
104
+ monitorService.recordWebhookEvent();
105
+ // Process the event
106
+ const processed = await monitorService.processLabelEvent(event);
107
+ return reply.status(200).send({
108
+ status: processed ? 'processed' : 'duplicate',
109
+ event: {
110
+ type: event.type,
111
+ issue: event.issueNumber,
112
+ label: event.labelName,
113
+ },
114
+ });
115
+ });
116
+ }
117
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/routes/webhooks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAI1D;;;GAGG;AACH,SAAS,eAAe,CAAC,MAA0B,EAAE,OAAe,EAAE,eAAmC;IACvG,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,sDAAsD;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,cAAc,GAAG,SAAS,CAAC;IACjC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAExE,uDAAuD;IACvD,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAClF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AASD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAuB,EACvB,OAA4B;IAE5B,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,qBAAqB,EAAE,GAAG,OAAO,CAAC;IAEvF,uFAAuF;IACvF,MAAM,CAAC,oBAAoB,CACzB,kBAAkB,EAClB,EAAE,OAAO,EAAE,QAAQ,EAAE,EACrB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QACnB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAc,CAAC,CAAC;YACxC,6CAA6C;YAC7C,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAY,EAAE,SAAS,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CACF,CAAC;IAEF,wEAAwE;IACxE,oEAAoE;IACpE,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,EAAE,EACF,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAE,EAAE;QACrD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAwC,CAAC;QAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,MAA8B,CAAC;QAEpD,2BAA2B;QAC3B,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAuB,CAAC;QACrF,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,OAAO,EAAE,eAAe,CAAC,EAAE,CAAC;YAC9D,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YAC7C,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,+BAA+B;QAC/B,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,sCAAsC;QACtC,MAAM,OAAO,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC/E,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,0BAA0B,EAAE,CAAC,CAAC;QAC3F,CAAC;QAED,mEAAmE;QACnE,IAAI,qBAAqB,EAAE,CAAC;YAC1B,MAAM,cAAc,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACzE,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAChC,MAAM,CAAC,GAAG,CAAC,IAAI,CACb,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAC9C,2CAA2C,CAC5C,CAAC;gBACF,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBAC5B,MAAM,EAAE,SAAS;oBACjB,MAAM,EAAE,wBAAwB;iBACjC,CAAC,CAAC;YACL,CAAC;YACD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC;gBACpD,MAAM,CAAC,GAAG,CAAC,KAAK,CACd,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,EACzE,sDAAsD,CACvD,CAAC;gBACF,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBAC5B,MAAM,EAAE,SAAS;oBACjB,MAAM,EAAE,8BAA8B;iBACvC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,cAAc,CAAC,eAAe,CAC1C,OAAO,CAAC,KAAK,CAAC,IAAI,EAClB,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAC9B,OAAO,CAAC,UAAU,CAAC,IAAI,EACvB,OAAO,CAAC,KAAK,CAAC,MAAM,EACpB,WAAW,EACX,SAAS,CACV,CAAC;QAEF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,8EAA8E;YAC9E,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChD,MAAM,CAAC,GAAG,CAAC,IAAI,CACb,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,EACzE,8EAA8E,CAC/E,CAAC;gBACF,cAAc,CAAC,kBAAkB,EAAE,CAAC;gBACpC,MAAM,aAAa,GAAG,MAAM,cAAc,CAAC,8BAA8B,CACvE,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAC9B,OAAO,CAAC,UAAU,CAAC,IAAI,EACvB,OAAO,CAAC,KAAK,CAAC,MAAM,EACpB,OAAO,CAAC,KAAK,CAAC,IAAI,CACnB,CAAC;gBACF,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBAC5B,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;oBAC/C,MAAM,EAAE,aAAa;wBACnB,CAAC,CAAC,sCAAsC;wBACxC,CAAC,CAAC,0CAA0C;iBAC/C,CAAC,CAAC;YACL,CAAC;YAED,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,4DAA4D;QAC5D,cAAc,CAAC,kBAAkB,EAAE,CAAC;QAEpC,oBAAoB;QACpB,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAEhE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YAC5B,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW;YAC7C,KAAK,EAAE;gBACL,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,KAAK,EAAE,KAAK,CAAC,WAAW;gBACxB,KAAK,EAAE,KAAK,CAAC,SAAS;aACvB;SACF,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import { WorkflowService } from '../services/workflow-service.js';
3
+ /**
4
+ * Setup workflow routes
5
+ */
6
+ export declare function setupWorkflowRoutes(server: FastifyInstance, workflowService: WorkflowService): Promise<void>;
7
+ //# sourceMappingURL=workflows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/routes/workflows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAM7E,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGlE;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,eAAe,EACvB,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,IAAI,CAAC,CAiKf"}
@@ -0,0 +1,138 @@
1
+ import { CreateWorkflowRequestSchema, ListWorkflowsQuerySchema, WorkflowIdParamSchema, } from '../types/index.js';
2
+ import { requireRead, requireWrite } from '../auth/middleware.js';
3
+ /**
4
+ * Setup workflow routes
5
+ */
6
+ export async function setupWorkflowRoutes(server, workflowService) {
7
+ // POST /workflows - Create and start a workflow
8
+ server.post('/workflows', {
9
+ preHandler: [requireWrite('workflows')],
10
+ schema: {
11
+ description: 'Create and start a new workflow',
12
+ tags: ['Workflows'],
13
+ body: {
14
+ type: 'object',
15
+ properties: {
16
+ definitionId: { type: 'string' },
17
+ definition: { type: 'object' },
18
+ context: { type: 'object' },
19
+ metadata: {
20
+ type: 'object',
21
+ properties: {
22
+ name: { type: 'string' },
23
+ tags: { type: 'array', items: { type: 'string' } },
24
+ },
25
+ },
26
+ },
27
+ required: ['context'],
28
+ },
29
+ },
30
+ }, async (request, reply) => {
31
+ const body = CreateWorkflowRequestSchema.parse(request.body);
32
+ const workflow = await workflowService.create(body);
33
+ return reply
34
+ .status(201)
35
+ .header('location', `/workflows/${workflow.id}`)
36
+ .send(workflow);
37
+ });
38
+ // GET /workflows - List workflows
39
+ server.get('/workflows', {
40
+ preHandler: [requireRead('workflows')],
41
+ schema: {
42
+ description: 'List workflows',
43
+ tags: ['Workflows'],
44
+ querystring: {
45
+ type: 'object',
46
+ properties: {
47
+ status: {
48
+ type: 'string',
49
+ enum: ['created', 'running', 'paused', 'completed', 'cancelled', 'failed'],
50
+ },
51
+ page: { type: 'integer', minimum: 1, default: 1 },
52
+ pageSize: { type: 'integer', minimum: 1, maximum: 100, default: 20 },
53
+ },
54
+ },
55
+ },
56
+ }, async (request, reply) => {
57
+ const query = ListWorkflowsQuerySchema.parse(request.query);
58
+ const result = await workflowService.list(query);
59
+ return reply.send(result);
60
+ });
61
+ // GET /workflows/:id - Get workflow details
62
+ server.get('/workflows/:id', {
63
+ preHandler: [requireRead('workflows')],
64
+ schema: {
65
+ description: 'Get workflow details',
66
+ tags: ['Workflows'],
67
+ params: {
68
+ type: 'object',
69
+ properties: {
70
+ id: { type: 'string', format: 'uuid' },
71
+ },
72
+ required: ['id'],
73
+ },
74
+ },
75
+ }, async (request, reply) => {
76
+ const params = WorkflowIdParamSchema.parse(request.params);
77
+ const workflow = await workflowService.get(params.id);
78
+ return reply.send(workflow);
79
+ });
80
+ // POST /workflows/:id/pause - Pause workflow
81
+ server.post('/workflows/:id/pause', {
82
+ preHandler: [requireWrite('workflows')],
83
+ schema: {
84
+ description: 'Pause a running workflow',
85
+ tags: ['Workflows'],
86
+ params: {
87
+ type: 'object',
88
+ properties: {
89
+ id: { type: 'string', format: 'uuid' },
90
+ },
91
+ required: ['id'],
92
+ },
93
+ },
94
+ }, async (request, reply) => {
95
+ const params = WorkflowIdParamSchema.parse(request.params);
96
+ const workflow = await workflowService.pause(params.id);
97
+ return reply.send(workflow);
98
+ });
99
+ // POST /workflows/:id/resume - Resume workflow
100
+ server.post('/workflows/:id/resume', {
101
+ preHandler: [requireWrite('workflows')],
102
+ schema: {
103
+ description: 'Resume a paused workflow',
104
+ tags: ['Workflows'],
105
+ params: {
106
+ type: 'object',
107
+ properties: {
108
+ id: { type: 'string', format: 'uuid' },
109
+ },
110
+ required: ['id'],
111
+ },
112
+ },
113
+ }, async (request, reply) => {
114
+ const params = WorkflowIdParamSchema.parse(request.params);
115
+ const workflow = await workflowService.resume(params.id);
116
+ return reply.send(workflow);
117
+ });
118
+ // DELETE /workflows/:id - Cancel workflow
119
+ server.delete('/workflows/:id', {
120
+ preHandler: [requireWrite('workflows')],
121
+ schema: {
122
+ description: 'Cancel a workflow',
123
+ tags: ['Workflows'],
124
+ params: {
125
+ type: 'object',
126
+ properties: {
127
+ id: { type: 'string', format: 'uuid' },
128
+ },
129
+ required: ['id'],
130
+ },
131
+ },
132
+ }, async (request, reply) => {
133
+ const params = WorkflowIdParamSchema.parse(request.params);
134
+ await workflowService.cancel(params.id);
135
+ return reply.status(204).send();
136
+ });
137
+ }
138
+ //# sourceMappingURL=workflows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflows.js","sourceRoot":"","sources":["../../src/routes/workflows.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { type FastifyInstance, type FastifyServerOptions } from 'fastify';
2
+ import { type OrchestratorConfig } from './config/index.js';
3
+ /**
4
+ * Server creation options
5
+ */
6
+ export interface CreateServerOptions {
7
+ /** Configuration (loads from file/env if not provided) */
8
+ config?: OrchestratorConfig;
9
+ /** Additional Fastify options */
10
+ fastifyOptions?: FastifyServerOptions;
11
+ /** Skip route registration (for testing individual routes) */
12
+ skipRoutes?: boolean;
13
+ }
14
+ /**
15
+ * Create and configure the Fastify server
16
+ */
17
+ export declare function createServer(options?: CreateServerOptions): Promise<FastifyInstance>;
18
+ /**
19
+ * Start the server and begin listening
20
+ */
21
+ export declare function startServer(server: FastifyInstance): Promise<string>;
22
+ /**
23
+ * Create a server for testing
24
+ */
25
+ export declare function createTestServer(configOverrides?: Partial<OrchestratorConfig>): Promise<FastifyInstance>;
26
+ /**
27
+ * Create a fully configured server for production
28
+ */
29
+ export declare function createProductionServer(): Promise<FastifyInstance>;
30
+ declare module 'fastify' {
31
+ interface FastifyInstance {
32
+ config: OrchestratorConfig;
33
+ }
34
+ }
35
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAKnF,OAAO,EAAE,KAAK,kBAAkB,EAAgC,MAAM,mBAAmB,CAAC;AAwB1F;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,0DAA0D;IAC1D,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,iCAAiC;IACjC,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,8DAA8D;IAC9D,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,eAAe,CAAC,CAsR9F;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAS1E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,eAAe,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAChD,OAAO,CAAC,eAAe,CAAC,CAG1B;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,eAAe,CAAC,CAGvE;AAGD,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,eAAe;QACvB,MAAM,EAAE,kBAAkB,CAAC;KAC5B;CACF"}