---
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)