video-accessibility/docs/project/infrastructure.md
Vadym Samoilenko 6559ccc1f9 feat(help): in-app role-based help guides + screenshot capture pipeline
- Help.tsx: role tabs, TOC scroll-spy, search, lightbox, react-markdown renderer
- 7 markdown guides (global, client, linguist, reviewer, production, PM, admin)
  with explicit click/drag/keyboard annotations throughout
- Sidebar: Help button added at bottom of nav (all roles)
- App.tsx: /help route, no RoleGate
- frontend/public/help-screenshots/{role}/: directories ready for screenshots
- tools/capture-help-screenshots.ts: Playwright screenshot script
  - Clicks "Local login" toggle before filling credentials
  - Uses test-admin local account (not SSO)
- backend/scripts/seed_test_users.py: idempotent MongoDB seed script
  creates 6 local-auth users (admin + 5 roles) for capture + local dev
- .env.screenshots.example: template with test-admin credentials
- Removes docs/video_accessibility_user_guide_v3.md (superseded by in-app guides)
- Deps: react-markdown, remark-gfm, rehype-raw added to frontend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 13:08:13 +01:00

172 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Infrastructure — Accessible Video Processing Platform
<!-- SCOPE: Declarative inventory of what is deployed and where — servers, services, ports, external dependencies. No procedures (see runbook.md). -->
<!-- DOC_KIND: explanation -->
<!-- DOC_ROLE: canonical -->
<!-- READ_WHEN: Read when you need to know what runs where, which ports are exposed, or which external services are used. -->
<!-- SKIP_WHEN: Skip when you need deployment steps → runbook.md; API contracts → api_spec.md. -->
<!-- PRIMARY_SOURCES: docker-compose.yml, backend/app/core/config.py -->
**Generated:** 2026-05-01
---
## Quick Navigation
- [Docs Hub](../README.md)
- [Runbook](runbook.md)
- [Architecture](architecture.md)
- [Tech Stack](tech_stack.md)
## Agent Entry
| Signal | Value |
|--------|-------|
| Purpose | Inventory of servers, Docker services, ports, and external dependencies |
| Read When | You need to know what runs where, port mappings, or external service dependencies |
| Skip When | You need how-to deploy → runbook.md; API contracts → api_spec.md |
| Canonical | Yes |
| Next Docs | [Runbook](runbook.md), [Architecture](architecture.md) |
| Primary Sources | `docker-compose.yml`, `.env.example` |
---
## Server Inventory
| Server | Role | Environment |
|--------|------|-------------|
| `optical-web-1` | Production host — runs all Docker services | Production |
| Local machine | Developer workstation — Docker Compose local stack | Development |
**Production URL:** `https://ai-sandbox.oliver.solutions/video-accessibility`
**Production API URL:** `https://ai-sandbox.oliver.solutions/video-accessibility-back`
---
## Docker Services
All services are defined in `docker-compose.yml` and share the `accessible-video-network` bridge network.
| Service | Image / Build | Container Name | Purpose |
|---------|--------------|----------------|---------|
| `mongodb` | `mongo:7.0` | `accessible-video-mongodb` | Primary database |
| `redis` | `redis:7-alpine` | `accessible-video-redis` | Celery broker + result backend |
| `api` | `./backend` (target: `api`) | `accessible-video-api` | FastAPI REST + WebSocket |
| `worker` | `./backend` (target: `worker`) | `accessible-video-worker` | Celery: default, ingest, notify, render queues |
| `tts-worker` | `./backend` (target: `worker`) | `accessible-video-tts-worker` | Celery: tts queue |
| `ffmpeg-worker` | `./backend` (target: `worker`) | `accessible-video-ffmpeg-worker` | Celery: ffmpeg queue |
| `whisper-worker` | `./backend` (target: `whisper-worker`) | `accessible-video-whisper-worker` | Celery: whisper queue |
---
## Port Allocation
| Service | Internal Port | External Port | Notes |
|---------|--------------|---------------|-------|
| `api` | 8000 | **8012** | Exposed to host |
| `mongodb` | 27017 | — | Internal only |
| `redis` | 6379 | — | Internal only |
| Workers | — | — | No HTTP port |
Production: nginx reverse-proxies `optical-web-1:8012``https://ai-sandbox.oliver.solutions/video-accessibility-back`.
---
## Worker Configuration
| Worker | Celery Queues | Concurrency | Memory Limit | Notes |
|--------|--------------|-------------|--------------|-------|
| `worker` | `default, ingest, notify, render` | `${WORKER_CONCURRENCY:-8}` | — | General pipeline |
| `tts-worker` | `tts` | `${TTS_WORKER_CONCURRENCY:-2}` | — | Configurable via env |
| `ffmpeg-worker` | `ffmpeg` | `${FFMPEG_WORKER_CONCURRENCY:-1}` | — | CPU-bound; 1 local, higher in Cloud Run mode |
| `whisper-worker` | `whisper` | `${WHISPER_WORKER_CONCURRENCY:-1}` | **8 GB** (4 GB reserved) | RAM-bound; Whisper large-v3 needs ~46 GB |
Cloud Run offload: when `FFMPEG_SERVICE_URL` or `WHISPER_SERVICE_URL` are set, the respective workers delegate to Cloud Run HTTP endpoints instead of running locally.
---
## Volumes
| Volume Name | Mounted In | Purpose |
|-------------|-----------|---------|
| `accessible-video-mongodb-data` | mongodb `/data/db` | MongoDB data |
| `accessible-video-mongodb-config` | mongodb `/data/configdb` | MongoDB config |
| `accessible-video-redis-data` | redis `/data` | Redis AOF persistence |
| `accessible-video-api-logs` | api `/app/logs` | API log files |
| `accessible-video-worker-logs` | worker `/app/logs` | Worker log files |
| `accessible-video-tts-worker-logs` | tts-worker `/app/logs` | TTS worker logs |
| `accessible-video-ffmpeg-worker-logs` | ffmpeg-worker `/app/logs` | FFmpeg worker logs |
| `accessible-video-whisper-worker-logs` | whisper-worker `/app/logs` | Whisper worker logs |
| `accessible-video-shared-tmp` | worker, tts/ffmpeg/whisper workers `/shared-tmp` | Shared temp dir for FFmpeg operations |
| `./secrets` (bind mount) | all services `/secrets:ro` | GCP credentials JSON |
---
## External Dependencies
| Service | Purpose | Config Key |
|---------|---------|------------|
| Google Cloud Storage | Video files, VTT, MP3, rendered video | `GCS_BUCKET`, `GOOGLE_APPLICATION_CREDENTIALS` |
| MongoDB Atlas | Production database (can also run local container) | `MONGODB_URI`, `MONGODB_DB` |
| Gemini 2.5 Pro | VTT generation, translation | `GEMINI_API_KEY` |
| Google Cloud Translate | Language translation | `TRANSLATE_API_KEY` |
| Google Cloud TTS | Audio description synthesis | `GOOGLE_TTS_CREDENTIALS` |
| ElevenLabs | Premium TTS synthesis | `ELEVENLABS_API_KEY` |
| SendGrid | Transactional email (notifications, delivery) | `SENDGRID_API_KEY` |
| Azure AD / Microsoft MSAL | SSO authentication | `AZURE_CLIENT_ID`, `AZURE_AUTHORITY`, `AZURE_REDIRECT_URI` |
| Sentry | Error tracking and alerting | `SENTRY_DSN` |
| OpenTelemetry / OTLP | Distributed tracing | `OTEL_EXPORTER_OTLP_ENDPOINT` |
| AI Cost Tracker | Cross-project AI cost tracking (optical-dev) | `COST_TRACKER_BASE_URL`, `COST_TRACKER_API_KEY` |
| Google Cloud Run (optional) | Offload FFmpeg and Whisper workloads | `FFMPEG_SERVICE_URL`, `WHISPER_SERVICE_URL` |
---
## Health Checks
| Service | Check | Interval |
|---------|-------|---------|
| `mongodb` | TCP port 27017 check | 60s (10s timeout, 3 retries) |
| `redis` | `redis-cli ping` | 30s (10s timeout, 3 retries) |
| `api` | Depends on mongodb + redis healthy | — |
| Workers | Depend on mongodb + redis healthy | — |
Admin health endpoint: `GET /api/v1/admin/health/detailed` (requires admin Bearer token).
---
## Redis Configuration
```text
maxmemory 2gb
maxmemory-policy allkeys-lru
appendonly yes
```
---
## Log Rotation
All services use Docker `json-file` logging:
```text
max-size: 10m
max-file: 3
```
---
## Maintenance
**Last Updated:** 2026-05-01
**Update Triggers:**
- New service added to `docker-compose.yml`
- Port mapping changes
- New external dependency added
- Worker queue or concurrency configuration changes
**Verification:**
- [ ] All services in `docker-compose.yml` listed
- [ ] Port table matches `ports:` sections in compose file
- [ ] External dependencies match env vars in `.env.example`
- [ ] Volume names match `volumes:` section in compose file