Backend - Routes moved under /api/, JWT bearer auth via @before_request - DEV_AUTH_BYPASS escape hatch for local dev - In-memory chat history and report state replaced with Postgres tables (preferences, chat_messages, reports, feedback_events) keyed on user - SQLAlchemy 2.x + Alembic migrations run on container start - Graceful Airtable failure handling — bad creds no longer 500 the API - Per-user data isolation via g.user_email from validated token Frontend - React + Vite + TypeScript SPA at /programme-pulse/ - MSAL.js (PKCE, sessionStorage, ID token to backend) - VITE_DEV_AUTH_BYPASS mirrors backend bypass for local dev - Streaming chat via fetch ReadableStream + SSE parsing - Charts via chart.js, markdown via react-markdown + remark-gfm - Full UI parity with the original templates/index.html Deploy (optical-dev split-build pattern) - Dockerfile + docker-compose.yml (name: programme-pulse pinned; app + Postgres; 127.0.0.1 binding only) - deploy/apache-programme-pulse.conf.tmpl with flushpackets=on for SSE - deploy/deploy.sh mirrors OSOP — port auto-pick (5051..5099), apache conf render, frontend build in throwaway node container, rsync to /var/www/html/programme-pulse, /api/health poll Tests - 49 passing; new tests for DB-backed preferences and JWT auth helpers - SQLite-backed test fixture in tests/conftest.py Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
43 lines
1.3 KiB
YAML
43 lines
1.3 KiB
YAML
# Top-level project name pinned per global Docker policy — without this, the
|
|
# compose file (when run from /opt/programme-pulse via deploy.sh) would default
|
|
# to project name "programme-pulse" anyway, but pinning it is explicit and
|
|
# survives if the file ever moves under deploy/.
|
|
name: programme-pulse
|
|
|
|
services:
|
|
app:
|
|
build: .
|
|
restart: unless-stopped
|
|
ports:
|
|
# Bind only to loopback — Apache fronts the container.
|
|
- "127.0.0.1:${PROGRAMME_PULSE_PORT:-5051}:5051"
|
|
environment:
|
|
- PORT=5051
|
|
- DATABASE_URL=postgresql+psycopg://${POSTGRES_USER:-pulse}:${POSTGRES_PASSWORD:-pulse}@db:5432/${POSTGRES_DB:-pulse}
|
|
env_file:
|
|
- .env
|
|
volumes:
|
|
- ./reports:/app/reports
|
|
- ./docs/Programme Pulse transcripts:/app/docs/Programme Pulse transcripts:ro
|
|
- ./logs:/app/logs
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
|
|
db:
|
|
image: postgres:16-alpine
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_USER: ${POSTGRES_USER:-pulse}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-pulse}
|
|
POSTGRES_DB: ${POSTGRES_DB:-pulse}
|
|
volumes:
|
|
- pgdata:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-pulse} -d ${POSTGRES_DB:-pulse}"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 12
|
|
|
|
volumes:
|
|
pgdata:
|