- Add DEPLOYMENT-CHECKLIST.md with step-by-step guide
- Add frontend/.env.production for build
- Update .env.fastapi.example with correct REDIRECT_URI
- Include all verification steps and troubleshooting
Ready for production deployment!
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Update .env: REDIRECT_URI without /api/ prefix
- Add OAuth handler in App.tsx for SSO callback
- Add basename to BrowserRouter: /solventum-image-metadata
- Add .env.production for server deployment
Matches Azure AD config:
https://ai-sandbox.oliver.solutions/solventum-image-metadata/
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Add prominent "Login with Microsoft" button
- Match original Flask design with Microsoft icon
- Add divider between SSO and local login
- Update styling to match gold theme
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Add Montserrat font from Google Fonts
- Use original color scheme (gold #FFC407, dark gradients)
- Add glass morphism effect with backdrop blur
- Add shimmer animation on header
- Style upload zone with hover/drag states
- Match all original design elements from Flask version
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Copy utils.py from src/ (required by extractors)
- Fixes ModuleNotFoundError: No module named 'app.processors.utils'
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- cd back to SCRIPT_DIR before running docker-compose logs/ps
- Fixes "no such file" error when running from frontend/ directory
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- FileUploadZone: Drag-drop with metadata source selector
- FileList: Batch operations (select, download, process more)
- FileItem: File card with expandable metadata editor
These were created but not committed previously.
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Add Redis container back (no external port exposure)
- Redis only accessible within Docker network
- Backend connects via redis://redis:6379/0
- Simplify Redis health check in deploy.sh
This avoids port conflicts while keeping Redis in Docker.
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Remove postgres service (port 5432 conflict)
- Using SQLite by default (simpler for single-server deployment)
- Remove postgres-data volume
- PostgreSQL can be added later if needed
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Comment out Excel file volume mount by default
- Excel lookup will be disabled if file not present
- Prevents deployment error when file doesn't exist
- Users can uncomment the line if they have the Excel file
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Change BACKEND_PORT from 8001 to 5001 (same as Flask)
- Keeps existing Azure AD redirect URI working
- No need to update Azure AD app registration
- Apache proxy can use same port configuration
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Make BACKEND_PORT configurable via .env
- Update docker-compose to use ${BACKEND_PORT:-8001}
- Update deploy.sh to read port from .env
- Update Apache config examples to use port 8001
- Update all documentation with correct port
Apache config must proxy:
/solventum-image-metadata/api → http://localhost:8001
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Update REDIRECT_URI to include /api/auth/microsoft/callback path
- Add production Azure AD credentials to .env.fastapi.example
- Create Apache migration guide with correct configuration
BREAKING CHANGE: Apache proxy must change from port 5001 to 8000
- Old: ProxyPass /solventum-image-metadata/ http://localhost:5001/
- New: ProxyPass /solventum-image-metadata/api http://localhost:8000
Frontend now served as static files, not proxied.
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Create idempotent deploy.sh for production deployment
- Add docker-compose.fastapi.yml with Redis + Backend
- Configure health checks for all services
- Add .env.fastapi.example with all configuration
- Remove old Flask deployment script (docker-run.sh)
Deployment features:
- Pre-flight checks (Docker, Node, permissions)
- Frontend build with Vite
- Deploy to /var/www/html/solventum-image-metadata
- Graceful container restart
- Health checks (backend + Redis)
- Auto-cleanup old Docker images
Usage:
cd /opt/solventum-image-metadata
git pull origin main
sudo ./deploy.sh
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
Fixed three critical issues:
1. Session persistence - Cookies not saved after page refresh
- Replaced APPLICATION_ROOT with SESSION_COOKIE_PATH
- Added proper cookie settings for reverse proxy (HttpOnly, SameSite)
- Set correct cookie path matching URL_PREFIX
2. AJAX detection for FormData uploads (JPG, etc.)
- Enhanced @login_required to detect POST/PUT/DELETE as AJAX
- Added Content-Type check for JSON requests
- Added path prefix check for API endpoints
3. JavaScript AJAX identification
- Updated fetchWithAuth() to add X-Requested-With header
- Properly handles both JSON and FormData requests using Headers API
- Ensures all fetch calls are identified as AJAX by server
Changes:
- web_app.py: Fixed Flask session cookie configuration
- src/auth.py: Improved AJAX detection logic in login_required decorator
- templates/index.html: Enhanced fetchWithAuth() with proper headers
This fixes:
- Users having to re-login on every page refresh
- "Unexpected token '<'" errors when uploading JPG files
- Session cookies not persisting through reverse proxy
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
Fixed two critical issues with API authentication on production server:
1. Modified @login_required decorator to detect AJAX/API requests and return
JSON error with 401 status instead of HTML redirect. This prevents
"Unexpected token '<'" errors when session expires.
2. Created fetchWithAuth() helper function in JavaScript that automatically
handles 401 responses by redirecting to login page. Updated all 11 API
fetch calls to use this wrapper.
Changes:
- src/auth.py: Added AJAX detection and JSON error responses to login_required
- templates/index.html: Added fetchWithAuth() and updated all fetch() calls
This fixes the console errors:
- "Failed to load templates: SyntaxError: Unexpected token '<'"
- 502 Bad Gateway errors now properly handled with session checks
Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
- Login button now uses MSAL.js loginRedirect() for PKCE
- oauth_callback uses MSAL.js handleRedirectPromise() to complete token exchange
- PKCE flow is now entirely in browser (SPA compatible)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Render oauth_callback.html with MSAL.js for browser token exchange
- Add /auth/token endpoint to receive token from JavaScript
- Token exchange happens in browser (cross-origin) for SPA compatibility
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Check for OAuth code in query params on main page
- Process SSO login without requiring /auth/callback route
- Redirect to clean URL after successful login
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use initiate_auth_code_flow for PKCE (required by Azure AD for public clients)
- Store auth flow in session for token exchange
- Fix AADSTS9002325 error
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove -back suffix, use single path for monolithic Flask app
- All routes now use /solventum-image-metadata/ prefix
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add URL_PREFIX for all redirect URLs
- Redirects now go to /solventum-image-metadata-back/login instead of /login
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add deploy.sh for idempotent Docker deployments
- Configure API_BASE for /solventum-image-metadata-back/ reverse proxy
- Enable Azure AD SSO with public client flow (no secret required)
- Remove hardcoded tester user for production security
- Add ProxyFix middleware for reverse proxy header handling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add GPT-5, GPT-5-mini, and GPT-5-nano to valid models list
- Add model validation with automatic fallback to gpt-4o-mini
- Update _is_new_model() to recognize GPT-5 as new generation
- Add detailed API response logging (model used, tokens, content preview)
- Add empty content detection with helpful error messages
- Fix API parameter selection for GPT-5 models
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Enhanced JSON and text parsing:
- Smarter JSON extraction from responses with extra text
- Find JSON object {...} anywhere in response text
- Improved markdown code block removal
- Validate parsed JSON has meaningful content
- Better text parsing fallback with multiple strategies
- Added debug logging for raw AI responses
- Handle edge cases like empty titles or malformed JSON
Fixes issue where AI-generated metadata was not displayed correctly.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed two critical issues:
1. OpenAI API temperature parameter:
- New models (gpt-5-mini, gpt-4o, o1, o3) only support default temperature=1
- Modified _get_api_params() to exclude temperature for new models
- Older models still use custom temperature setting
- Fixes 400 error: 'temperature' unsupported value
2. File cleanup to prevent disk space issues:
- Added cleanup_session_files() to remove files when session ends
- Added cleanup_old_files() to remove files older than 24 hours
- Cleanup runs automatically on app startup in Docker mode
- Cleanup runs on logout to free up space immediately
- Added /cleanup-session endpoint for manual cleanup
- Files no longer accumulate in Docker volume
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed two critical issues:
1. OpenAI API compatibility for newer models:
- Added _get_token_param() method to detect model type
- Newer models (gpt-5-mini, gpt-4o, o1, o3) use max_completion_tokens
- Older models (gpt-3.5-turbo) use max_tokens
- Fixes 400 error: 'max_tokens' not supported parameter
2. Progress bar for AI generation:
- Added startProgressAnimation() and stopProgressAnimation()
- Animated progress bar shows activity during AI processing
- Progress slowly increments to 90% to indicate work in progress
- Stops animation when processing completes or errors occur
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Modified docker-compose.yml to support .env file:
- Added env_file directive to load .env automatically
- Simplified environment section (only DOCKER_MODE required)
- Enables AI metadata generation when OPENAI_API_KEY is set in .env
- All optional configs now loaded from .env file
Users can now create .env file with their OpenAI API key and other settings.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed critical bug preventing download functionality:
- Changed currentSessionId to sessionId to match actual variable name
- Function was silently failing with 'No active session' error
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Modified download feature to work with selected files instead of all files:
- Button now shows 'Download Selected Files (N) as ZIP' with count
- New endpoint /download-selected accepts POST with file_indices
- Frontend sends only selected file indices to backend
- Button text updates dynamically when selection changes
- All files selected by default as before
- Users can select/deselect files before downloading
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Improved Download All Files button display:
- Changed insertion point from message div to after fileList element
- Added prominent styling with border, background, and shadow
- Increased button size and padding for better visibility
- Added hover effect for better UX
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added functionality to download all processed files at once in a ZIP archive:
- New endpoint /download-all/<session_id> in web_app.py
- Creates timestamped ZIP archive with all files from session
- Download All button appears after successful file updates
- Button shows at bottom of results with clear styling
- Added zipfile and datetime imports
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Modified updateAllFiles() function to display download buttons for each updated file.
Success messages now include download links with improved UX using flexbox layout.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>