API Gateway / BFF (ST-105)
Overview
Implements the Backend for Frontend (BFF) pattern using Next.js Route Handlers. Provides a unified API layer for the web application, handling authentication, authorization, validation, and data aggregation.
Architecture
Following ADR-0001, the BFF is implemented as:
- Next.js Route Handlers on Vercel (MVP)
- REST-first API design
- Type-safe with TypeScript
- Validated with Zod schemas
API Structure
All API routes are under /api/*:
/api/
├── auth/ # Authentication endpoints
├── ingestion/ # CI ingestion endpoint
├── repos/ # Repository management
├── dsr/ # Data subject requests
├── audit-logs/ # Audit log queries
├── health/ # Health checks
├── metrics/ # Prometheus metrics
└── version/ # API version
Endpoints
Authentication
POST /api/auth/register- User registrationPOST /api/auth/login- User loginPOST /api/auth/logout- User logoutGET /api/auth/me- Current user infoGET /api/auth/oauth/github- GitHub OAuth initiationGET /api/auth/callback/github- GitHub OAuth callback
Ingestion
POST /api/ingestion- Submit test reports (HMAC authenticated)
Repositories
GET /api/repos/[repoId]/roles- List users with rolesPOST /api/repos/[repoId]/roles- Assign roleDELETE /api/repos/[repoId]/roles- Remove roleGET /api/repos/[repoId]/roles/audit- Role audit logs
Data Subject Requests
GET /api/dsr- List DSR requestsPOST /api/dsr/export- Request data exportGET /api/dsr/export/[requestId]- Download exportPOST /api/dsr/deletion- Request account deletion
Health & Monitoring
GET /api/health/db- Database healthGET /api/health/mq- Message queue healthGET /api/health/storage- Object storage healthGET /api/status- Overall system statusGET /api/metrics- Prometheus metricsGET /api/version- API version
Request Flow
- Middleware - Security headers, request ID generation
- Authentication - Session validation (if required)
- Authorization - Permission checks (RBAC)
- Validation - Request body validation (Zod)
- Rate Limiting - Rate limit enforcement
- Business Logic - Service layer processing
- Response - JSON response with appropriate status
Error Handling
Standard Error Response
{
"error": "Error message",
"details": [] // Optional, development only
}
Status Codes
200- Success201- Created400- Bad Request (validation error)401- Unauthorized403- Forbidden404- Not Found409- Conflict413- Payload Too Large429- Too Many Requests500- Internal Server Error
Validation
All endpoints use Zod schemas for validation:
import { validateRequest } from '@/lib/validation';
import { registerSchema } from '@/lib/schemas/auth';
const result = await validateRequest(request, registerSchema);
if (!result.success) {
return NextResponse.json({ error: result.error.error }, { status: 400 });
}
Authentication
Session-Based
- JWT tokens in HTTP-only cookies
- Automatic session validation
- Middleware extracts user from session
HMAC (CI Systems)
Authorization: Bearer <repo_id>X-FR-Sig: <hmac_signature>- Used for ingestion endpoint
Authorization
RBAC enforced via middleware:
import { requireAuthz } from '@/lib/server/authz';
await requireAuthz(request, 'admin', 'role', repoId);
Rate Limiting
Applied per endpoint:
auth:register- 5 requests / 15 minutesauth:login- 10 requests / 15 minutesingestion:submit- 500 requests / hour
Response Headers
All responses include:
X-Request-ID- Request identifierX-RateLimit-Limit- Rate limit maximumX-RateLimit-Remaining- Remaining requestsX-RateLimit-Reset- Reset timestamp- Security headers (see ST-204)
Future Enhancements
- GraphQL endpoint (optional)
- API versioning (
/api/v1/) - Request/response logging
- OpenAPI documentation generation
- API key authentication
- Webhook endpoints
Related Documentation
- Authentication - Auth endpoints
- Input Validation - Validation
- Rate Limiting - Rate limits
- RBAC - Authorization