# JobsBoard Platform — Production Deployment & Operational Architecture Guide ## 1. System Topology Overview ```text [ Internet / CDN (Cloudflare) ] │ HTTPS / TLS Termination │ ▼ [ Next.js Application ] (Docker Container / Node.js 20+) │ ┌───────────────────────────┼───────────────────────────┐ ▼ ▼ ▼ [ PostgreSQL 16+ ] [ Upstash / Redis ] [ S3 / Cloudflare R2 ] Primary Relational DB Distributed Rate Limiting Private Candidate Files (Foreign Keys & BOLA) & Session Revocations (Pre-signed downloads) ``` --- ## 2. Infrastructure System States | Subsystem | State | Implementation / Configuration Details | | :--- | :--- | :--- | | **Relational Database** | **ACTIVE AND VERIFIED** | **PostgreSQL 16** container actively running on `localhost:5432` (`jobsboard-postgres`). Schema synchronized with 76 production indexes, cascades, and constraints. All 1,425 jobs, 400 companies, 9 users, 1 resume, and active applications imported and verified. | | **Multi-Tenant Ownership**| **ACTIVE AND VERIFIED** | Strict foreign-key relationship (`job.postedById === user.id` OR `job.companyId === user.companyId`). String matching eliminated; scraped jobs cannot be claimed or manipulated by employers. | | **Session Invalidation** | **ACTIVE AND VERIFIED** | Dynamic DB rehydration in `getAuthUser()`. Suspended accounts (`lockedUntil > now`) are immediately denied access on next HTTP request regardless of unexpired JWT token. | | **Distributed Rate Limiting** | **IMPLEMENTED BUT NOT CONFIGURED** | Unified `IRateLimiter` with `DistributedRedisRateLimiter` (atomic `INCR` + `EXPIRE` over Upstash REST). Automatically activates when `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` are set. Falls back to in-memory store with 10k key eviction cap. | | **Object Storage** | **IMPLEMENTED BUT NOT CONFIGURED** | `IObjectStorage` abstraction in `lib/storage.ts`. Local adapter stores files with UUID keys and strict path traversal sanitization (`../../../etc/passwd` -> `etcpasswd`). Production S3/R2 adapter activates when `STORAGE_ACCESS_KEY` & `STORAGE_SECRET_KEY` are provided. | | **Background Processing** | **DEVELOPMENT ONLY** | In-memory asynchronous queue (`lib/queue.ts`) with exponential backoff retries and dead-letter log handling. Suitable for non-blocking local email and notification dispatches. Requires BullMQ/SQS for persistent distributed workers. | --- ## 3. Environment Variables Specification Create `.env.production` in the deployment environment: ```bash # Database Connection (PostgreSQL 16+) DATABASE_URL="postgresql://username:password@db-host.internal:5432/jobsboard?schema=public&sslmode=require" # NextAuth Authentication NEXTAUTH_URL="https://jobsboard.yourdomain.com" NEXTAUTH_SECRET="generate-strong-64-character-crypto-hex-secret" # Node Environment NODE_ENV="production" PORT=3000 # Distributed Rate Limiting (Upstash / Redis REST API) UPSTASH_REDIS_REST_URL="https://your-redis-instance.upstash.io" UPSTASH_REDIS_REST_TOKEN="your-upstash-rest-token" # Object Storage (AWS S3, Cloudflare R2, MinIO) STORAGE_ENDPOINT="https://.r2.cloudflarestorage.com" STORAGE_BUCKET="jobsboard-private-assets" STORAGE_ACCESS_KEY="your-storage-access-key" STORAGE_SECRET_KEY="your-storage-secret-key" # Automated Cron & Job Alert Security Secret CRON_SECRET="generate-strong-random-bearer-token-for-alerts" # Outbound Email Service (Resend / AWS SES) RESEND_API_KEY="re_your_api_key_here" EMAIL_FROM="JobsBoard Talent Alerts " ``` --- ## 4. Production Database Migration & Restoration ### Step 1: Initialize Database Schema ```bash npx prisma db push --schema=prisma/schema.postgresql.prisma ``` ### Step 2: Restore Core Dataset (If Migrating Existing SQLite dev.db) ```bash DATABASE_URL="postgresql://user:password@host:5432/jobsboard?schema=public" node scripts/import-postgres-data.js ``` ### Step 3: Run E2E Database & Multi-Tenant Tests ```bash npm run test:postgres ``` --- ## 5. Failure Modes & Resilience Policy | Failure Condition | System Impact | Degraded Behavior & Safeguards | | :--- | :--- | :--- | | **PostgreSQL Outage** | Critical | `/api/health` returns `503 Service Unavailable`. Database queries fail fast; sensitive operations reject rather than expose unauthenticated resources. | | **Redis / Rate Limiter Down** | Medium | `DistributedRedisRateLimiter` automatically degrades to high-throughput local memory limiter (`MemoryRateLimiter`). Sensitive endpoints remain bounded by local 10k LRU memory table. | | **Object Storage Unreachable** | Medium | Resume download fallback serves generated PDF stream on-the-fly via PDFKit. `/api/health` reports degraded storage status. | | **Queue Worker Crash** | Low | In-memory queue logs dead-letter events for retry upon container restart. | --- ## 6. Disaster Recovery & Backup Plan 1. **Daily Automated Snapshots**: ```bash # Daily PostgreSQL Logical Backup pg_dump -U postgres -h localhost -d jobsboard --format=custom --file="/backups/jobsboard_$(date +%Y%m%d_%H%M%S).dump" ``` 2. **Restoration Procedure**: ```bash pg_restore -U postgres -h localhost -d jobsboard --clean --if-exists "/backups/jobsboard_target.dump" ``` 3. **Point-in-Time Recovery (PITR)**: Enable Write-Ahead Log (WAL) archiving in production cloud database providers (AWS RDS, Supabase, Neon, GCP Cloud SQL).