managarten/services/mana-api-gateway/CLAUDE.md
Till-JS fc0ed636fc feat(api-gateway): add Swagger, admin endpoints, and scheduler
- Add Swagger/OpenAPI documentation at /docs endpoint
- Add admin module for system-wide API key management
- Add scheduler for monthly credit reset and usage cleanup
- Add Docker Compose entry for Mac Mini deployment
- Document all endpoints with descriptions and examples
2026-01-29 18:03:16 +01:00

287 lines
9.1 KiB
Markdown

# Mana API Gateway
Custom NestJS API Gateway for monetizing ManaCore services (mana-search, mana-stt, mana-tts).
## Overview
- **Port**: 3030
- **Technology**: NestJS 10 + Drizzle ORM + Redis
- **Purpose**: API Key Management, Usage Tracking, Rate Limiting, Credit-based Billing
## Architecture
```
┌─────────────────────────┐
│ API Gateway │
│ (Port 3030) │
│ │
Clients ───────────>│ • API Key Validation │
(X-API-Key Header) │ • Rate Limiting │
│ • Usage Tracking │
│ • Credit Deduction │
└───────────┬─────────────┘
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ mana-search │ │ mana-stt │ │ mana-tts │
│ (Port 3021) │ │ (Port 3020) │ │ (Port 3022) │
└───────────────┘ └───────────────┘ └───────────────┘
```
## Quick Start
### Development
```bash
# Install dependencies
pnpm install
# Push database schema
pnpm db:push
# Start in development mode
pnpm dev
```
### Production
```bash
# Build
pnpm build
# Start
pnpm start
```
## API Endpoints
### Public API (with API Key)
| Method | Endpoint | Description | Credits |
|--------|----------|-------------|---------|
| POST | `/v1/search` | Web search | 1 |
| POST | `/v1/extract` | Content extraction | 1 |
| POST | `/v1/extract/bulk` | Bulk extraction | 1 per URL |
| GET | `/v1/search/engines` | Available search engines | 0 |
| POST | `/v1/stt/transcribe` | Audio → Text | 10/min |
| GET | `/v1/stt/models` | Available STT models | 0 |
| GET | `/v1/stt/languages` | Supported languages | 0 |
| POST | `/v1/tts/synthesize` | Text → Audio | 1/1000 chars |
| GET | `/v1/tts/voices` | Available voices | 0 |
| GET | `/v1/tts/languages` | Supported languages | 0 |
### Management API (with JWT)
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api-keys` | Create new API key |
| GET | `/api-keys` | List all API keys |
| GET | `/api-keys/:id` | Get API key details |
| PATCH | `/api-keys/:id` | Update API key |
| DELETE | `/api-keys/:id` | Delete API key |
| POST | `/api-keys/:id/regenerate` | Regenerate API key |
| GET | `/api-keys/:id/usage` | Get usage statistics |
| GET | `/api-keys/:id/usage/summary` | Get usage summary |
### Admin API (with JWT + Admin Role)
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/admin/api-keys` | List all API keys (paginated) |
| GET | `/admin/api-keys/:id` | Get any API key details |
| PATCH | `/admin/api-keys/:id` | Update any key (tier, credits, limits) |
| DELETE | `/admin/api-keys/:id` | Delete any API key |
| GET | `/admin/usage/summary` | System-wide usage stats |
| GET | `/admin/usage/top-users` | Top users by usage |
### System
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/health` | Health check |
| GET | `/metrics` | Prometheus metrics |
| GET | `/docs` | Swagger/OpenAPI documentation |
## Pricing Tiers
| Tier | Rate Limit | Monthly Credits | Endpoints | Price |
|------|------------|-----------------|-----------|-------|
| Free | 10 req/min | 100 | Search only | Free |
| Pro | 100 req/min | 5,000 | All | €19/month |
| Enterprise | 1,000 req/min | 50,000 | All | €99/month |
## Credit Costs
| Operation | Cost |
|-----------|------|
| Search | 1 credit |
| Extract | 1 credit |
| STT | 10 credits/minute |
| TTS | 1 credit/1000 chars |
## Usage Examples
### Create an API Key
```bash
# First, get a JWT token from mana-core-auth
TOKEN=$(curl -s -X POST http://localhost:3001/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "password"}' | jq -r '.accessToken')
# Create an API key
curl -X POST http://localhost:3030/api-keys \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "My API Key", "tier": "free"}'
```
### Use the API
```bash
# Search
curl -X POST http://localhost:3030/v1/search \
-H "X-API-Key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"query": "quantum computing"}'
# Extract content
curl -X POST http://localhost:3030/v1/extract \
-H "X-API-Key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/article"}'
# Text-to-Speech
curl -X POST http://localhost:3030/v1/tts/synthesize \
-H "X-API-Key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"text": "Hello, world!", "voice": "en-US-1"}' \
--output audio.mp3
# Speech-to-Text
curl -X POST http://localhost:3030/v1/stt/transcribe \
-H "X-API-Key: sk_live_xxx" \
-F "file=@audio.wav"
```
### Check Usage
```bash
curl http://localhost:3030/api-keys/{id}/usage \
-H "Authorization: Bearer $TOKEN"
```
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `PORT` | 3030 | API port |
| `DATABASE_URL` | - | PostgreSQL connection URL |
| `REDIS_HOST` | localhost | Redis host |
| `REDIS_PORT` | 6379 | Redis port |
| `SEARCH_SERVICE_URL` | http://localhost:3021 | mana-search URL |
| `STT_SERVICE_URL` | http://localhost:3020 | mana-stt URL |
| `TTS_SERVICE_URL` | http://localhost:3022 | mana-tts URL |
| `MANA_CORE_AUTH_URL` | http://localhost:3001 | Auth service URL |
| `ADMIN_USER_IDS` | - | Comma-separated admin user IDs |
## Development Commands
```bash
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Build for production
pnpm build
# Start production server
pnpm start
# Type checking
pnpm type-check
# Linting
pnpm lint
# Database commands
pnpm db:push # Push schema to database
pnpm db:generate # Generate migrations
pnpm db:migrate # Run migrations
pnpm db:studio # Open Drizzle Studio
```
## Database Schema
The gateway uses its own schema (`api_gateway`) in the shared ManaCore database:
- `api_gateway.api_keys` - API key storage and configuration
- `api_gateway.api_usage` - Detailed usage logs
- `api_gateway.api_usage_daily` - Aggregated daily usage for billing
## Rate Limiting
Rate limiting uses Redis with a sliding window algorithm:
- Each API key has a configurable rate limit (requests per minute)
- Rate limit headers are included in responses:
- `X-RateLimit-Limit` - Maximum requests per minute
- `X-RateLimit-Remaining` - Remaining requests
- `X-RateLimit-Reset` - Unix timestamp when limit resets
## Authentication
Two types of authentication:
1. **X-API-Key header** - For public API endpoints (`/v1/*`)
2. **Bearer JWT token** - For management endpoints (`/api-keys/*`)
The JWT token is validated against mana-core-auth service.
## Project Structure
```
services/mana-api-gateway/
├── src/
│ ├── main.ts # Application entry point
│ ├── app.module.ts # Root module
│ ├── config/
│ │ ├── configuration.ts # App configuration
│ │ └── pricing.ts # Pricing tiers and credit costs
│ ├── db/
│ │ ├── schema/ # Drizzle schemas
│ │ ├── database.module.ts # Database provider
│ │ ├── connection.ts # DB connection
│ │ └── migrate.ts # Migration script
│ ├── api-keys/ # API key management
│ ├── usage/ # Usage tracking
│ ├── proxy/ # Proxy services to backends
│ ├── guards/ # Auth, rate limit, credits guards
│ ├── common/ # Decorators, filters, interceptors
│ ├── credits/ # Credits service (mana-core-auth client)
│ ├── metrics/ # Prometheus metrics
│ └── health/ # Health check endpoint
├── drizzle.config.ts # Drizzle Kit configuration
├── package.json
├── tsconfig.json
└── Dockerfile
```
## Troubleshooting
### API Key not working
1. Check the key is valid: `curl -H "X-API-Key: $KEY" http://localhost:3030/health`
2. Check the key is active in the database
3. Check the key hasn't expired
4. Check the endpoint is allowed for the key's tier
### Rate limit exceeded
Wait for the `X-RateLimit-Reset` timestamp, or upgrade to a higher tier.
### Credits exhausted
Check usage with the management API, or wait for monthly reset.