Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
This commit is contained in:
799
npm/packages/agentic-synth/docs/DEPLOYMENT.md
Normal file
799
npm/packages/agentic-synth/docs/DEPLOYMENT.md
Normal file
@@ -0,0 +1,799 @@
|
||||
# 🚀 Agentic-Synth Deployment Guide
|
||||
|
||||
**Version**: 0.1.0
|
||||
**Last Updated**: 2025-11-22
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Pre-Deployment Checklist](#1-pre-deployment-checklist)
|
||||
2. [Environment Configuration](#2-environment-configuration)
|
||||
3. [Deployment Platforms](#3-deployment-platforms)
|
||||
4. [Production Best Practices](#4-production-best-practices)
|
||||
5. [Monitoring & Logging](#5-monitoring--logging)
|
||||
6. [Scaling Strategies](#6-scaling-strategies)
|
||||
7. [Security Considerations](#7-security-considerations)
|
||||
8. [Troubleshooting](#8-troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
## 1. Pre-Deployment Checklist
|
||||
|
||||
### ✅ Code Readiness
|
||||
|
||||
- [ ] All tests passing (run `npm test`)
|
||||
- [ ] Build succeeds (run `npm run build`)
|
||||
- [ ] No ESLint errors (run `npm run lint`)
|
||||
- [ ] TypeScript compiles (run `npm run typecheck`)
|
||||
- [ ] Dependencies audited (run `npm audit`)
|
||||
- [ ] Environment variables documented
|
||||
- [ ] Error handling implemented
|
||||
- [ ] Logging configured
|
||||
- [ ] Performance benchmarks met
|
||||
|
||||
### ✅ Configuration
|
||||
|
||||
- [ ] API keys secured (not in source code)
|
||||
- [ ] Cache strategy configured
|
||||
- [ ] Retry logic enabled
|
||||
- [ ] Rate limiting implemented
|
||||
- [ ] Timeout values set appropriately
|
||||
- [ ] Health check endpoint created
|
||||
- [ ] Metrics collection enabled
|
||||
|
||||
### ✅ Documentation
|
||||
|
||||
- [ ] README.md up to date
|
||||
- [ ] API documentation complete
|
||||
- [ ] Environment variables listed
|
||||
- [ ] Deployment instructions written
|
||||
- [ ] Troubleshooting guide available
|
||||
|
||||
---
|
||||
|
||||
## 2. Environment Configuration
|
||||
|
||||
### 2.1 Environment Variables
|
||||
|
||||
Create a `.env` file (or configure in platform):
|
||||
|
||||
```bash
|
||||
# API Configuration
|
||||
SYNTH_PROVIDER=gemini
|
||||
SYNTH_API_KEY=your-api-key-here
|
||||
SYNTH_MODEL=gemini-2.0-flash-exp
|
||||
|
||||
# Optional: OpenRouter fallback
|
||||
OPENROUTER_API_KEY=your-openrouter-key
|
||||
|
||||
# Cache Configuration
|
||||
CACHE_STRATEGY=memory
|
||||
CACHE_TTL=3600
|
||||
MAX_CACHE_SIZE=10000
|
||||
|
||||
# Performance
|
||||
MAX_RETRIES=3
|
||||
REQUEST_TIMEOUT=30000
|
||||
ENABLE_STREAMING=true
|
||||
|
||||
# Optional Integrations
|
||||
ENABLE_AUTOMATION=false
|
||||
ENABLE_VECTOR_DB=false
|
||||
RUVECTOR_URL=http://localhost:3000
|
||||
|
||||
# Monitoring
|
||||
LOG_LEVEL=info
|
||||
ENABLE_METRICS=true
|
||||
```
|
||||
|
||||
### 2.2 Configuration Validation
|
||||
|
||||
```typescript
|
||||
// config/validate.ts
|
||||
import { z } from 'zod';
|
||||
|
||||
const EnvSchema = z.object({
|
||||
SYNTH_PROVIDER: z.enum(['gemini', 'openrouter']),
|
||||
SYNTH_API_KEY: z.string().min(10),
|
||||
SYNTH_MODEL: z.string().optional(),
|
||||
CACHE_TTL: z.string().transform(Number).pipe(z.number().positive()),
|
||||
MAX_CACHE_SIZE: z.string().transform(Number).pipe(z.number().positive()),
|
||||
MAX_RETRIES: z.string().transform(Number).pipe(z.number().min(0).max(10)),
|
||||
REQUEST_TIMEOUT: z.string().transform(Number).pipe(z.number().positive()),
|
||||
});
|
||||
|
||||
export function validateEnv() {
|
||||
try {
|
||||
return EnvSchema.parse(process.env);
|
||||
} catch (error) {
|
||||
console.error('❌ Environment validation failed:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Deployment Platforms
|
||||
|
||||
### 3.1 Node.js Server (Express/Fastify)
|
||||
|
||||
**Installation:**
|
||||
|
||||
```bash
|
||||
npm install @ruvector/agentic-synth express dotenv
|
||||
```
|
||||
|
||||
**Server Setup:**
|
||||
|
||||
```typescript
|
||||
// server.ts
|
||||
import express from 'express';
|
||||
import { AgenticSynth } from '@ruvector/agentic-synth';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
// Initialize synth
|
||||
const synth = new AgenticSynth({
|
||||
provider: process.env.SYNTH_PROVIDER as 'gemini',
|
||||
apiKey: process.env.SYNTH_API_KEY!,
|
||||
cacheStrategy: 'memory',
|
||||
cacheTTL: parseInt(process.env.CACHE_TTL || '3600'),
|
||||
maxCacheSize: parseInt(process.env.MAX_CACHE_SIZE || '10000'),
|
||||
});
|
||||
|
||||
// Health check
|
||||
app.get('/health', async (req, res) => {
|
||||
try {
|
||||
const stats = synth.cache.getStats();
|
||||
res.json({
|
||||
status: 'healthy',
|
||||
timestamp: new Date().toISOString(),
|
||||
cache: {
|
||||
size: stats.size,
|
||||
hitRate: (stats.hitRate * 100).toFixed(2) + '%'
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(503).json({ status: 'unhealthy', error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Generate endpoint
|
||||
app.post('/generate/:type', async (req, res) => {
|
||||
try {
|
||||
const { type } = req.params;
|
||||
const options = req.body;
|
||||
|
||||
const result = await synth.generate(type as any, options);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
app.listen(PORT, () => {
|
||||
console.log(`✅ Server running on port ${PORT}`);
|
||||
});
|
||||
```
|
||||
|
||||
**Start:**
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
node dist/server.js
|
||||
```
|
||||
|
||||
### 3.2 AWS Lambda (Serverless)
|
||||
|
||||
**Installation:**
|
||||
|
||||
```bash
|
||||
npm install @ruvector/agentic-synth aws-lambda
|
||||
```
|
||||
|
||||
**Lambda Handler:**
|
||||
|
||||
```typescript
|
||||
// lambda/handler.ts
|
||||
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
|
||||
import { AgenticSynth } from '@ruvector/agentic-synth';
|
||||
|
||||
// Initialize outside handler for reuse (Lambda warm starts)
|
||||
const synth = new AgenticSynth({
|
||||
provider: process.env.SYNTH_PROVIDER as 'gemini',
|
||||
apiKey: process.env.SYNTH_API_KEY!,
|
||||
cacheStrategy: 'memory',
|
||||
cacheTTL: 3600,
|
||||
});
|
||||
|
||||
export const handler = async (
|
||||
event: APIGatewayProxyEvent
|
||||
): Promise<APIGatewayProxyResult> => {
|
||||
try {
|
||||
const { type, ...options } = JSON.parse(event.body || '{}');
|
||||
|
||||
const result = await synth.generate(type, options);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(result),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
statusCode: 500,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ error: error.message }),
|
||||
};
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**Deployment (Serverless Framework):**
|
||||
|
||||
```yaml
|
||||
# serverless.yml
|
||||
service: agentic-synth-api
|
||||
|
||||
provider:
|
||||
name: aws
|
||||
runtime: nodejs20.x
|
||||
region: us-east-1
|
||||
environment:
|
||||
SYNTH_PROVIDER: ${env:SYNTH_PROVIDER}
|
||||
SYNTH_API_KEY: ${env:SYNTH_API_KEY}
|
||||
CACHE_TTL: 3600
|
||||
|
||||
functions:
|
||||
generate:
|
||||
handler: dist/lambda/handler.handler
|
||||
events:
|
||||
- http:
|
||||
path: generate
|
||||
method: post
|
||||
timeout: 30
|
||||
memorySize: 1024
|
||||
```
|
||||
|
||||
```bash
|
||||
serverless deploy
|
||||
```
|
||||
|
||||
### 3.3 Docker Container
|
||||
|
||||
**Dockerfile:**
|
||||
|
||||
```dockerfile
|
||||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
RUN npm ci --production
|
||||
|
||||
# Copy source and build
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
|
||||
|
||||
# Start server
|
||||
CMD ["node", "dist/server.js"]
|
||||
```
|
||||
|
||||
**Build & Run:**
|
||||
|
||||
```bash
|
||||
docker build -t agentic-synth .
|
||||
docker run -p 3000:3000 \
|
||||
-e SYNTH_PROVIDER=gemini \
|
||||
-e SYNTH_API_KEY=your-key \
|
||||
-e CACHE_TTL=3600 \
|
||||
agentic-synth
|
||||
```
|
||||
|
||||
**Docker Compose:**
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
agentic-synth:
|
||||
build: .
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- SYNTH_PROVIDER=gemini
|
||||
- SYNTH_API_KEY=${SYNTH_API_KEY}
|
||||
- CACHE_TTL=3600
|
||||
- MAX_CACHE_SIZE=10000
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
||||
interval: 30s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 3.4 Vercel (Edge Functions)
|
||||
|
||||
**Installation:**
|
||||
|
||||
```bash
|
||||
npm install @ruvector/agentic-synth
|
||||
```
|
||||
|
||||
**API Route:**
|
||||
|
||||
```typescript
|
||||
// api/generate.ts
|
||||
import type { VercelRequest, VercelResponse } from '@vercel/node';
|
||||
import { AgenticSynth } from '@ruvector/agentic-synth';
|
||||
|
||||
const synth = new AgenticSynth({
|
||||
provider: process.env.SYNTH_PROVIDER as 'gemini',
|
||||
apiKey: process.env.SYNTH_API_KEY!,
|
||||
cacheStrategy: 'memory',
|
||||
cacheTTL: 3600,
|
||||
});
|
||||
|
||||
export default async function handler(
|
||||
req: VercelRequest,
|
||||
res: VercelResponse
|
||||
) {
|
||||
if (req.method !== 'POST') {
|
||||
return res.status(405).json({ error: 'Method not allowed' });
|
||||
}
|
||||
|
||||
try {
|
||||
const { type, ...options } = req.body;
|
||||
const result = await synth.generate(type, options);
|
||||
res.status(200).json(result);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Deploy:**
|
||||
|
||||
```bash
|
||||
vercel deploy --prod
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Production Best Practices
|
||||
|
||||
### 4.1 Error Handling
|
||||
|
||||
```typescript
|
||||
import { AgenticSynth, APIError, ValidationError } from '@ruvector/agentic-synth';
|
||||
|
||||
app.post('/generate', async (req, res) => {
|
||||
try {
|
||||
const result = await synth.generate(req.body.type, req.body.options);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
if (error instanceof ValidationError) {
|
||||
return res.status(400).json({
|
||||
error: 'Validation failed',
|
||||
details: error.validationErrors
|
||||
});
|
||||
}
|
||||
|
||||
if (error instanceof APIError) {
|
||||
console.error('API Error:', {
|
||||
provider: error.provider,
|
||||
status: error.statusCode,
|
||||
message: error.message
|
||||
});
|
||||
|
||||
return res.status(502).json({
|
||||
error: 'External API error',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
|
||||
// Unknown error
|
||||
console.error('Unexpected error:', error);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 4.2 Request Validation
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod';
|
||||
|
||||
const GenerateRequestSchema = z.object({
|
||||
type: z.enum(['time-series', 'events', 'structured']),
|
||||
options: z.object({
|
||||
count: z.number().positive().max(10000),
|
||||
schema: z.record(z.any()),
|
||||
constraints: z.array(z.string()).optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
app.post('/generate', async (req, res) => {
|
||||
try {
|
||||
const validated = GenerateRequestSchema.parse(req.body);
|
||||
const result = await synth.generate(validated.type, validated.options);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return res.status(400).json({
|
||||
error: 'Invalid request',
|
||||
details: error.errors
|
||||
});
|
||||
}
|
||||
// ... other error handling
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 4.3 Rate Limiting
|
||||
|
||||
```typescript
|
||||
import rateLimit from 'express-rate-limit';
|
||||
|
||||
const limiter = rateLimit({
|
||||
windowMs: 60 * 1000, // 1 minute
|
||||
max: 60, // 60 requests per minute
|
||||
message: 'Too many requests, please try again later',
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
});
|
||||
|
||||
app.use('/generate', limiter);
|
||||
```
|
||||
|
||||
### 4.4 Caching Strategy
|
||||
|
||||
```typescript
|
||||
// Use cache for repeated requests
|
||||
const synth = new AgenticSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.SYNTH_API_KEY!,
|
||||
cacheStrategy: 'memory',
|
||||
cacheTTL: 3600, // 1 hour
|
||||
maxCacheSize: 10000,
|
||||
});
|
||||
|
||||
// Monitor cache performance
|
||||
setInterval(() => {
|
||||
const stats = synth.cache.getStats();
|
||||
console.log('Cache Stats:', {
|
||||
size: stats.size,
|
||||
hitRate: (stats.hitRate * 100).toFixed(2) + '%',
|
||||
utilization: ((stats.size / 10000) * 100).toFixed(2) + '%'
|
||||
});
|
||||
}, 60000); // Every minute
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Monitoring & Logging
|
||||
|
||||
### 5.1 Structured Logging
|
||||
|
||||
```typescript
|
||||
import winston from 'winston';
|
||||
|
||||
const logger = winston.createLogger({
|
||||
level: process.env.LOG_LEVEL || 'info',
|
||||
format: winston.format.json(),
|
||||
transports: [
|
||||
new winston.transports.File({ filename: 'error.log', level: 'error' }),
|
||||
new winston.transports.File({ filename: 'combined.log' }),
|
||||
],
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
logger.add(new winston.transports.Console({
|
||||
format: winston.format.simple(),
|
||||
}));
|
||||
}
|
||||
|
||||
// Log all requests
|
||||
app.use((req, res, next) => {
|
||||
logger.info('Request', {
|
||||
method: req.method,
|
||||
path: req.path,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
next();
|
||||
});
|
||||
|
||||
// Log generation events
|
||||
app.post('/generate', async (req, res) => {
|
||||
const start = Date.now();
|
||||
try {
|
||||
const result = await synth.generate(req.body.type, req.body.options);
|
||||
|
||||
logger.info('Generation success', {
|
||||
type: req.body.type,
|
||||
count: req.body.options.count,
|
||||
duration: Date.now() - start,
|
||||
cached: result.metadata.cached,
|
||||
generationTime: result.metadata.generationTime
|
||||
});
|
||||
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
logger.error('Generation failed', {
|
||||
type: req.body.type,
|
||||
error: error.message,
|
||||
duration: Date.now() - start
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 5.2 Metrics Collection
|
||||
|
||||
```typescript
|
||||
import { Counter, Histogram, register } from 'prom-client';
|
||||
|
||||
// Define metrics
|
||||
const requestCounter = new Counter({
|
||||
name: 'synth_requests_total',
|
||||
help: 'Total number of generation requests',
|
||||
labelNames: ['type', 'status']
|
||||
});
|
||||
|
||||
const requestDuration = new Histogram({
|
||||
name: 'synth_request_duration_seconds',
|
||||
help: 'Duration of generation requests',
|
||||
labelNames: ['type']
|
||||
});
|
||||
|
||||
const cacheHitRate = new Histogram({
|
||||
name: 'synth_cache_hit_rate',
|
||||
help: 'Cache hit rate percentage'
|
||||
});
|
||||
|
||||
// Expose metrics endpoint
|
||||
app.get('/metrics', async (req, res) => {
|
||||
res.set('Content-Type', register.contentType);
|
||||
res.end(await register.metrics());
|
||||
});
|
||||
|
||||
// Track metrics
|
||||
app.post('/generate', async (req, res) => {
|
||||
const end = requestDuration.startTimer({ type: req.body.type });
|
||||
|
||||
try {
|
||||
const result = await synth.generate(req.body.type, req.body.options);
|
||||
|
||||
requestCounter.inc({ type: req.body.type, status: 'success' });
|
||||
cacheHitRate.observe(result.metadata.cached ? 100 : 0);
|
||||
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
requestCounter.inc({ type: req.body.type, status: 'error' });
|
||||
throw error;
|
||||
} finally {
|
||||
end();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Scaling Strategies
|
||||
|
||||
### 6.1 Horizontal Scaling
|
||||
|
||||
**Load Balancer (Nginx):**
|
||||
|
||||
```nginx
|
||||
upstream agentic_synth {
|
||||
least_conn;
|
||||
server synth1:3000 weight=1;
|
||||
server synth2:3000 weight=1;
|
||||
server synth3:3000 weight=1;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
location / {
|
||||
proxy_pass http://agentic_synth;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
|
||||
location /health {
|
||||
proxy_pass http://agentic_synth/health;
|
||||
proxy_connect_timeout 2s;
|
||||
proxy_send_timeout 2s;
|
||||
proxy_read_timeout 2s;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 Kubernetes Deployment
|
||||
|
||||
```yaml
|
||||
# deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: agentic-synth
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: agentic-synth
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: agentic-synth
|
||||
spec:
|
||||
containers:
|
||||
- name: agentic-synth
|
||||
image: agentic-synth:latest
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
env:
|
||||
- name: SYNTH_PROVIDER
|
||||
value: "gemini"
|
||||
- name: SYNTH_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: synth-secrets
|
||||
key: api-key
|
||||
- name: CACHE_TTL
|
||||
value: "3600"
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "1000m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 3000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 3000
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: agentic-synth-service
|
||||
spec:
|
||||
selector:
|
||||
app: agentic-synth
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 3000
|
||||
type: LoadBalancer
|
||||
---
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: agentic-synth-hpa
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: agentic-synth
|
||||
minReplicas: 3
|
||||
maxReplicas: 10
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 70
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 80
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Security Considerations
|
||||
|
||||
### 7.1 API Key Management
|
||||
|
||||
```typescript
|
||||
// ✅ Good: Environment variables
|
||||
const synth = new AgenticSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: process.env.SYNTH_API_KEY!
|
||||
});
|
||||
|
||||
// ❌ Bad: Hardcoded
|
||||
const synth = new AgenticSynth({
|
||||
provider: 'gemini',
|
||||
apiKey: 'AIza...' // NEVER DO THIS
|
||||
});
|
||||
```
|
||||
|
||||
### 7.2 Input Validation
|
||||
|
||||
```typescript
|
||||
const MAX_GENERATION_COUNT = 10000;
|
||||
const MAX_SCHEMA_DEPTH = 5;
|
||||
|
||||
function validateOptions(options: any) {
|
||||
if (options.count > MAX_GENERATION_COUNT) {
|
||||
throw new Error(`Count exceeds maximum (${MAX_GENERATION_COUNT})`);
|
||||
}
|
||||
|
||||
if (getSchemaDepth(options.schema) > MAX_SCHEMA_DEPTH) {
|
||||
throw new Error(`Schema depth exceeds maximum (${MAX_SCHEMA_DEPTH})`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.3 HTTPS Only
|
||||
|
||||
```typescript
|
||||
// Redirect HTTP to HTTPS
|
||||
app.use((req, res, next) => {
|
||||
if (req.header('x-forwarded-proto') !== 'https' && process.env.NODE_ENV === 'production') {
|
||||
res.redirect(`https://${req.header('host')}${req.url}`);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Issue: High Memory Usage**
|
||||
- Solution: Reduce `maxCacheSize` or enable streaming for large datasets
|
||||
|
||||
**Issue: Slow Response Times**
|
||||
- Solution: Enable caching, use faster model, increase `cacheTTL`
|
||||
|
||||
**Issue: Rate Limiting (429)**
|
||||
- Solution: Implement exponential backoff, add rate limiter
|
||||
|
||||
**Issue: API Connection Failures**
|
||||
- Solution: Verify API key, check network connectivity, implement retry logic
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-11-22
|
||||
**Package Version**: 0.1.0
|
||||
**Status**: Production Ready ✅
|
||||
Reference in New Issue
Block a user