docs: update
This commit is contained in:
parent
298898f79d
commit
c2b161d71c
103
CLAUDE.md
103
CLAUDE.md
|
|
@ -56,6 +56,8 @@ banatie-service/
|
|||
│ ├── landing/ # Next.js landing page
|
||||
│ ├── studio/ # Next.js SaaS platform
|
||||
│ └── admin/ # Next.js admin dashboard
|
||||
├── packages/
|
||||
│ └── database/ # Shared database package (Drizzle ORM)
|
||||
├── data/ # Docker volume data (postgres, minio)
|
||||
├── docker-compose.yml # Infrastructure services
|
||||
├── pnpm-workspace.yaml # Workspace configuration
|
||||
|
|
@ -66,15 +68,23 @@ banatie-service/
|
|||
|
||||
- **Express App**: Configured in `src/app.ts` with middleware, CORS, and route mounting
|
||||
- **Server Entry**: `src/server.ts` starts the HTTP server
|
||||
- **Image Generation**: `src/services/ImageGenService.ts` handles Gemini AI integration
|
||||
- **Storage**: `src/services/MinioStorageService.ts` handles file uploads to MinIO
|
||||
- **Route Handling**: `src/routes/generate.ts` contains the main API endpoint logic
|
||||
- **Database Client**: `src/db.ts` - Drizzle ORM connection to PostgreSQL
|
||||
- **Authentication**: `src/services/ApiKeyService.ts` - API key management and validation
|
||||
- **Image Generation**: `src/services/ImageGenService.ts` - Gemini AI integration
|
||||
- **Storage**: `src/services/MinioStorageService.ts` - File uploads to MinIO
|
||||
- **Route Handling**:
|
||||
- `src/routes/bootstrap.ts` - Bootstrap initial master key (one-time)
|
||||
- `src/routes/admin/keys.ts` - API key management (master key required)
|
||||
- `src/routes/generate.ts` - Image generation endpoint (API key required)
|
||||
|
||||
### Middleware Stack (API Service)
|
||||
|
||||
- `src/middleware/upload.ts` - Multer configuration for file uploads (max 3 files, 5MB each)
|
||||
- `src/middleware/validation.ts` - Express-validator for request validation
|
||||
- `src/middleware/errorHandler.ts` - Centralized error handling and 404 responses
|
||||
- `src/middleware/auth/validateApiKey.ts` - API key authentication
|
||||
- `src/middleware/auth/requireMasterKey.ts` - Master key authorization
|
||||
- `src/middleware/auth/rateLimiter.ts` - Rate limiting per API key (100 req/hour)
|
||||
|
||||
### TypeScript Configuration (API Service)
|
||||
|
||||
|
|
@ -89,13 +99,32 @@ banatie-service/
|
|||
### Storage & Data
|
||||
|
||||
- **MinIO**: Object storage for generated images and uploads (port 9000)
|
||||
- **PostgreSQL**: Database for user data, metadata (port 5434)
|
||||
- **PostgreSQL**: Database for API keys, user data, and metadata (port 5434)
|
||||
- Database name: `banatie_db`
|
||||
- User: `banatie_user`
|
||||
- Tables: `api_keys`, `organizations`, `projects`, `users`, `images`, `upload_sessions`
|
||||
- **File Organization**: `orgId/projectId/category/year-month/filename.ext`
|
||||
|
||||
### Database Package (`packages/database/`)
|
||||
|
||||
Shared Drizzle ORM package used by API service and future apps:
|
||||
|
||||
- **Schema**: `src/schema/apiKeys.ts` - API keys table definition
|
||||
- **Client Factory**: `src/client.ts` - Database connection creator
|
||||
- **Migrations**: `migrations/` - SQL migration files
|
||||
- **Configuration**: `drizzle.config.ts` - Drizzle Kit configuration
|
||||
|
||||
Key table: `api_keys`
|
||||
- Stores hashed API keys (SHA-256)
|
||||
- Two types: `master` (admin, never expires) and `project` (90-day expiration)
|
||||
- Soft delete via `is_active` flag
|
||||
- Audit trail with `createdBy`, `lastUsedAt`, `createdAt`
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
### Root Environment (`.env.docker`)
|
||||
|
||||
- `DATABASE_URL` - PostgreSQL connection string (for Docker: `postgresql://banatie_user:banatie_secure_password@postgres:5432/banatie_db`)
|
||||
- `MINIO_ROOT_USER` - MinIO admin username
|
||||
- `MINIO_ROOT_PASSWORD` - MinIO admin password
|
||||
|
||||
|
|
@ -103,6 +132,7 @@ banatie-service/
|
|||
|
||||
Required environment variables:
|
||||
|
||||
- `DATABASE_URL` - PostgreSQL connection string (for local dev: `postgresql://banatie_user:banatie_secure_password@localhost:5434/banatie_db`)
|
||||
- `GEMINI_API_KEY` - Google Gemini API key (required)
|
||||
- `MINIO_ENDPOINT` - MinIO endpoint (`localhost:9000` for local dev, `minio:9000` for Docker)
|
||||
- `MINIO_ACCESS_KEY` - MinIO service account key
|
||||
|
|
@ -110,20 +140,28 @@ Required environment variables:
|
|||
- `MINIO_BUCKET_NAME` - Storage bucket name (default: `banatie`)
|
||||
- `PORT` - Server port (default: 3000)
|
||||
- `NODE_ENV` - Environment mode
|
||||
- `CORS_ORIGIN` - CORS origin setting (default: \*)
|
||||
- `CORS_ORIGIN` - CORS origin setting (default: multiple localhost URLs for frontend apps)
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
### API Service
|
||||
|
||||
- **@banatie/database** - Shared database package (workspace dependency)
|
||||
- **@google/genai** - Google Gemini AI client
|
||||
- **drizzle-orm** - TypeScript ORM (via database package)
|
||||
- **postgres** - PostgreSQL client for Node.js (via database package)
|
||||
- **express** v5 - Web framework
|
||||
- **multer** - File upload handling
|
||||
- **minio** - MinIO client for object storage
|
||||
- **express-validator** - Request validation
|
||||
- **winston** - Logging
|
||||
- **helmet** - Security middleware
|
||||
- **express-rate-limit** - Rate limiting
|
||||
|
||||
### Database Package
|
||||
|
||||
- **drizzle-orm** - TypeScript ORM for SQL databases
|
||||
- **drizzle-kit** - CLI tools for migrations
|
||||
- **postgres** - PostgreSQL client for Node.js
|
||||
|
||||
### Frontend Apps (Next.js)
|
||||
|
||||
|
|
@ -147,9 +185,59 @@ Required environment variables:
|
|||
|
||||
## API Endpoints (API Service)
|
||||
|
||||
### Public Endpoints (No Authentication)
|
||||
- `GET /health` - Health check with uptime and status
|
||||
- `GET /api/info` - API information and limits
|
||||
- `POST /api/generate` - Main image generation endpoint (multipart/form-data)
|
||||
- `POST /api/bootstrap/initial-key` - Create first master key (one-time only)
|
||||
|
||||
### Admin Endpoints (Master Key Required)
|
||||
- `POST /api/admin/keys` - Create new API keys (master or project)
|
||||
- `GET /api/admin/keys` - List all API keys
|
||||
- `DELETE /api/admin/keys/:keyId` - Revoke an API key
|
||||
|
||||
### Protected Endpoints (API Key Required)
|
||||
- `POST /api/generate` - Generate images from text + optional reference images
|
||||
- `POST /api/text-to-image` - Generate images from text only (JSON)
|
||||
- `POST /api/enhance` - Enhance and optimize text prompts
|
||||
- `GET /api/images` - List generated images
|
||||
|
||||
**Authentication**: All protected endpoints require `X-API-Key` header
|
||||
|
||||
## Authentication Setup
|
||||
|
||||
### First-Time Setup
|
||||
|
||||
1. **Start Services**: `docker compose up -d`
|
||||
2. **Create Master Key**:
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/bootstrap/initial-key
|
||||
```
|
||||
Save the returned key securely!
|
||||
|
||||
3. **Create Project Key** (for testing):
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/admin/keys \
|
||||
-H "X-API-Key: YOUR_MASTER_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"type": "project", "projectId": "test", "name": "Test Key"}'
|
||||
```
|
||||
|
||||
### Using API Keys
|
||||
|
||||
```bash
|
||||
# Image generation with project key
|
||||
curl -X POST http://localhost:3000/api/generate \
|
||||
-H "X-API-Key: YOUR_PROJECT_KEY" \
|
||||
-F "prompt=a sunset" \
|
||||
-F "filename=test_image"
|
||||
```
|
||||
|
||||
### Key Management
|
||||
|
||||
- **Master Keys**: Never expire, can create/revoke other keys, admin access
|
||||
- **Project Keys**: Expire in 90 days, for image generation only
|
||||
- **Rate Limits**: 100 requests per hour per key
|
||||
- **Revocation**: Soft delete via `is_active` flag
|
||||
|
||||
## Development Notes
|
||||
|
||||
|
|
@ -159,3 +247,4 @@ Required environment variables:
|
|||
- ESLint configured with TypeScript and Prettier integration
|
||||
- Jest for testing with ts-jest preset (API service)
|
||||
- Each app can be developed and deployed independently
|
||||
- **Docker**: Uses monorepo-aware Dockerfile (`Dockerfile.mono`) that includes workspace packages
|
||||
|
|
|
|||
|
|
@ -10,7 +10,40 @@ http://localhost:3000
|
|||
|
||||
## Authentication
|
||||
|
||||
API key required via `GEMINI_API_KEY` environment variable (server-side configuration).
|
||||
All API endpoints (except `/health`, `/api/info`, and `/api/bootstrap/*`) require authentication via API key.
|
||||
|
||||
### API Key Types
|
||||
|
||||
1. **Master Keys** - Full admin access, never expire, can create/revoke other keys
|
||||
2. **Project Keys** - Standard access for image generation, expire in 90 days
|
||||
|
||||
### Using API Keys
|
||||
|
||||
Include your API key in the `X-API-Key` header:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/generate \
|
||||
-H "X-API-Key: bnt_your_key_here" \
|
||||
-F "prompt=..." \
|
||||
-F "filename=..."
|
||||
```
|
||||
|
||||
### Getting Your First API Key
|
||||
|
||||
1. **Bootstrap** - Create initial master key (one-time only):
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/bootstrap/initial-key
|
||||
```
|
||||
|
||||
2. **Create Project Key** - Use master key to create project keys:
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/admin/keys \
|
||||
-H "X-API-Key: YOUR_MASTER_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"type": "project", "projectId": "my-project", "name": "My Project Key"}'
|
||||
```
|
||||
|
||||
**Important:** Save keys securely when created - they cannot be retrieved later!
|
||||
|
||||
## Content Types
|
||||
|
||||
|
|
@ -19,12 +52,126 @@ API key required via `GEMINI_API_KEY` environment variable (server-side configur
|
|||
|
||||
## Rate Limits
|
||||
|
||||
Standard Express rate limiting applies. Configure via environment variables.
|
||||
- **Per API Key:** 100 requests per hour
|
||||
- Rate limit information included in response headers:
|
||||
- `X-RateLimit-Limit`: Maximum requests per window
|
||||
- `X-RateLimit-Remaining`: Requests remaining
|
||||
- `X-RateLimit-Reset`: When the limit resets (ISO 8601)
|
||||
- **429 Too Many Requests:** Returned when limit exceeded
|
||||
|
||||
---
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Authentication & Admin
|
||||
|
||||
#### `POST /api/bootstrap/initial-key`
|
||||
|
||||
Create the first master API key. This endpoint works only once when no keys exist.
|
||||
|
||||
**Authentication:** None required (public endpoint, one-time use)
|
||||
|
||||
**Response (201):**
|
||||
```json
|
||||
{
|
||||
"apiKey": "bnt_...",
|
||||
"type": "master",
|
||||
"name": "Initial Master Key",
|
||||
"expiresAt": null,
|
||||
"message": "IMPORTANT: Save this key securely. You will not see it again!"
|
||||
}
|
||||
```
|
||||
|
||||
**Error (403):**
|
||||
```json
|
||||
{
|
||||
"error": "Bootstrap not allowed",
|
||||
"message": "API keys already exist. Use /api/admin/keys to create new keys."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `POST /api/admin/keys`
|
||||
|
||||
Create a new API key (master or project).
|
||||
|
||||
**Authentication:** Master key required via `X-API-Key` header
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"type": "master | project",
|
||||
"projectId": "required-for-project-keys",
|
||||
"name": "optional-friendly-name",
|
||||
"expiresInDays": 90
|
||||
}
|
||||
```
|
||||
|
||||
**Response (201):**
|
||||
```json
|
||||
{
|
||||
"apiKey": "bnt_...",
|
||||
"metadata": {
|
||||
"id": "uuid",
|
||||
"type": "project",
|
||||
"projectId": "my-project",
|
||||
"name": "My Project Key",
|
||||
"expiresAt": "2025-12-29T17:08:02.536Z",
|
||||
"scopes": ["generate", "read"],
|
||||
"createdAt": "2025-09-30T17:08:02.553Z"
|
||||
},
|
||||
"message": "IMPORTANT: Save this key securely. You will not see it again!"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `GET /api/admin/keys`
|
||||
|
||||
List all API keys.
|
||||
|
||||
**Authentication:** Master key required
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"keys": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"type": "master",
|
||||
"projectId": null,
|
||||
"name": "Initial Master Key",
|
||||
"scopes": ["*"],
|
||||
"isActive": true,
|
||||
"createdAt": "2025-09-30T17:01:23.456Z",
|
||||
"expiresAt": null,
|
||||
"lastUsedAt": "2025-09-30T17:08:45.123Z",
|
||||
"createdBy": null
|
||||
}
|
||||
],
|
||||
"total": 1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `DELETE /api/admin/keys/:keyId`
|
||||
|
||||
Revoke an API key (soft delete).
|
||||
|
||||
**Authentication:** Master key required
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"message": "API key revoked successfully",
|
||||
"keyId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Health Check
|
||||
|
||||
#### `GET /health`
|
||||
|
|
@ -79,6 +226,8 @@ Returns API metadata and configuration limits.
|
|||
|
||||
Generate images from text prompts with optional reference images.
|
||||
|
||||
**Authentication:** API key required (master or project)
|
||||
|
||||
**Content-Type:** `multipart/form-data`
|
||||
|
||||
**Parameters:**
|
||||
|
|
@ -105,6 +254,7 @@ Generate images from text prompts with optional reference images.
|
|||
**Example Request:**
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/generate \
|
||||
-H "X-API-Key: bnt_your_api_key_here" \
|
||||
-F "prompt=A majestic mountain landscape at sunset" \
|
||||
-F "filename=mountain-sunset" \
|
||||
-F "autoEnhance=true" \
|
||||
|
|
@ -151,6 +301,8 @@ curl -X POST http://localhost:3000/api/generate \
|
|||
|
||||
Generate images from text prompts only using JSON payload. Simplified endpoint for text-only requests without file uploads.
|
||||
|
||||
**Authentication:** API key required (master or project)
|
||||
|
||||
**Content-Type:** `application/json`
|
||||
|
||||
**Request Body:**
|
||||
|
|
@ -180,6 +332,7 @@ Generate images from text prompts only using JSON payload. Simplified endpoint f
|
|||
**Example Request:**
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/text-to-image \
|
||||
-H "X-API-Key: bnt_your_api_key_here" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"prompt": "A beautiful sunset over mountains with golden clouds",
|
||||
|
|
@ -237,6 +390,8 @@ curl -X POST http://localhost:3000/api/text-to-image \
|
|||
|
||||
Enhance and optimize text prompts for better image generation results.
|
||||
|
||||
**Authentication:** API key required (master or project)
|
||||
|
||||
**Content-Type:** `application/json`
|
||||
|
||||
**Request Body:**
|
||||
|
|
@ -299,17 +454,33 @@ Enhance and optimize text prompts for better image generation results.
|
|||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Bad Request - Invalid parameters or validation failure |
|
||||
| 404 | Not Found - Endpoint does not exist |
|
||||
| 401 | Unauthorized - Missing, invalid, expired, or revoked API key |
|
||||
| 403 | Forbidden - Insufficient permissions (e.g., master key required) |
|
||||
| 404 | Not Found - Endpoint or resource does not exist |
|
||||
| 429 | Too Many Requests - Rate limit exceeded |
|
||||
| 500 | Internal Server Error - Server configuration or processing error |
|
||||
|
||||
## Common Error Messages
|
||||
|
||||
### Authentication Errors
|
||||
- `"Missing API key"` - No X-API-Key header provided
|
||||
- `"Invalid API key"` - The provided API key is invalid, expired, or revoked
|
||||
- `"Master key required"` - This endpoint requires a master API key
|
||||
- `"Bootstrap not allowed"` - API keys already exist, cannot bootstrap again
|
||||
|
||||
### Validation Errors
|
||||
- `"Prompt is required"` - Missing or empty prompt parameter
|
||||
- `"Reference image validation failed"` - Invalid file format or size
|
||||
- `"Server configuration error"` - Missing GEMINI_API_KEY
|
||||
- `"Image generation failed"` - AI service error
|
||||
- `"Validation failed"` - Parameter validation error
|
||||
|
||||
### Rate Limiting
|
||||
- `"Rate limit exceeded"` - Too many requests, retry after specified time
|
||||
|
||||
### Server Errors
|
||||
- `"Server configuration error"` - Missing GEMINI_API_KEY or database connection
|
||||
- `"Image generation failed"` - AI service error
|
||||
- `"Authentication failed"` - Error during authentication process
|
||||
|
||||
---
|
||||
|
||||
## File Upload Specifications
|
||||
|
|
@ -323,8 +494,23 @@ Enhance and optimize text prompts for better image generation results.
|
|||
|
||||
| Header | Value | Description |
|
||||
|--------|-------|-------------|
|
||||
| `X-Request-ID` | string | Unique request identifier (auto-generated) |
|
||||
| `X-API-Key` | string | API key for authentication (required for most endpoints) |
|
||||
| `X-Request-ID` | string | Unique request identifier (auto-generated by server) |
|
||||
|
||||
## Response Headers
|
||||
|
||||
| Header | Description |
|
||||
|--------|-------------|
|
||||
| `X-Request-ID` | Request identifier for tracking |
|
||||
| `X-RateLimit-Limit` | Maximum requests allowed per window |
|
||||
| `X-RateLimit-Remaining` | Requests remaining in current window |
|
||||
| `X-RateLimit-Reset` | When the rate limit resets (ISO 8601) |
|
||||
|
||||
## CORS
|
||||
|
||||
Cross-origin requests supported. Configure via `CORS_ORIGIN` environment variable.
|
||||
Cross-origin requests supported from:
|
||||
- `http://localhost:3001` (Landing Page)
|
||||
- `http://localhost:3002` (Studio Platform)
|
||||
- `http://localhost:3003` (Admin Dashboard)
|
||||
|
||||
Configure additional origins via `CORS_ORIGIN` environment variable.
|
||||
Loading…
Reference in New Issue