Commit graph

43 commits

Author SHA1 Message Date
nickviljoen
bf89466d06 feat(settings): default-profile UI per client (admin-only) for Box webhook flow
Adds a "Default Profile" sub-tab to the Settings modal. Lists the
current client's profiles as radio buttons, shows which is the active
default and whether it's a runtime override or the static value from
client_config.py. Admins click a different profile + Set to override;
clear-override button reverts to the static value.

Storage layer: backend/client_defaults.json (gitignored, per-server),
following the same pattern as user_access.json. Resolution order in
client_config.get_default_profile(): override → static
default_profile field → None. The Box webhook handler is the sole
consumer that needs profile selection without a logged-in user; it
now reads via get_default_profile() so overrides take effect.

Why a separate JSON, not rewriting client_config.py: a buggy override
write can never break server boot — worst case the override is
ignored and the static value applies. Cleaner separation between
"static config you check in" and "runtime overrides admins make".

Backend:
- client_config.get_default_profile(client_id) — resolver
- client_config.set_default_profile(client_id, profile_id) — validates
  + writes (rejects profiles not in client's profile list)
- client_config.clear_default_profile_override(client_id)
- GET /api/clients/<id>/default_profile (any auth'd user)
- PUT /api/clients/<id>/default_profile (admin-only, _require_admin)
- DELETE /api/clients/<id>/default_profile (admin-only)
- Box webhook handler in api_server.py now uses get_default_profile()

Frontend:
- New "Default Profile" tab button + tab content in Settings modal
- showTab hook loads settings when tab activates
- loadDefaultProfileSettings / saveDefaultProfile /
  clearDefaultProfileOverride functions
- DOM-construction (createElement + textContent) used throughout —
  no innerHTML with interpolated values, so user-controllable
  strings (client_id, profile_id) can never cause XSS

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 13:50:20 +02:00
nickviljoen
90563b8cf2 Add AXA document-mode QC pipeline (Phases 1, 3, 4, 5)
Multi-page PDF QC for AXA Ireland policy documents. Runs as a third mode
alongside static + video, gated on profile.mode. New code isolated under
backend/document_mode/ with new endpoints under /api/document/*.

Phase 1 — Spine + 6 deterministic doc-scope checks ($0, runs in seconds):
- Scope-aware dispatcher (document/targeted/page_sample/page_pair/page_each)
- axa_font_inventory, axa_phone_inventory, axa_bold_words_definitions,
  axa_page_numbering, axa_print_code, axa_omg_versioning
- Bootstrap bold-words dictionary extracted from Example 1 General Definitions

Phase 3 — Old-vs-new diff (~$0.50/run, 3-5 min):
- Page alignment via difflib SequenceMatcher (windowed fuzzy match)
- Vision-LLM page-pair diff via Gemini 2.5 Pro (8 concurrent)
- Two-slot upload UX, axa_policy_document_diff profile, mode=document_diff

Phase 4 — PDF accessibility (PyMuPDF, $0):
- 9 PDF/UA-1 aligned criteria (tagged structure, /MarkInfo, title, /Lang,
  encryption, font embedding, PDF version, XMP UA-conformance, alt-text)
- _run_verapdf() stub for optional Java-based veraPDF integration later

Phase 5 — Print preflight (PyMuPDF, $0):
- 7 criteria (page geometry, bleed, image colour spaces, image DPI,
  transparency, PDF/X conformance, spot colours)

Profile additions:
- axa_policy_document — 8 deterministic checks, $0 cost
- axa_policy_document_diff — 1 page-pair LLM check, ~$0.50/run

API additions:
- POST /api/document/start_analysis (single PDF)
- POST /api/document/start_diff (old + new PDFs)

Frontend additions:
- Third profile.mode value (document_diff) in applyProfileMode()
- Two-slot upload UX with PDF-only file pickers
- checkFormValidity() branches by mode for the analyse-button gate

Smoke-tested locally against Example 1 (Home Insurance V8, 86pp) and
Example 2 (Landlord V1 vs V10, 68→74pp) with real findings caught
including bold-words gaps, missing PDF/UA flag, transparency on press,
V1→V10 bold-formatting fixes. Plan + integration map + gotchas in
backend/AXA_DOCUMENT_MODE_PLAN.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 18:38:14 +02:00
nickviljoen
125c5e7064 Simplify settings UX and add client access request flow
Settings panel:
- Reference Assets tab: collapse the Brand Name + Tags + Description form to a single Name field; the user-entered name now drives the dropdown label on the main configuration page (falls back to filename for legacy records).
- Media Plan tab: add a Name field. Backend stores display_name on the plan record, and both the active-plan card and the main-page dropdown prefer display_name (falling back to original_filename for old plans).
- Modal footer is now context-aware: Save Profile + Cancel show only on the Profile / Create Profile tabs; Reference Assets / QC Tools / Media Plan show a single green Save button that closes the modal.

Client access request:
- New "Request Client Access" tile on the client picker, alongside the user's existing client tiles. Opens a modal that auto-fills name + email from the MSAL session (read-only), shows checkboxes for clients the user does not already have, and accepts an optional reason.
- New POST /api/access_request endpoint (auth-required) that takes identity from the verified session, validates the requested clients, looks up admin recipients via user_access.list_access_entries, and emails them via the new email_service module (Mailgun SMTP with STARTTLS). Reply-To is set to the requester. Logs an access_request event to the daily JSONL usage logs.
- New GET /api/all_clients endpoint so the form can list clients the requester currently cannot see.
- Mailgun SMTP credentials added to the four env files (and placeholders in the .env.template files) under SMTP_SERVER / SMTP_PORT / SMTP_USER / SMTP_PASSWORD / SENDER_EMAIL / ERROR_EMAIL / REPORT_EMAILS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:02:40 +02:00
nickviljoen
106f361a6d Revert prod-specific MSAL redirect slash strip (v1.0.1)
IT confirmed prod is registered with the trailing-slash form,
matching dev. The v1.0.1 hostname special-case is no longer needed —
both environments can preserve window.location.pathname as-is.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 11:33:16 +02:00
nickviljoen
1e3adfa2b5 Strip trailing slash on MSAL redirect URI for optical-prod
Prod's Azure AD registration uses the no-trailing-slash form while
dev's uses the trailing-slash form. Rather than normalize via
helpdesk, we key the URI shape off the hostname so both environments
match their respective registrations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 22:40:04 +02:00
nickviljoen
f85ba2069f Refresh pricing and surface input/output tokens in reporting
- Update Gemini 2.5 Pro output pricing from $5 to $10 per 1M tokens
  (verified against ai.google.dev on 2026-04-22); OpenAI GPT-4o unchanged.
- Extend /api/client_usage_stats and /api/admin/users to return input
  tokens, output tokens, and per-provider cost breakdown.
- Surface the new data in the client Reporting tab and admin users
  table, with K/M token formatting.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 20:59:41 +02:00
nickviljoen
fee62d0766 Keep trailing slash on MSAL redirect URI for deployed envs
Azure AD has the trailing-slash form registered for the dev
environment. Previously we stripped it, causing AADSTS50011 on
first sign-in. Local dev (localhost) still uses no-path form.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 18:23:31 +02:00
nickviljoen
6592c38b0a Add per-user client access control and admin management
Default-deny access model with admin grant/revoke via new User Access
tab. /api/clients filters by user grants; client-scoped endpoints
enforce access server-side. Admin role and client grants persist in
user_access.json with audit trail in usage logs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 12:33:09 +02:00
nickviljoen
20259dcad0 Add Honda client, video QC, session refresh, Amazon check tuning
- Add Honda client with static_general and video_general profiles
- Add video QC capability using Gemini native video analysis (4 checks:
  visual_quality, brand_consistency, text_legibility, pacing_flow)
- Add video_general profile assigned to all 8 clients
- Extend session lifetime with MSAL silent token refresh (proactive
  every 45min + reactive on expiry), switch cache to localStorage
- Re-enable OCR layout measurements for Amazon checks
- Add scope boundary notes to all 6 Amazon checks to prevent cross-
  check penalization (locale errors isolated to logo_country only)
- Relax margins left-alignment tolerance from 1% to 4% to account
  for logo lockup internal padding
- Update brand guidelines DB with Amazon localization matrix and
  processed Dove PDF summary

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 14:53:52 +02:00
nickviljoen
402f2e6cf2 Reword batch completion popup to avoid implying QC pass/fail
Changed "Success: 2" to "Processed 2 of 2" so the popup clearly
reports processing status, not QC results. Processing errors only
shown when they occur.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:26:17 +02:00
nickviljoen
d5acdd962b Fix long filename overflow in file queue, reports, and consolidated report
- web_ui: add overflow:hidden and min-width:0 to .form-section to
  prevent long filenames breaking the CSS grid layout
- web_ui: add overflow-x:hidden to queue list container
- api_server: add word-break:break-all to .filename in individual reports
- api_server: add table-layout:fixed and word-break to consolidated
  report table cells for proper text wrapping

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 19:09:06 +02:00
nickviljoen
eeaeb96b4e Fix file queue overflow for long filenames + score product-only shots neutrally
- File queue: add text-overflow ellipsis, min-width:0, flex-shrink:0 to
  prevent long filenames from pushing Pending/Remove buttons out of view
- text_readability: product-only images (no marketing text layout) now
  score 7/10 neutral instead of 1-2/10 critical fail. Hidden/invisible
  text in marketing layouts still scores 1-2.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 18:57:01 +02:00
nickviljoen
4d456f45e5 Add delete functionality for saved output reports
- New API endpoint POST /api/delete_output_files (auth required)
- Delete Selected button in saved files controls bar
- Confirmation prompt before deletion
- Auto-refreshes file list after successful delete
- Path traversal protection via os.path.basename sanitization

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 12:24:28 +02:00
nickviljoen
08b17508ba Add periodic auth session check and rename Amazon Box Placement to Element Placement
- Add silent auth check every 5 minutes to detect expired sessions proactively,
  showing a "Session Expired" prompt instead of failing silently on next action
- Rename amazon_box_placement to amazon_element_placement across module directory,
  profile config, class name, and documentation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 10:01:27 +02:00
nickviljoen
ec7d676abf Update Reference Assets UI: rename, add description, and remove button
- Rename "Upload Brand Guidelines" to "Upload a Reference Asset"
- Add info box explaining how each file type is used (PDF, images, Excel)
- Add "Remove" button on each uploaded reference asset
- Accept .xlsx/.xls files in the file picker
- Show "Localisation Matrix" badge with market count for parsed Excel files
- Update all labels and placeholder text to reference asset terminology

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 22:09:48 +02:00
nickviljoen
34a03be6cb Amazon prompt tuning, report details for passing checks, and queue fix
- Fix process queue bug: reset queue items to pending after completion so
  reprocessing works without page refresh
- Show report details for 10/10 scores by extracting explanation and
  elements_found fields from Amazon check JSON responses, with a fallback
  that renders all JSON data as a structured summary
- Add Amazon Static grade override: any individual check scoring below 6
  forces overall grade to Fail (same logic as L'Oreal)
- Box placement prompt: relax tape visibility rule from "all edges" to
  "at least one edge visible", prevent false positives on landscape formats
  where box sits near right edge
- Headline layout prompt: fix LLM misreading one-word-per-line as combined
  lines in tall/portrait formats, score multi-sentence headlines in 9:16
  as 6/10 (pass with recommendation) instead of fail

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 16:19:42 +02:00
nickviljoen
dd9ed44ad1 Fix saved files button alignment and add media plan selector to main page
Long filenames no longer push View/Download buttons out of line. Added Media Plan
dropdown in QC Configuration so users can opt-in to using a media plan per analysis.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 08:07:20 +02:00
nickviljoen
5429e4c684 Add media plan upload with automatic asset matching and validation
Upload Excel media plans per client. On QC analysis, automatically
match the uploaded file's name against the media plan's Asset IDs
to validate dimensions and file type, and include the media plan
context (country, language, placement, vendor) in QC check prompts.

- New backend/media_plan_processor.py: Excel parsing, fuzzy filename
  matching, dimension/file-type validation, prompt context builder
- New backend/media_plans/ directory for storage
- API endpoints: POST/GET/DELETE /api/media_plan
- Settings modal: new "Media Plan" tab for upload/manage
- Analysis flow: auto-match + validation in response + context in prompts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:30:15 +02:00
nickviljoen
3f4cc149ad Process multi-page PDF reference assets with LLM summarization
PDF brand guidelines were previously ignored - QC checks received no
content from uploaded PDFs. Now on upload, all pages are text-extracted,
summarized by Gemini into a structured brand guidelines summary, and
a cover image is extracted. QC checks receive the full summary in their
prompt and the cover image as visual reference.

- New backend/pdf_processor.py: text extraction, cover image, LLM summary
- brand_guidelines_db.py: summary/cover path tracking, cleanup on delete
- api_server.py: background processing on upload, summary-aware content
  retrieval, PDF cover image support, status/reprocess endpoints, startup
  backfill for existing unprocessed PDFs
- web_ui.html: processing status badges and upload feedback for PDFs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:02:47 +02:00
nickviljoen
cfcb601951 Fix QC Tools tab not showing due to cached modal DOM
Settings modal was only created once per page load (if !modal).
Now recreates the modal each time it opens, ensuring the latest
tabs and content are always rendered. Prevents stale cached HTML.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:40:21 +02:00
nickviljoen
3a98b1089d Add QC Tools reference tab in settings modal
Add a read-only "QC Tools" tab in the settings modal that lists all
available QC tools with their descriptions, so users can reference
what each tool does when creating or editing profiles. Includes a
search/filter input for quick lookup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:31:28 +02:00
nickviljoen
f87341c6bd Fix saved files showing across clients on switch
- Clear saved files list immediately when switching clients
- Remove retry logic that could load wrong client's files
- Hide saved files container when no files found (was keeping old list)
- Guard against stale fetch results if client changes mid-request

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 13:14:35 +02:00
nickviljoen
06a6562a92 Admin as full page, track user logins, fix reporting bugs
- Convert admin panel from popup modal to dedicated full page section
- Log user_login events on auth status check to track all visitors
- Admin user list now shows all users (login visitors + analysts)
- Fix cost field name (total_cost_usd vs estimated_cost_usd fallback)
- Round scores to 2 decimal places in reporting tables
- Reset reporting dashboard when switching clients
- Clear stale data on client switch before loading new client

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 13:03:52 +02:00
nickviljoen
8a82df4438 Add client-scoped reporting dashboard and admin panel
Move reporting from settings modal into a dedicated tab within each
client's main view with date range filtering, usage stats, and cost
tracking. Add admin panel with platform-wide user activity overview,
accessible only to configured admin users.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 12:34:20 +02:00
nickviljoen
3d94490879 Fix reference assets client filtering and profile editor check list
- Filter main page Reference Assets dropdown by selectedClient
- Profile editor now shows only the checks belonging to the selected
  profile instead of all 42 checks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 19:24:43 +02:00
nickviljoen
8c9401bf3c Add combined check, client-scoped assets, UI restructure, reporting, and report consolidation
- Create visual_readability_contrast combined check merging text readability
  and background contrast into a single LLM call for L'Oreal Static profile
- Update loreal_static.json to use combined check (2 checks, 100-point scale)
- Add client_id filtering to brand guidelines (upload, fetch, backfill migration)
- Restructure settings modal from 5 tabs to 4: Profile, Create New Profile,
  Reference Assets, Reporting (removed Model Selection, merged Tools into Profile)
- Add GET /api/profile_usage_stats endpoint with summary cards and recent analyses
- Add POST /api/consolidate_reports endpoint generating HTML summary with
  pass/fail highlighting from multiple selected reports
- Add report selection checkboxes and consolidation controls to saved files list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 19:10:32 +02:00
nickviljoen
ed0c362683 Update cost estimate to reflect actual usage (50x more accurate)
Issue: UI showed estimated cost of $0.15 per check, but actual
usage data shows average cost of only $0.003 per check - a 50x
difference!

Analysis from actual usage report:
- L'Oreal: 2 analyses, 6 checks total
- Cost: $0.02 total = $0.003 per check
- Old estimate: $0.15 per check (way too high)
- New estimate: $0.01 per check (conservative but realistic)

Changes:
- Updated cost calculation from 0.15 to 0.01 per check
- Updated display text from "$0.15 each" to "~$0.01 each"
- Applied to both web_ui.html and frontend/index.html

Example:
- Before: 3 checks = $0.45 estimated
- After: 3 checks = $0.03 estimated
- Actual: 3 checks = ~$0.01 (based on real usage)

New estimate is much closer to reality and based on actual
Gemini API usage data from production analyses.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 13:43:50 +02:00
nickviljoen
564ee96ac7 Fix selectedClient persistence bug on page refresh
Issue: When refreshing the page after selecting a client, saved files
would not display because init() was called without await, causing a
race condition where loadSavedFiles() could execute before selectedClient
was properly set.

Fix: Added await to init() call in DOMContentLoaded handler (line 3280)
to ensure init() completes before continuing. This guarantees that
loadSavedFiles() is called after selectedClient is properly set.

Also added debug logging to trace selectedClient value through the
initialization process for easier troubleshooting.

Testing: After this fix, refreshing the page should properly restore
the selected client and display their saved files.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 12:15:32 +02:00
nickviljoen
b1f3275a97 Fix client filtering bug in saved files refresh
The refreshSavedFilesAfterAnalysis() function was correctly filtering
the initial fetch by client, but the three retry attempts in the loop
were missing the client filter parameter. This caused the first API
call to correctly return only the selected client's files, but the
subsequent three calls to return all files.

Fixed by adding client filter to all refresh attempts in the loop.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 11:37:52 +02:00
nickviljoen
2d27356478 Add debug logging for client filtering
- Log client_filter parameter received by backend
- Log selectedClient value in frontend
- Log number of files returned
- Help diagnose why all files are showing for all clients

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 11:27:34 +02:00
nickviljoen
477780df09 Add client-specific output folders and 14-day auto-cleanup
## New Features

### Client-Specific Output Folders
- Files now saved in client-specific subdirectories (loreal/, diageo/, unilever/, general/)
- Automatic client detection from profile ID
- Better organization for multi-client environment
- Each client only sees their own QC reports

### Automatic File Cleanup
- Auto-delete reports older than 14 days on every file listing request
- Keeps output folder clean and manageable
- Configurable cleanup age (default: 14 days)

### File Filtering by Client
- API endpoint `/api/output_files` now accepts `?client=<client_id>` parameter
- Frontend automatically filters files by selected client
- No more cluttered file lists for clients

### Migration Script
- `migrate_output_files.py` - Move existing files to client folders
- Dry-run mode by default (use --execute to run)
- Deletes files older than 14 days during migration
- Supports both development (--dev) and production (--production)

## API Changes

### Modified Endpoints
- `GET /api/output_files?client=<client_id>` - List files filtered by client
- `GET /output/<client>/<filename>` - Serve files from client folders
- `GET /output/<filename>` - Legacy route for backward compatibility

### New Functions
- `get_client_from_profile(profile_id)` - Detect client from profile
- `ensure_client_output_folder(client)` - Create client folders
- `cleanup_old_files(max_age_days)` - Delete old files

## File Structure
```
output-dev/
├── loreal/
│   └── 20260202_102514_Missing_text_report.html
├── diageo/
│   └── 20260202_103423_Product_shot_report.html
├── unilever/
│   └── 20260202_104512_Key_visual_report.html
└── general/
    └── 20260202_105634_Other_report.html
```

## Frontend Changes
- `loadSavedFiles()` now includes client parameter in API calls
- Automatically filters saved files by selected client
- Clean UI showing only relevant reports

## Usage

### Migration (Development)
```bash
# Dry-run (no changes)
python3 migrate_output_files.py

# Execute migration
python3 migrate_output_files.py --execute
```

### Migration (Production)
```bash
# Dry-run for production folder
python3 migrate_output_files.py --production

# Execute migration
python3 migrate_output_files.py --production --execute
```

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 11:18:05 +02:00
nickviljoen
ba8b6dfa57 Fix authentication redirect to show client selection screen
After successful Microsoft authentication, force a full page reload to fetch
fresh HTML from the server instead of trying to reinitialize the cached page.
This ensures users see the client selection screen immediately after login
instead of the old cached interface.

Changes:
- Replace init() call with window.location.reload(true) after successful login
- Bypasses browser cache to fetch fresh HTML
- Fixes issue where users had to manually reload to see new interface

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 11:04:59 +02:00
nickviljoen
16741a96d6 Add L'Oréal Static General profile with multi-file queue and enhanced reporting
## New Features

### L'Oréal Static General Profile
- Created new profile with 3 checks optimized for digital marketing assets
- Even weighting (33.3% each) for 100-point scoring scale
- Removed print-specific requirements (3m viewing distance)
- Focus on marketing text vs product packaging distinction

### Multi-File Queue System (web_ui.html)
- Added file queue functionality for batch processing
- Users can now upload and process multiple files simultaneously
- Queue displays file status (pending, analyzing, complete, error)
- Individual file removal and queue clearing options
- Progress tracking for batch operations

### New General QC Checks
1. background_contrast_general
   - Optimized for digital assets (no distance requirements)
   - Checks logo, product, and marketing text contrast
   - Detects overlapping and blending issues
   - Provides element-by-element breakdown

2. text_readability_general
   - Focus on marketing text only (excludes product packaging)
   - Checks for overlapping elements
   - Digital readability optimization
   - Specific issue identification

3. language_consistency (enhanced)
   - Better distinction between marketing and packaging text
   - Detailed language detection and reporting
   - Lists specific text analyzed

### Usage Tracking System
- Added usage_tracker.py for analysis logging
- Tracks user activity, profile usage, and costs
- Daily log files in JSONL format
- Cost estimation per LLM provider

## Bug Fixes

### Authentication & User Management
- Fixed Flask 'g' import missing issue
- Fixed user info access in background threads
- Pass user_info to threads instead of accessing g.user
- Improved error handling for usage logging

### HTML Report Generation
- Fixed missing analysis details in reports
- Now extracts and displays all JSON fields properly
- Shows comprehensive breakdowns:
  - Analysis details
  - Elements checked (logo, product, text)
  - Marketing text found
  - Issues identified
  - Specific recommendations
- No more blank "Pass/Fail" results

### Scoring System
- Fixed usage_tracker to handle dict of check results (not list)
- Better handling of model_used field variations
- Skip non-dict check results gracefully

## Configuration Changes

### Model Versions (llm_config.py)
- Fixed invalid GPT-4.1 model ID to gpt-4o
- Added Gemini 3 Pro beta model option
- AVAILABLE_MODELS dict for UI selection
- Model version override support

### Profile Updates
- Static General: 3 checks, total weight 10.0
- Each check: text_readability_general (3.33), background_contrast_general (3.33), language_consistency (3.34)
- Maximum score: 100 points

## Technical Improvements

- Enhanced prompt engineering for consistent LLM outputs
- Mandatory detailed explanations in all checks
- Structured JSON responses with comprehensive fields
- Better error messages and fallback handling
- Client configuration support (client_config.py)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 10:58:39 +02:00
nickviljoen
c68470c78f Fix BASE_PATH detection to handle URLs without trailing slash
The getBasePath() function was only detecting /ai_qc/ (with trailing slash) but failing when users accessed /ai_qc (without trailing slash). This caused auth endpoints to be called at wrong URLs (/auth/status instead of /ai_qc/auth/status), resulting in 404 errors and JSON parsing failures.

Fix: Updated function to handle both /ai_qc and /ai_qc/ cases consistently.
2026-01-19 22:26:10 +02:00
nickviljoen
adf24a4603 Updated UI for creating profiles and profile discriptions 2025-12-06 14:32:47 +02:00
nickviljoen
199b9c72bf UI Update to be more BTG look and feel 2025-11-15 10:52:52 +02:00
nickviljoen
0a62034685 Fix MSAL interaction_in_progress error
Added protection against concurrent sign-in attempts by:
- Adding isSigningIn flag to prevent double-clicks
- Clearing MSAL localStorage/sessionStorage before authentication
- Properly resetting flag in finally block

This resolves the "interaction_in_progress" error that was preventing
users from signing in with Microsoft authentication.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 22:57:49 +02:00
michael
2598f162e4 changed MSAL URL and added base path to various API endpoint URLs in the HTML and api_server.py 2025-08-28 09:38:52 -05:00
nickviljoen
355be50b23 Bug fixes, profile updates, report updates 2025-08-23 14:44:17 +02:00
nickviljoen
56ecf9218c Added local host URl for Auth testing 2025-08-22 16:41:48 +02:00
nickviljoen
e5d36cac82 Updated SSO error, Updated Unilever Profile scoring weighting, updated output file list order 2025-08-21 17:27:11 +02:00
nickviljoen
5243ad4ae3 SSO Added 2025-08-20 15:30:29 +02:00
michael
c3b0c37ed4 initial commit 2025-08-12 14:52:49 -05:00