SpektraBot Development Guide โ
Getting started with local development, testing, deployment procedures, CI/CD, and troubleshooting for SpektraBot.
Deployment section below is historical. The Helm / Civo Kubernetes content describes the retired infrastructure. Current deployment is Azure Container Apps โ see Architecture ยง17 for the live build-and-deploy workflow. The sections below are retained for archaeology until we rewrite this page.
1. Deployment (historical โ retired Civo Kubernetes) โ
1.1 Helm Chart Structure โ
The application Helm chart is in helm/spektrabot/ with 37 templates:
| Template | Description |
|---|---|
api-deployment.yaml | API backend pods |
web-deployment.yaml | Next.js frontend pods |
redis-deployment.yaml | Redis cache |
cloudnativepg-cluster.yaml | CloudNativePG PostgreSQL cluster |
cloudnativepg-objectstore.yaml | Backup object store config |
cloudnativepg-scheduledbackup.yaml | Scheduled database backups (CNPG barman) |
pg-backup-s3-cronjob.yaml | Standalone S3 backup CronJob (every 6h) |
pg-backup-s3-configmap.yaml | Backup script configuration |
ingress.yaml | NGINX ingress for HTTP traffic |
ingress-socketio.yaml | WebSocket ingress with sticky sessions |
hpa.yaml | Horizontal Pod Autoscaler |
networkpolicy.yaml | Network policies for pod isolation |
cronjob-gias-sync.yaml | Daily GIAS school data sync |
umami-deployment.yaml | Privacy-focused analytics |
secret.yaml | Kubernetes secrets |
configmap.yaml | Configuration |
rbac.yaml | RBAC rules |
servicemonitor-api.yaml | Prometheus ServiceMonitor for API |
podmonitor-cnpg.yaml | Prometheus PodMonitor for PostgreSQL |
cnpg-custom-queries-cm.yaml | Custom PostgreSQL metric queries |
1.2 Values Configuration โ
| File | Purpose |
|---|---|
values.yaml | Default values (local development) |
values-civo.yaml | Civo Kubernetes overrides (storage class: civo-volume) |
values-pilot.yaml | 20-user pilot sizing |
values-production.yaml | Production configuration |
1.3 Kubernetes Architecture โ
1.4 Backup Strategy (Dual-Layer) โ
Primary: Standalone S3 CronJob (every 6 hours)
- pg_dump in custom format uploaded to Civo Object Storage
- Independent of kubelet exec (works even when cluster has proxy issues)
- Integrity verification: rejects files <1MB, validates with
pg_restore --list - Retains last 7 backups with automatic pruning
- Civo S3 quirks: signature v2, multipart threshold 600MB
Secondary: CNPG Barman Cloud (continuous + daily)
- WAL archiving for point-in-time recovery
- Daily base backups at 2 AM UTC
- 30-day retention
- Depends on kubelet exec (can fail during cluster issues)
1.5 Docker Multi-Stage Builds โ
Both API and Web packages use multi-stage Docker builds:
- deps -- Install pnpm dependencies with hoisting
- builder -- Compile TypeScript / build Next.js (standalone output)
- runner -- Minimal production image
Key considerations:
--platform linux/amd64required when building on ARM (Mac) for Civo (AMD64)--no-cacheto avoid cached ARM layerspnpm-workspace.yamland.npmrcmust be copied for monorepo resolution- Next.js requires
output: "standalone"innext.config.ts
2. Development Setup โ
Prerequisites โ
- Node.js 22+
- pnpm 9+
- Docker and Docker Compose
Quick Start โ
bash
# 1. Install dependencies
pnpm install
# 2. Start database services
docker-compose up -d
# 3. Configure environment
cp .env.example .env
# Edit .env with your Azure OpenAI API keys and other settings
# 4. Generate Prisma client
pnpm db:generate
# 5. Run database migrations
pnpm db:migrate
# 6. Seed database (optional)
pnpm db:seed
# 7. Start development servers
pnpm dev- Frontend: http://localhost:3000
- API: http://localhost:3001
- Prisma Studio:
pnpm db:studio
Key Development Scripts โ
| Script | Description |
|---|---|
pnpm dev | Start all services in development mode |
pnpm build | Build all packages for production |
pnpm test | Run all tests |
pnpm lint | Lint all packages |
pnpm type-check | TypeScript type checking |
pnpm db:generate | Generate Prisma client |
pnpm db:migrate | Run database migrations |
pnpm db:studio | Open Prisma Studio GUI |
pnpm db:seed | Seed database with test data |
3. Testing โ
The test suite uses Vitest with ~30+ test files across multiple layers.
Test Structure โ
| Directory | Type | Examples |
|---|---|---|
tests/unit/ | Unit tests | Auth service, chat handlers, admin service, prompt assembly, config validation |
tests/unit/chat/ | Chat unit tests | Agentic RAG, clarification, conversation history, validators |
tests/integration/ | Integration tests | Azure OpenAI flow, RAG knowledge base, user isolation, admin schools, prompt quality |
tests/infrastructure/ | Infrastructure tests | Database persistence, pgvector indexes |
tests/services/ | Service tests | Children CRUD, email service, waitlist |
Running Tests โ
bash
# Run all tests
pnpm test
# Run integration tests only
pnpm test:integration
# Run with coverage
pnpm test:ci
# Run specific test file
pnpm --filter @spektrabot/api test -- tests/unit/chat/agentic-rag.test.ts4. Key Configuration โ
Environment Variables โ
| Variable | Required | Description |
|---|---|---|
DATABASE_URL | Yes | PostgreSQL connection string |
REDIS_URL | Yes | Redis connection string |
JWT_SECRET | Yes | JWT signing secret (32+ chars) |
AZURE_OPENAI_API_KEY | Yes | Azure OpenAI API key |
AZURE_OPENAI_ENDPOINT | Yes | Azure OpenAI endpoint URL |
AZURE_OPENAI_API_VERSION | No | Azure OpenAI API version (default: 2024-10-21) |
AZURE_OPENAI_DEPLOYMENT_NAME | No | Chat model deployment (default: gpt-4o) |
AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME | No | Embedding model deployment (default: text-embedding-3-large) |
AI_MODEL | No | AI model (default: gpt-4o) |
CORS_ORIGIN | Yes | Allowed CORS origins (comma-separated) |
INVITE_CODE | Yes | Registration invite code |
RESEND_API_KEY | No | Resend email service API key |
CIVO_ACCESS_KEY | No | Civo object storage access key |
ENABLE_AGENTIC_RAG | No | Enable agentic RAG (default: true) |
RELEVANCE_THRESHOLD | No | RAG relevance threshold (default: 0.3) |
SKIP_HALLUCINATION_CHECK | No | Skip hallucination checking (default: false) |
DATA_RETENTION_DAYS | No | GDPR data retention period (default: 90) |