Files
stack/apps/api/src/stitcher/stitcher.controller.ts
Jason Woltje 41d56dadf0
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fix(#199): implement rate limiting on webhook endpoints
Implements comprehensive rate limiting on all webhook and coordinator endpoints
to prevent DoS attacks. Follows TDD protocol with 14 passing tests.

Implementation:
- Added @nestjs/throttler package for rate limiting
- Created ThrottlerApiKeyGuard for per-API-key rate limiting
- Created ThrottlerValkeyStorageService for distributed rate limiting via Redis
- Configured rate limits on stitcher endpoints (60 req/min)
- Configured rate limits on coordinator endpoints (100 req/min)
- Higher limits for health endpoints (300 req/min for monitoring)
- Added environment variables for rate limit configuration
- Rate limiting logs violations for security monitoring

Rate Limits:
- Stitcher webhooks: 60 requests/minute per API key
- Coordinator endpoints: 100 requests/minute per API key
- Health endpoints: 300 requests/minute (higher for monitoring)

Storage:
- Uses Valkey (Redis) for distributed rate limiting across API instances
- Falls back to in-memory storage if Redis unavailable

Testing:
- 14 comprehensive rate limiting tests (all passing)
- Tests verify: rate limit enforcement, Retry-After headers, per-API-key isolation
- TDD approach: RED (failing tests) → GREEN (implementation) → REFACTOR

Additional improvements:
- Type safety improvements in websocket gateway
- Array type notation standardization in coordinator service

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 13:07:16 -06:00

52 lines
1.7 KiB
TypeScript

import { Controller, Post, Body, UseGuards } from "@nestjs/common";
import { Throttle } from "@nestjs/throttler";
import { StitcherService } from "./stitcher.service";
import { WebhookPayloadDto, DispatchJobDto } from "./dto";
import type { JobDispatchResult, JobDispatchContext } from "./interfaces";
import { ApiKeyGuard } from "../common/guards";
/**
* StitcherController - Webhook and job dispatch endpoints
*
* SECURITY:
* - All endpoints require API key authentication via X-API-Key header
* - Rate limiting: 60 requests per minute per IP/API key
*
* Handles incoming webhooks from @mosaic bot and provides
* endpoints for manual job dispatch
*/
@Controller("stitcher")
@UseGuards(ApiKeyGuard)
@Throttle({ default: { ttl: 60000, limit: 60 } }) // 60 requests per minute
export class StitcherController {
constructor(private readonly stitcherService: StitcherService) {}
/**
* Webhook endpoint for @mosaic bot
*
* Rate limit: 60 requests per minute per IP/API key
*/
@Post("webhook")
@Throttle({ default: { ttl: 60000, limit: 60 } })
async webhook(@Body() payload: WebhookPayloadDto): Promise<JobDispatchResult> {
return this.stitcherService.handleWebhook(payload);
}
/**
* Manual job dispatch endpoint
*
* Rate limit: 60 requests per minute per IP/API key
*/
@Post("dispatch")
@Throttle({ default: { ttl: 60000, limit: 60 } })
async dispatch(@Body() dto: DispatchJobDto): Promise<JobDispatchResult> {
const context: JobDispatchContext = {
workspaceId: dto.workspaceId,
type: dto.type,
...(dto.context !== undefined && { metadata: dto.context }),
};
return this.stitcherService.dispatchJob(context);
}
}