@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.
- package/LICENSE +191 -0
- package/dist/auth/api-key.d.ts +63 -0
- package/dist/auth/api-key.d.ts.map +1 -0
- package/dist/auth/api-key.js +102 -0
- package/dist/auth/api-key.js.map +1 -0
- package/dist/auth/github-oauth.d.ts +29 -0
- package/dist/auth/github-oauth.d.ts.map +1 -0
- package/dist/auth/github-oauth.js +136 -0
- package/dist/auth/github-oauth.js.map +1 -0
- package/dist/auth/index.d.ts +5 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +9 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/jwt.d.ts +34 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/jwt.js +74 -0
- package/dist/auth/jwt.js.map +1 -0
- package/dist/auth/middleware.d.ts +43 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +101 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +5 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +21 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +295 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +733 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +174 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +30 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +173 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/index.d.ts +4 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +4 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +32 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +92 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/middleware/request-logger.d.ts +31 -0
- package/dist/middleware/request-logger.d.ts.map +1 -0
- package/dist/middleware/request-logger.js +89 -0
- package/dist/middleware/request-logger.js.map +1 -0
- package/dist/routes/agents.d.ts +7 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +78 -0
- package/dist/routes/agents.js.map +1 -0
- package/dist/routes/dispatch.d.ts +8 -0
- package/dist/routes/dispatch.d.ts.map +1 -0
- package/dist/routes/dispatch.js +46 -0
- package/dist/routes/dispatch.js.map +1 -0
- package/dist/routes/events.d.ts +14 -0
- package/dist/routes/events.d.ts.map +1 -0
- package/dist/routes/events.js +240 -0
- package/dist/routes/events.js.map +1 -0
- package/dist/routes/health.d.ts +14 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +132 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/index.d.ts +36 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +34 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/integrations.d.ts +34 -0
- package/dist/routes/integrations.d.ts.map +1 -0
- package/dist/routes/integrations.js +81 -0
- package/dist/routes/integrations.js.map +1 -0
- package/dist/routes/metrics.d.ts +31 -0
- package/dist/routes/metrics.d.ts.map +1 -0
- package/dist/routes/metrics.js +157 -0
- package/dist/routes/metrics.js.map +1 -0
- package/dist/routes/pr-webhooks.d.ts +15 -0
- package/dist/routes/pr-webhooks.d.ts.map +1 -0
- package/dist/routes/pr-webhooks.js +114 -0
- package/dist/routes/pr-webhooks.js.map +1 -0
- package/dist/routes/queue.d.ts +7 -0
- package/dist/routes/queue.d.ts.map +1 -0
- package/dist/routes/queue.js +94 -0
- package/dist/routes/queue.js.map +1 -0
- package/dist/routes/webhooks.d.ts +15 -0
- package/dist/routes/webhooks.d.ts.map +1 -0
- package/dist/routes/webhooks.js +117 -0
- package/dist/routes/webhooks.js.map +1 -0
- package/dist/routes/workflows.d.ts +7 -0
- package/dist/routes/workflows.d.ts.map +1 -0
- package/dist/routes/workflows.js +138 -0
- package/dist/routes/workflows.js.map +1 -0
- package/dist/server.d.ts +35 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +264 -0
- package/dist/server.js.map +1 -0
- package/dist/services/agent-registry.d.ts +89 -0
- package/dist/services/agent-registry.d.ts.map +1 -0
- package/dist/services/agent-registry.js +173 -0
- package/dist/services/agent-registry.js.map +1 -0
- package/dist/services/epic-completion-monitor-service.d.ts +69 -0
- package/dist/services/epic-completion-monitor-service.d.ts.map +1 -0
- package/dist/services/epic-completion-monitor-service.js +200 -0
- package/dist/services/epic-completion-monitor-service.js.map +1 -0
- package/dist/services/identity.d.ts +41 -0
- package/dist/services/identity.d.ts.map +1 -0
- package/dist/services/identity.js +91 -0
- package/dist/services/identity.js.map +1 -0
- package/dist/services/index.d.ts +13 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +13 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/label-monitor-service.d.ts +95 -0
- package/dist/services/label-monitor-service.d.ts.map +1 -0
- package/dist/services/label-monitor-service.js +414 -0
- package/dist/services/label-monitor-service.js.map +1 -0
- package/dist/services/label-sync-service.d.ts +76 -0
- package/dist/services/label-sync-service.d.ts.map +1 -0
- package/dist/services/label-sync-service.js +108 -0
- package/dist/services/label-sync-service.js.map +1 -0
- package/dist/services/phase-tracker-service.d.ts +32 -0
- package/dist/services/phase-tracker-service.d.ts.map +1 -0
- package/dist/services/phase-tracker-service.js +82 -0
- package/dist/services/phase-tracker-service.js.map +1 -0
- package/dist/services/pr-feedback-monitor-service.d.ts +86 -0
- package/dist/services/pr-feedback-monitor-service.d.ts.map +1 -0
- package/dist/services/pr-feedback-monitor-service.js +423 -0
- package/dist/services/pr-feedback-monitor-service.js.map +1 -0
- package/dist/services/queue-service.d.ts +62 -0
- package/dist/services/queue-service.d.ts.map +1 -0
- package/dist/services/queue-service.js +147 -0
- package/dist/services/queue-service.js.map +1 -0
- package/dist/services/redis-queue-adapter.d.ts +35 -0
- package/dist/services/redis-queue-adapter.d.ts.map +1 -0
- package/dist/services/redis-queue-adapter.js +218 -0
- package/dist/services/redis-queue-adapter.js.map +1 -0
- package/dist/services/smee-receiver.d.ts +87 -0
- package/dist/services/smee-receiver.d.ts.map +1 -0
- package/dist/services/smee-receiver.js +225 -0
- package/dist/services/smee-receiver.js.map +1 -0
- package/dist/services/webhook-setup-service.d.ts +253 -0
- package/dist/services/webhook-setup-service.d.ts.map +1 -0
- package/dist/services/webhook-setup-service.js +369 -0
- package/dist/services/webhook-setup-service.js.map +1 -0
- package/dist/services/worker-dispatcher.d.ts +57 -0
- package/dist/services/worker-dispatcher.d.ts.map +1 -0
- package/dist/services/worker-dispatcher.js +211 -0
- package/dist/services/worker-dispatcher.js.map +1 -0
- package/dist/services/workflow-service.d.ts +65 -0
- package/dist/services/workflow-service.d.ts.map +1 -0
- package/dist/services/workflow-service.js +164 -0
- package/dist/services/workflow-service.js.map +1 -0
- package/dist/sse/events.d.ts +50 -0
- package/dist/sse/events.d.ts.map +1 -0
- package/dist/sse/events.js +152 -0
- package/dist/sse/events.js.map +1 -0
- package/dist/sse/index.d.ts +4 -0
- package/dist/sse/index.d.ts.map +1 -0
- package/dist/sse/index.js +7 -0
- package/dist/sse/index.js.map +1 -0
- package/dist/sse/stream.d.ts +109 -0
- package/dist/sse/stream.d.ts.map +1 -0
- package/dist/sse/stream.js +239 -0
- package/dist/sse/stream.js.map +1 -0
- package/dist/sse/subscriptions.d.ts +91 -0
- package/dist/sse/subscriptions.d.ts.map +1 -0
- package/dist/sse/subscriptions.js +299 -0
- package/dist/sse/subscriptions.js.map +1 -0
- package/dist/types/api.d.ts +651 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +169 -0
- package/dist/types/api.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +27 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/monitor.d.ts +243 -0
- package/dist/types/monitor.d.ts.map +1 -0
- package/dist/types/monitor.js +2 -0
- package/dist/types/monitor.js.map +1 -0
- package/dist/types/problem-details.d.ts +63 -0
- package/dist/types/problem-details.d.ts.map +1 -0
- package/dist/types/problem-details.js +37 -0
- package/dist/types/problem-details.js.map +1 -0
- package/dist/types/sse.d.ts +224 -0
- package/dist/types/sse.d.ts.map +1 -0
- package/dist/types/sse.js +103 -0
- package/dist/types/sse.js.map +1 -0
- package/dist/types/webhook.d.ts +59 -0
- package/dist/types/webhook.d.ts.map +1 -0
- package/dist/types/webhook.js +2 -0
- package/dist/types/webhook.js.map +1 -0
- package/dist/utils/correlation.d.ts +30 -0
- package/dist/utils/correlation.d.ts.map +1 -0
- package/dist/utils/correlation.js +34 -0
- package/dist/utils/correlation.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/shutdown.d.ts +28 -0
- package/dist/utils/shutdown.d.ts.map +1 -0
- package/dist/utils/shutdown.js +86 -0
- package/dist/utils/shutdown.js.map +1 -0
- package/dist/worker/claude-cli-worker.d.ts +61 -0
- package/dist/worker/claude-cli-worker.d.ts.map +1 -0
- package/dist/worker/claude-cli-worker.js +330 -0
- package/dist/worker/claude-cli-worker.js.map +1 -0
- package/dist/worker/cli-spawner.d.ts +42 -0
- package/dist/worker/cli-spawner.d.ts.map +1 -0
- package/dist/worker/cli-spawner.js +183 -0
- package/dist/worker/cli-spawner.js.map +1 -0
- package/dist/worker/config.d.ts +76 -0
- package/dist/worker/config.d.ts.map +1 -0
- package/dist/worker/config.js +39 -0
- package/dist/worker/config.js.map +1 -0
- package/dist/worker/epic-post-tasks.d.ts +73 -0
- package/dist/worker/epic-post-tasks.d.ts.map +1 -0
- package/dist/worker/epic-post-tasks.js +266 -0
- package/dist/worker/epic-post-tasks.js.map +1 -0
- package/dist/worker/gate-checker.d.ts +22 -0
- package/dist/worker/gate-checker.d.ts.map +1 -0
- package/dist/worker/gate-checker.js +41 -0
- package/dist/worker/gate-checker.js.map +1 -0
- package/dist/worker/index.d.ts +13 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +19 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/label-manager.d.ts +89 -0
- package/dist/worker/label-manager.d.ts.map +1 -0
- package/dist/worker/label-manager.js +200 -0
- package/dist/worker/label-manager.js.map +1 -0
- package/dist/worker/output-capture.d.ts +58 -0
- package/dist/worker/output-capture.d.ts.map +1 -0
- package/dist/worker/output-capture.js +153 -0
- package/dist/worker/output-capture.js.map +1 -0
- package/dist/worker/phase-loop.d.ts +64 -0
- package/dist/worker/phase-loop.d.ts.map +1 -0
- package/dist/worker/phase-loop.js +185 -0
- package/dist/worker/phase-loop.js.map +1 -0
- package/dist/worker/phase-resolver.d.ts +62 -0
- package/dist/worker/phase-resolver.d.ts.map +1 -0
- package/dist/worker/phase-resolver.js +144 -0
- package/dist/worker/phase-resolver.js.map +1 -0
- package/dist/worker/pr-feedback-handler.d.ts +105 -0
- package/dist/worker/pr-feedback-handler.d.ts.map +1 -0
- package/dist/worker/pr-feedback-handler.js +391 -0
- package/dist/worker/pr-feedback-handler.js.map +1 -0
- package/dist/worker/pr-linker.d.ts +69 -0
- package/dist/worker/pr-linker.d.ts.map +1 -0
- package/dist/worker/pr-linker.js +108 -0
- package/dist/worker/pr-linker.js.map +1 -0
- package/dist/worker/pr-manager.d.ts +61 -0
- package/dist/worker/pr-manager.d.ts.map +1 -0
- package/dist/worker/pr-manager.js +140 -0
- package/dist/worker/pr-manager.js.map +1 -0
- package/dist/worker/repo-checkout.d.ts +63 -0
- package/dist/worker/repo-checkout.d.ts.map +1 -0
- package/dist/worker/repo-checkout.js +160 -0
- package/dist/worker/repo-checkout.js.map +1 -0
- package/dist/worker/stage-comment-manager.d.ts +34 -0
- package/dist/worker/stage-comment-manager.d.ts.map +1 -0
- package/dist/worker/stage-comment-manager.js +114 -0
- package/dist/worker/stage-comment-manager.js.map +1 -0
- package/dist/worker/types.d.ts +192 -0
- package/dist/worker/types.d.ts.map +1 -0
- package/dist/worker/types.js +53 -0
- package/dist/worker/types.js.map +1 -0
- 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":"AACA,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,6BAA6B,EAC7B,2BAA2B,GAC5B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAuB,EACvB,YAA0B;IAE1B,kCAAkC;IAClC,MAAM,CAAC,GAAG,CACR,QAAQ,EACR;QACE,UAAU,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,EAAE;YACN,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,QAAQ,EAAE;wBACR,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,CAAC,cAAc,EAAE,eAAe,EAAE,gBAAgB,CAAC;qBAC1D;oBACD,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;iBAC/B;aACF;SACO;KACX,EACD,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAE,EAAE;QACrD,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACjD,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,CACF,CAAC;IAEF,sCAAsC;IACtC,MAAM,CAAC,IAAI,CACT,QAAQ,EACR;QACE,UAAU,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACnC,0EAA0E;KAC3E,EACD,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAE,EAAE;QACrD,MAAM,IAAI,GAAG,2BAA2B,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAErD,uCAAuC;QACvC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,yBAAyB,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACtF,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAElC,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CACF,CAAC;IAEF,yCAAyC;IACzC,MAAM,CAAC,GAAG,CACR,YAAY,EACZ;QACE,UAAU,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,EAAE;YACN,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE;iBACvC;gBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;aACjB;SACF;KACF,EACD,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAE,EAAE;QACrD,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3D,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC,CACF,CAAC;IAEF,qDAAqD;IACrD,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB;QACE,UAAU,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,EAAE;YACN,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE;iBACvC;gBACD,QAAQ,EAAE,CAAC,IAAI,CAAC;aACjB;YACD,wEAAwE;SACzE;KACF,EACD,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAE,EAAE;QACrD,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,6BAA6B,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE/D,gFAAgF;QAChF,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAEvD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CACzC,MAAM,CAAC,EAAE,EACT,IAAI,EACJ,OAAO,CAAC,IAAI,CAAC,MAAM,CACpB,CAAC;QAEF,oEAAoE;QACpE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,yBAAyB,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;QAClG,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAElC,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC,CACF,CAAC;IAEF,0CAA0C;IAC1C,MAAM,CAAC,GAAG,CACR,cAAc,EACd;QACE,UAAU,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;KACnC,EACD,KAAK,EAAE,QAAwB,EAAE,KAAmB,EAAE,EAAE;QACtD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,aAAa,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -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":"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"}
|
|
@@ -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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"}
|
package/dist/server.d.ts
ADDED
|
@@ -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"}
|