164 lines
7.6 KiB
Markdown
164 lines
7.6 KiB
Markdown
---
|
|
title: "Client Knowledge: Barclays"
|
|
description: "Barclays-specific context: projects, tech constraints, deployment quirks, and lessons learned"
|
|
tags: [client-knowledge, barclays]
|
|
created: 2026-04-27
|
|
updated: 2026-04-28
|
|
---
|
|
|
|
# Client Knowledge: Barclays
|
|
|
|
## Key Takeaways
|
|
|
|
- Two active projects: Mod Comms (GCP, multi-agent AI) and Banner Builder (optical-dev, React+FastAPI)
|
|
- Barclays requires strict brand compliance — logo versions matter, Barclays design tokens used in UI
|
|
- GCP deployment = no WebSockets — REST polling is mandatory for Mod Comms
|
|
- Banner Builder uses Zustand for workflow state management (journey store pattern)
|
|
|
|
---
|
|
|
|
## Projects
|
|
|
|
| Project | Server | Stack | Status | Purpose |
|
|
|---------|--------|-------|--------|---------|
|
|
| [[01 Projects/modcomms/Mod Comms\|Mod Comms]] | GCP | FastAPI + React + Gemini + PostgreSQL | active | AI proof review — compliance/brand/tone/channel checks |
|
|
| [[01 Projects/Barclays-banner-builder/Barclays Banner Builder\|Banner Builder]] | optical-dev | FastAPI + React + PostgreSQL + Docker | active | AI banner generation tool — Brief → Variants → Edit → Export |
|
|
|
|
---
|
|
|
|
## Mod Comms — Key Facts
|
|
|
|
**What it does:** Upload proof (image/PDF) → 4 AI agents analyze in parallel → lead agent synthesizes verdict
|
|
|
|
**4 agents:** Legal compliance, Brand adherence, Tone of Voice, Channel suitability
|
|
|
|
**AI:** Google Gemini Pro (primary) + Flash (fallback) — chosen for GCP co-location
|
|
|
|
**Critical incident (2026-03-18):** WebSocket connections dropped at 30s on GCP LB → switched to REST polling. See [[wiki/architecture/gcp-deployment-lb-timeout|gcp-deployment-lb-timeout]].
|
|
|
|
**Auth:** Azure AD (MSAL) — uses `DISABLE_AUTH=true` locally
|
|
|
|
**Dev start:**
|
|
```bash
|
|
# Backend
|
|
cd backend && uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
|
|
|
# Frontend
|
|
cd frontend && npm install && npm run dev
|
|
|
|
# DB migrations
|
|
cd backend && alembic upgrade head
|
|
```
|
|
|
|
**Env vars (backend):**
|
|
```
|
|
GEMINI_API_KEY=
|
|
DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/modcomms
|
|
AZURE_TENANT_ID=
|
|
AZURE_CLIENT_ID=
|
|
DISABLE_AUTH=true
|
|
```
|
|
|
|
---
|
|
|
|
## Banner Builder — Key Facts
|
|
|
|
**What it does:** AI-assisted banner creation. Workflow: Brief → Edit Variants → Banner Editor → Export CSV/PDF
|
|
|
|
**Workflow state:** Managed with Zustand `journey store` — backward navigation allowed, forward steps grayed out until completed. See [[wiki/concepts/export-endpoint-filter-pattern|export-endpoint-filter-pattern]].
|
|
|
|
**Export quirk:** PDF/CSV exports must receive `variant_ids` from frontend — backend cannot infer selection. Always pass explicitly.
|
|
|
|
**Deploy:** optical-dev at `/barclays-banner-builder/` subpath. Deploy via `bash deploy.sh` on server.
|
|
|
|
**Apache config:** Barclays Include fragment at `/opt/barclays-banner-builder/deploy/apache-barclays.conf`. Port: 8010.
|
|
|
|
**Critical incident (2026-04-17):** Apache Include directive ordering — Banner Builder's conf was loading after hp-prod-tracker's catch-all `ProxyPass / http://...`, which intercepted all requests. Fixed by reordering Include lines in vhost config.
|
|
|
|
**Stack:**
|
|
- Frontend: React + TypeScript + Vite + Zustand
|
|
- Backend: FastAPI + Python + Alembic + PostgreSQL
|
|
- Auth: Azure AD (MSAL)
|
|
- Deploy: Docker Compose + Apache subpath
|
|
|
|
---
|
|
|
|
## Brand Requirements
|
|
|
|
- Logo versions matter — track which version is active (`v4`, `v5`, `v6`)
|
|
- Barclays design tokens used in UI (Zustand journey stepper used Barclays color tokens)
|
|
- Export outputs go to OMG media booking system — format must be exact
|
|
|
|
---
|
|
|
|
## Banner Builder UI Rebrand (2026-04-28)
|
|
|
|
The banner builder UI was rebranded from the Barclays design system to the **Oliver Modcomms design system**. Visual layer changed; core functionality unchanged.
|
|
|
|
**What changed:**
|
|
- Tailwind tokens renamed from `barclays-*` → `oliver-*`
|
|
- Layout: horizontal nav → dark vertical sidebar (`w-[220px]`), matching the Modcomms pattern
|
|
- Theme colour picker added to both `BannerEditor` and `VariantsGrid` views; variants have a `theme` enum: `navy | sky-blue | yellow | lime | teal`
|
|
- Logo: placeholder `CopyGenBannerAgent_RFA.png` generated via `sips` (PIL not available on macOS); real CopyGen/Oliver asset needed
|
|
|
|
**What did NOT change (by design):**
|
|
- Internal localStorage key names (`barclays-*`) intentionally kept to avoid invalidating in-flight user sessions — see [[wiki/concepts/localstorage-key-migration-rebrand|localstorage-key-migration-rebrand]] for why and how to handle this in a future release
|
|
- AI Refine/Improve box only mutates copy text fields — cannot change visual theme/colours (by architecture)
|
|
- Barclays brand hex codes (`#00AEEF`, `#00395D`, etc.) remain correct in `tailwind.config.ts` as of commit `47b3f12`
|
|
|
|
---
|
|
|
|
---
|
|
|
|
## Lessons from banner-builder (2026-04-28)
|
|
|
|
QA session on barclays-banner-builder surfaced three non-obvious bugs. All three share a common trait: they fail silently rather than throwing a clear error.
|
|
|
|
### DB Seed Silent Skip
|
|
|
|
Seed scripts using `INSERT IF NOT EXISTS` or `get_or_create` silently skip existing rows. If a test/demo user was created before the seed ran (e.g., with a different password), the seed never updates it. Auth fails at login with no error in logs — the user row simply has the wrong password.
|
|
|
|
**Fix:** Always verify actual DB state when auth fails unexpectedly after seeding:
|
|
```sql
|
|
SELECT email, created_at FROM users WHERE email = 'seed@example.com';
|
|
-- If it exists with old data, DELETE and re-run seed, or UPDATE manually
|
|
```
|
|
|
|
### Zustand Async Hydration Bug
|
|
|
|
`ConversationLanding` fired an API call on mount before the Zustand auth store had hydrated from localStorage. On first render, `token` was `null` (initial state) → API call sent without auth header → 401 → redirect to login, even though the user was logged in.
|
|
|
|
**Fix:** Gate all auth-dependent API calls behind `hasHydrated`:
|
|
```typescript
|
|
const { token, hasHydrated } = useAuthStore()
|
|
useEffect(() => {
|
|
if (!hasHydrated) return
|
|
fetchData()
|
|
}, [hasHydrated, token])
|
|
```
|
|
|
|
See [[wiki/concepts/zustand-async-hydration]] for full pattern.
|
|
|
|
### Pydantic Model/Dict Interface Bug in tasks.py
|
|
|
|
`refine_variant_copy` Celery task was written to accept a `dict` but was called with a `BannerCopy` Pydantic model. Every `.get("field")` call on the Pydantic object returned `None` silently — the task continued running with all-null inputs, hanging the AI refinement pipeline without raising an exception.
|
|
|
|
**Fix:** Convert at call site: `task.delay(banner_copy.model_dump(), ...)` or update the function to accept the Pydantic model directly.
|
|
|
|
See [[wiki/concepts/pydantic-model-dict-interface]] for full pattern.
|
|
|
|
### LoginPage Hardcoded Redirect
|
|
|
|
`LoginPage` had a hardcoded redirect to `/brief` instead of `/` in the auth success handler. This caused the entire post-login flow to break for users who should land on the home route. Always use a configurable redirect target (e.g., `location.state?.from` or a constant) rather than a hardcoded path.
|
|
|
|
---
|
|
|
|
## Related
|
|
|
|
- [[wiki/architecture/gcp-deployment-lb-timeout|gcp-deployment-lb-timeout]] — WebSocket → REST polling
|
|
- [[wiki/architecture/optical-dev-server-deploy|optical-dev-server-deploy]] — Banner Builder deployment
|
|
- [[wiki/tech-patterns/python-ai-agents|python-ai-agents]] — multi-agent pattern used in Mod Comms
|
|
- [[wiki/concepts/export-endpoint-filter-pattern|export-endpoint-filter-pattern]] — variant_ids in exports
|
|
- [[wiki/concepts/zustand-async-hydration]] — Zustand hydration timing bug (Banner Builder)
|
|
- [[wiki/concepts/pydantic-model-dict-interface]] — Pydantic vs dict silent failure (Banner Builder tasks.py)
|
|
- [[wiki/concepts/localstorage-key-migration-rebrand]] — localStorage key migration after rebrand (Banner Builder 2026-04-28)
|