--- name: "Mod Comms" client: Barclays status: active tech: [React, TypeScript, FastAPI, Python, PostgreSQL, Docker, Google Gemini, Alembic] local_path: /Users/ai_leed/Documents/Projects/Oliver/modcomms deploy: ./deploy.sh url: https://baic.oliver.solutions/modcomms/ server: baic tags: [barclays, ai, compliance, proof-review, multi-agent, gcp] created: 2026-04-14 last_commit: 2026-05-14 commits: 208 port: 8000 db: PostgreSQL --- ## Overview ModComms is an AI-powered marketing proof review tool built by OLIVER Agency (BAIC team) for Barclays and Barclaycard. Users upload marketing assets (images, PDFs) and a five-agent AI system analyzes each proof in parallel for legal compliance, brand adherence, tone of voice, and channel suitability. Results return as Red/Amber/Green (RAG) verdicts with actionable feedback within seconds. The system is live in production and serves as internal tooling for Barclays' compliance and marketing teams. ## Tech Stack - **Frontend:** React 18+ with TypeScript, Vite, MSAL (Azure AD auth) - **Backend:** FastAPI with Python 3.12+, Uvicorn, asyncio - **Database:** PostgreSQL 16 (Alpine Docker image) - **Infrastructure:** Docker Compose, Apache HTTP Server (reverse proxy), Linux - **AI/ML:** Google Gemini 2.5 Pro (primary), Gemini 2.5 Flash (fallback), LlamaParse for KB ingestion - **Key libraries:** SQLAlchemy async ORM, Alembic migrations, PyMuPDF (PDF rasterization), Pydantic, python-multipart ## Architecture ModComms uses a **multi-agent parallel pipeline** with REST polling (replaced WebSocket to fix GCP load balancer 30s timeout). The frontend is a React SPA served by Apache; the backend is a FastAPI service in Docker that orchestrates four specialist AI agents (Legal, Brand, ChannelBestPractices, ChannelTechSpecs) concurrently, then synthesizes results via a Lead Agent. **Data flow:** 1. User uploads file → frontend base64-encodes → POST `/api/analyze` 2. Backend creates job ID, returns immediately, spawns asyncio background task 3. `_run_analysis()` loads reference docs (brand guidelines, channel specs), deduplicates via MD5 hash 4. Four agents call Gemini 2.5 Pro concurrently (each builds system prompt + reference context) 5. Lead Agent combines four SubReviews into single overallStatus (Passed/Failed/Requires Manual Legal Review) 6. File stored to `/app/storage` volume, thumbnail generated, proof_version inserted to PostgreSQL 7. Frontend polls `/api/jobs/{job_id}` until complete **Model fallback:** Rate limits trigger automatic retry with Gemini 2.5 Flash; sets `job.model_fallback = true`. **Timeout:** Hard 300-second limit per analysis. ``` Browser (React SPA) ↓ HTTPS/REST polling Apache (baic.oliver.solutions) ├─ /modcomms/ → frontend/dist/ └─ /back/ → proxy to :8000 ↓ FastAPI Backend (Docker :8000) ├─ Auth (Azure AD JWT) ├─ /api/analyze, /api/jobs, /api/campaigns, /api/proofs, /api/knowledge-base, /api/export ├─ asyncio agents: │ ├─ LegalAgent → Gemini 2.5 Pro │ ├─ BrandAgent → Gemini 2.5 Pro │ ├─ ChannelBestPracticesAgent → Gemini 2.5 Pro │ ├─ ChannelTechSpecsAgent → Gemini 2.5 Pro │ └─ LeadAgent (synthesis) └─ Services: ├─ AnalysisService (orchestration) ├─ ReferenceDocsService (brand/channel KB) ├─ KnowledgeBaseService (LlamaParse + distillation) ├─ StorageService (/app/storage) └─ PDFService (PyMuPDF render) ↓ PostgreSQL (Docker :5432) └─ 12 tables: campaigns, proofs, proof_versions, users, flagged_items, etc. ``` ## Dev Commands ```bash # Clone repo git clone git@bitbucket.org:zlalani/modcomms.git cd modcomms # Backend setup cd backend cp .env.example .env # Edit .env: set GEMINI_API_KEY, DISABLE_AUTH=true python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate pip install -r requirements.txt # Start PostgreSQL (Docker) docker compose up -d postgres # Run migrations alembic upgrade head # Start backend uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 # Check health: curl http://localhost:8000/health # Frontend setup (new terminal) cd frontend npm install # Create .env.local cat > .env.local << 'EOF' VITE_BACKEND_URL=http://localhost:8000 VITE_AZURE_CLIENT_ID=your_client_id VITE_AZURE_TENANT_ID=your_tenant_id VITE_AZURE_REDIRECT_URI=http://localhost:3000/ EOF npm run dev # Frontend at http://localhost:3000 # Build frontend for production npm run build ``` ## Deployment - **Server:** baic.oliver.solutions (Apache + Docker Compose) - **Deploy:** `./deploy.sh` (full pipeline: git pull → npm build → Docker build → migrations → restart) - **URL:** https://baic.oliver.solutions/modcomms/ (frontend), https://baic.oliver.solutions/back/ (backend) - **Port:** 8000 (backend container, proxied via Apache) - **Service:** Docker Compose (no systemd service) - **Local path:** /Users/ai_leed/Documents/Projects/Oliver/modcomms **Deploy process** (on server): 1. Copy `.env.deploy.example` → `.env.deploy`, fill secrets (GEMINI_API_KEY, Azure tenant/client IDs, DB passwords) 2. Run `./deploy.sh` - `git pull` - `npm install && npm run build` in frontend - Copy `frontend/dist/` to `/var/vhosts/baic.oliver.solutions/htdocs/modcomms` - `docker compose build` backend - Start PostgreSQL container - `alembic upgrade head` (migrations) - `docker compose up -d --force-recreate backend` - Wait for `/health` 200 response **Alternative (dev server):** `./deploy-dev.sh` (uses `sudo docker`, fixes dist permissions) ## Environment Variables **Backend (`backend/.env`)** - `GEMINI_API_KEY` — Google Gemini API key (required) - `DATABASE_URL` — PostgreSQL async connection string; default: `postgresql+asyncpg://modcomms:modcomms_dev@localhost:5432/modcomms` - `AZURE_TENANT_ID` — Azure AD tenant ID (required in production) - `AZURE_CLIENT_ID` — Azure AD app registration ID (required in production) - `DISABLE_AUTH` — Set `true` to skip JWT validation (local dev only); default: `false` - `CORS_ORIGINS` — Comma-separated allowed origins; default: `http://localhost:3000` - `HOST` — Server bind address; default: `0.0.0.0` - `PORT` — Server port; default: `8000` - `REFERENCE_DOCS_PATH` — Path to brand/channel guideline documents (local or DB) **Docker Compose (`.env`)** - `POSTGRES_USER` — default: `modcomms` - `POSTGRES_PASSWORD` — default: `modcomms_dev` - `POSTGRES_DB` — default: `modcomms` - `BACKEND_PORT` — host port for backend container; default: `8000` - `POSTGRES_PORT` — host port for PostgreSQL; default: `5432` **Frontend (`frontend/.env.local`)** - `VITE_BACKEND_URL` — Backend API URL; default: `http://localhost:8000` - `VITE_AZURE_CLIENT_ID` — Azure AD client ID - `VITE_AZURE_TENANT_ID` — Azure AD tenant ID - `VITE_AZURE_REDIRECT_URI` — Auth redirect; default: `http://localhost:3000/` ## API Endpoints **Analysis workflow** - `POST /api/analyze` — Submit proof for analysis; returns `{ job_id, status }` - `GET /api/jobs/{job_id}` — Poll analysis status; returns full ProofVersion when complete - `GET /api/jobs` — List all jobs (paginated) **Campaign & proof management** - `GET /api/campaigns` — List campaigns (user's org) - `POST /api/campaigns` — Create campaign - `GET /api/campaigns/{campaign_id}/proofs` — List proofs in campaign - `GET /api/proofs/{proof_id}` — Get proof and all versions - `GET /api/proofs/{proof_id}/versions/{version_id}` — Get specific version **Knowledge base** - `POST /api/knowledge-base/upload` — Upload KB document (LlamaParse ingestion) - `GET /api/knowledge-base` — List knowledge base documents - `DELETE /api/knowledge-base/{kb_id}` — Remove KB document **Export** - `GET /api/export/campaign/{campaign_id}/csv` — Export campaign data as CSV (super_admin, oversight_admin only) **Health** - `GET /health` — Unauthenticated health check ## Known Issues - **WebSocket timeout (resolved):** Replaced WebSocket with REST polling to fix G ## Timeline / Git History | Date | Change | |------|--------| | 2026-05-14 | Rename Legal Agent to Risk & Control Agent across frontend and backend | | 2026-04-15 | Replace logo SVG with PNG v6 in Sidebar and PDF Report | | 2026-04-15 | Add deploy-dev.sh for dev server (sudo docker, fix dist permissions) | | 2026-04-14 | Replace logo with v6 SVG across Sidebar and PDF Report | | 2026-03-19 | Add CSV export of campaign data for super_admin and oversight_admin | | 2026-03-18 | **Critical:** Switch WebSocket → REST polling (GCP LB 30s timeout fix) | | 2026-03-18 | Switch AI model: Pro primary, Flash fallback | | 2026-03-18 | Fix WebSocket keepalive + 25s→10s heartbeat | | 2026-03-16 | Fix PDF logo URL with Vite base path in production | | 2026-03-16 | Fix LlamaParse 401 + update logo to v5 | ## Sessions ### 2026-05-14 – Added grey placeholder text to Workfront **Asked:** Added grey placeholder text to Workfront Campaign ID field in Create New Campaign modal showing "WF1234567" format without hashtag/underscores and removed validation warning. **Done:** Placeholder text implemented and validation warning removed from modal component. ### 2026-05-14 – Asked | Show grey placeholder text **Asked:** Asked | Show grey placeholder text for Workfront Campaign ID field and remove validation warning **Done:** Done | Removed error validation logic, updated placeholder text to "WF1234567", and cleaned up unused error state declaration ### 2026-05-14 – Fix 500 error and document processing **Asked:** Fix 500 error and document processing failure on modcomms knowledge base. **Done:** Debugged and resolved server-side issue preventing document uploads from being processed. ### 2026-05-14 – Rename "Legal Agent" to "Risk & **Asked:** Rename "Legal Agent" to "Risk & Control Agent" across three production locations **Done:** Deployed changes to baic server after syncing 3 commits behind ### 2026-05-14 – Rename "Legal Agent" to "Risk & **Asked:** Rename "Legal Agent" to "Risk & Control Agent" across production application | Updated frontend display labels in multiple components and backend agent configuration with new name and dictionary keys | PDFReport.tsx, FeedbackReport.tsx, Projects.tsx, Campaigns.tsx, StatusDashboard.tsx, ChecksOverview.tsx, Analytics.tsx, constants.ts, types.ts, legal_agent.py, lead_agent.py **Done:** — ### 2026-04-15 – Replace logo with file from /Volumes/SSD/Downloads/BAR-ModComms-logos-v6.png **Asked:** Replace logo with file from /Volumes/SSD/Downloads/BAR-ModComms-logos-v6.png and set up server deployment process. **Done:** Created deploy-dev.sh script with dev-specific configurations (sudo docker compose, port 8001, dev project name) and successfully deployed changes. ### 2026-04-14 – Project catalogued **Done:** Added to Obsidian second brain with full details from CLAUDE.md and git history. --- ## Change Log | Date | Requested | Changed | Files | |------|-----------|---------|-------| | 2026-05-14 | Environment variable fix | Docker compose restart with --force-recreate, form submission handling | docker-compose.yml, .env | | 2026-05-14 | Docker container restart issue | Applied force-recreate flag to reload env_file, verified container key | docker-compose.yml, .env file | | 2026-05-14 | Ask a Question form | Form submission routing, .env.deploy.example values | .env.deploy.example, backend form handler | | 2026-05-14 | Profile question submission bug | Fix submission logic, update environment config | server files, .env.deploy.example | | 2026-05-14 | Profile questions submission | Mailgun domain placeholder fix, .env.deploy update, backend restart | backend/.env, .env.deploy | | 2026-05-14 | Logo update | Added Mailgun credentials to .env.deploy, updated .env.deploy.example | .env.deploy, .env.deploy.example | | 2026-05-14 | Campaign ID placeholder | Grey placeholder text format, validation warning removed | CreateNewCampaignModal.tsx | | 2026-05-14 | Create New Campaign modal | Remove validation function, remove error state, update placeholder text | CreateNewCampaignModal.tsx | | 2026-05-14 | Debugging Wizard skill | Server configuration, error handling, document processor | modcomms backend files, server logs | | 2026-05-14 | Rename Legal Agent | Text labels in PDF export, Campaign page, Knowledgebase | PDFExport.tsx, CampaignPage.tsx, Knowledgebase.tsx | | 2026-04-15 | Logo replacement, deployment scripts | Added deploy-dev.sh with sudo docker compose and dev port 8001, configured git pull workflow | deploy-dev.sh, deploy.sh | | 2026-04-14 | Logo update | Replace logo with v6 SVG | Sidebar, PDF Report | | 2026-03-18 | Fix dropped connections on GCP | WebSocket → REST polling | backend, frontend | ## Related - [[enterprise-ai-hub-nexus/Enterprise AI Hub Nexus]] (similar AI platform) - [[semblance/Semblance]] (same GCP deployment issues)