# Runbook — Accessible Video Processing Platform

<!-- SCOPE: runbook | owner: ln-115 | generated: 2026-04-29 -->

## Local Development Setup

### Prerequisites

| Requirement | Version |
|-------------|---------|
| Docker | 20.10+ |
| Docker Compose | V2 (bundled with Docker Desktop) |
| Node.js | 20+ |
| Python | 3.11+ (for local scripts only; app runs in Docker) |
| GCP credentials file | `./secrets/gcp-credentials.json` |

### First-Time Setup

| Step | Command / Action |
|------|-----------------|
| 1. Copy env template | `cp .env.prod.example .env.local` — fill in all values |
| 2. Copy frontend env | `cp frontend/.env.example frontend/.env.local` |
| 3. Place GCP credentials | Copy service account JSON to `./secrets/gcp-credentials.json` |
| 4. Set permissions | `chmod 600 ./secrets/gcp-credentials.json` |

### Starting the Local Environment

**Step 1 — Backend (Docker):**

`./scripts/run-local.sh`

Services after start:

| Service | URL |
|---------|-----|
| API | http://localhost:8003 |
| API docs (Swagger) | http://localhost:8003/docs |
| MongoDB | mongodb://localhost:27017 |
| Redis | redis://localhost:6379 |

**Step 2 — Frontend (Vite dev server, separate terminal):**

`cd frontend && npm install && npm run dev`

Frontend URL: http://localhost:6001/video-accessibility

### Common Local Commands

| Action | Command |
|--------|---------|
| Rebuild containers after code change | `./scripts/run-local.sh --rebuild` |
| Stop all services | `./scripts/run-local.sh --stop` |
| Tail all logs | `docker compose logs -f` |
| Tail API logs | `docker compose logs -f api` |
| Tail worker logs | `docker compose logs -f worker` |
| Restart a service | `docker compose restart api` |

### Test Credentials (Local Only)

| Role | Email | Password |
|------|-------|---------|
| Admin | admin@example.com | admin |
| Reviewer | reviewer@example.com | reviewer |
| Client | client@example.com | client123 |

Production uses Microsoft SSO — these credentials do not work in production.

---

## Production Deployment

**Server:** optical-web-1
**Deploy path:** `/opt/video-accessibility/`
**URL:** https://ai-sandbox.oliver.solutions/video-accessibility/

### Full Deployment (code + frontend)

Run on server (requires explicit user instruction — NEVER run via SSH without user approval):

`./scripts/full-deploy.sh`

This script:

| Step | Action |
|------|--------|
| 1 | Pull latest code from git |
| 2 | Build Docker images |
| 3 | Restart containers |
| 4 | Build frontend bundle |
| 5 | Copy bundle to Apache webroot |
| 6 | Run DB seed if needed |

### Frontend-Only Deployment

`./scripts/build-frontend.sh`

Builds the React bundle and copies to `/var/www/html/video-accessibility/`.

### Verification After Deploy

| Check | Command / URL |
|-------|--------------|
| API health | `curl https://ai-sandbox.oliver.solutions/video-accessibility-back/health` |
| Container status | `docker compose ps` |
| Frontend loads | Visit https://ai-sandbox.oliver.solutions/video-accessibility |
| Worker running | `docker compose logs --tail=20 worker` |

---

## Database Operations

### Backup MongoDB

| Step | Command |
|------|---------|
| Dump to container | `docker compose exec mongodb mongodump --out=/data/backup` |
| Copy to host | `docker cp accessible-video-mongodb:/data/backup ./mongodb-backup-$(date +%Y%m%d)` |

### Restore MongoDB

| Step | Command |
|------|---------|
| Copy to container | `docker cp ./mongodb-backup accessible-video-mongodb:/data/restore` |
| Restore | `docker compose exec mongodb mongorestore /data/restore` |

### MongoDB Shell

`docker compose exec mongodb mongosh`

---

## Restarting Services

| Action | Command |
|--------|---------|
| Restart all | `docker compose restart` |
| Restart API only | `docker compose restart api` |
| Restart worker only | `docker compose restart worker` |
| Rebuild + restart one service | `docker compose up -d --build api` |

---

## Updating Application

| Step | Command |
|------|---------|
| Pull code | `git pull origin main` |
| Full redeploy | `./scripts/full-deploy.sh` |
| Frontend only | `./scripts/build-frontend.sh` |

---

## Linting and Type Checking

| Check | Command | Must pass before deploy |
|-------|---------|------------------------|
| Backend lint | `cd backend && ruff check .` | Yes |
| Backend type check | `docker compose exec api python -m mypy app/` | Yes |
| Frontend lint | `cd frontend && npm run lint` | Yes |
| Frontend type check | `cd frontend && npm run type-check` | Yes (currently 0 errors) |

---

## Monitoring

| Tool | Access | Purpose |
|------|--------|---------|
| Docker stats | `docker stats` | Container CPU/memory usage |
| API logs | `docker compose logs -f api` | Request errors |
| Worker logs | `docker compose logs -f worker` | Task errors |
| Sentry | sentry.io | Exception capture + stack traces |
| Prometheus | localhost:8001/metrics | Metrics (internal only) |

---

## Troubleshooting

| Symptom | Check | Fix |
|---------|-------|-----|
| 502 Bad Gateway on API | `docker compose ps api` + logs | Restart: `docker compose restart api` |
| Frontend 404 | `ls /var/www/html/video-accessibility/` | Rebuild: `./scripts/build-frontend.sh` |
| WebSocket fails | `apache2ctl -M | grep proxy_wstunnel` | `sudo a2enmod proxy_wstunnel && sudo systemctl restart apache2` |
| Worker not processing | `docker compose logs -f worker` | Check Redis URL + GCP credentials mount |
| Upload fails (GCS) | Test credentials in container | Check `./secrets/gcp-credentials.json` exists + permissions |
| MongoDB auth fails | Check `MONGODB_URI` env var | Verify Atlas connection string |

---

## Apache Configuration

Required modules:

`sudo a2enmod rewrite proxy proxy_http proxy_wstunnel headers && sudo systemctl restart apache2`

Config file: `/etc/apache2/sites-available/ai-sandbox.oliver.solutions-ssl.conf`

Key directives needed:

| Directive | Purpose |
|-----------|---------|
| `Alias /video-accessibility /var/www/html/video-accessibility` | Serve frontend |
| `ProxyPass /video-accessibility-back http://localhost:8000` | Proxy API |
| `RewriteRule ^ /video-accessibility/index.html [L]` | SPA routing |
| `RewriteEngine On` with WebSocket rules | WS proxy |

---

## Maintenance

**Update triggers:** New deploy script, new service port, new server.
**Verification:** All commands in this runbook execute without error on a clean checkout. Test credentials are not committed to production env files.

<!-- END SCOPE: runbook -->
