New GET /analytics/by-agency endpoint groups review metrics by agency.
The Analytics page now shows a sortable agency performance table with
pass rates, failures, errors, and legal review counts for each agency.
Only visible to super_admin and oversight_admin users. Selected agency
row is highlighted when the AgencyFilterBar is active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backend: Expose created_by field on CampaignResponse schema and all
response constructors in routes.py
- Frontend API layer: Add created_by to CampaignResponse interface and
createdBy to the frontend campaign converter
- Campaign list: Add column sorting (click headers to toggle asc/desc),
per-column text filter inputs below headers, and a "My Campaigns Only"
toggle that filters to campaigns created by the current user
- Default sort is lastModified descending to match existing behavior
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a user_change_logs table to track all role and agency changes made
to users by super admins. Includes a change history modal in the User
Management screen (clock icon per row) showing timestamped, human-readable
change descriptions with the actor who made each change.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add CHECK constraint migration for users.role (super_admin, oversight_admin, agency_admin, basic_user)
- Add get_current_db_user dependency resolving Azure claims to User ORM with agency
- Add require_role() factory and require_write_access() dependency
- Auto-promote dev user to super_admin when DISABLE_AUTH=true
- Add /api/me, PUT /api/users/{id}, POST /api/agencies endpoints
- Apply agency-based data filtering on campaigns, analytics, audit routes
- Block oversight_admin from all mutation routes (campaigns, proofs, flags, resolves)
- Restrict dropdown option mutations to super_admin only
- Add role check in WebSocket handler to block oversight_admin from analysis
- Add CurrentUserResponse, UserUpdate, AgencyCreate schemas
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove proof_version_id from FlaggedItemCreate and ResolvedItemCreate
request schemas — the backend already derives it from URL path params.
The frontend was sending an empty string which caused Pydantic to reject
the request with 422, silently preventing flags/resolves from saving.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create ErrorItem record when proof analysis results in "Analysis Error" status
- Add submitter_name/submitter_agency fields to ErrorItemResponse schema
- Eager-load proof creator and agency in error items query to avoid N+1
- Populate submitter fields from proof creator in the API route
- Update frontend ErrorItemResponse type and conversion to map submitter fields
- Fix ErrorsTable proof name styling to blue link (text-active-blue) matching Flags tab
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add file_hash and is_identical_file columns to proof_versions table
- Compute MD5 hash on file upload and compare with previous version
- Display warning banner when uploading identical file as revision
- Return is_identical_file in WebSocket response and API endpoints
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend:
- Add email_service.py with Mailgun API integration
- Add SupportEmailRequest schema for email endpoint
- Add Mailgun config settings (API URL, key, from address, support email)
- Update .env.example with Mailgun configuration variables
Frontend:
- Update Login.tsx SupportModal to send emails via /api/support/email
- Update Profile.tsx question form to send emails via apiService
- Add loading states, success/error feedback, and auto-close on success
The support forms on both the login page and profile page now actually
send emails to the support team instead of just showing alerts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend:
- Update migration to seed agencies (OLIVER Agency, Barclays, etc.)
- Seed brand guidelines (Barclays, Barclaycard) in dropdown_options
- Seed channel/sub-channel/proof-type hierarchy
- Add /api/agencies endpoint to list all agencies
- Update DropdownOptionsResponse to include brand_guidelines
- Update dropdown repository to return brand guidelines
Frontend:
- Update DropdownOptions interface to include brandGuidelines
- CreateCampaignModal now receives brand guidelines from API
- Settings UsersTab fetches agencies from API instead of hardcoded list
- Add getAgencies() method to apiService
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend:
- Add PostgreSQL service to docker-compose with health checks
- Add SQLAlchemy async models for all entities (Agency, User, Campaign,
Proof, ProofVersion, FlaggedItem, ResolvedItem, ErrorItem)
- Add Alembic migration framework with initial schema migration
- Add repository layer for CRUD operations
- Add REST API endpoints for campaigns, proofs, and audit items
- Add file storage service for proof uploads
- Update WebSocket handler to optionally persist analysis results
Frontend:
- Add apiService.ts for REST API communication
- Update geminiService.ts to support database persistence options
Deployment:
- Update deploy.sh to handle database migrations (6-step process)
- Update Dockerfile to include alembic configuration
- Add PostgreSQL environment variables to .env templates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>