- Docker Swarm (Portainer) ignores 'restart: always' and often requires a 'deploy' block with replica counts to properly schedule a new service.
- Replaced standard docker-compose restart policy with a Swarm-compliant deploy block.
- The 'databack/mysql-backup' image crashes immediately when used in a pure cron context without legacy arguments and is incompatible with MySQL 8 caching_sha2_password.
- Switched to the actively maintained 'fradelg/mysql-cron-backup' image.
- Re-mapped environment variables to match the new image expectations (MYSQL_HOST, CRON_TIME, MAX_BACKUPS).
- Updated volume mapping destination to '/backup' as expected by the new image.
- Updated the host bind mount from the restricted '/root' directory to '/opt/fasto_backups' to ensure the Docker daemon has the necessary permissions to read and write database dumps.
- Appended a version suffix to the `init_sql` config name to bypass Docker Swarm's immutable config cache and force the cluster to pick up the latest database schema changes on deployment.
- Dropped the 'node.role == manager' deployment constraint to allow the backup container to be scheduled on any available node or to run smoothly in non-swarm Docker Compose environments.
- Added `databack/mysql-backup` service to the production docker-compose Swarm stack, scheduling a daily 02:55 AM cron backup of the database with a 3-day local retention policy.
- Fixed a critical race condition in the backend JWT authentication middleware where an invalid token returning 401 could crash the response flow if the route executed before the defensive checks caught it.
- Added strict undefined defensive checks to the `getUserById` endpoint and RBAC middleware to gracefully reject requests that somehow bypass the token parser.
- Updated `GEMINI.md` technical documentation to fully match the real codebase logic.
- Fixed UX rule to prevent `manager` role from seeing Funnels or Origins tabs in the sidebar.
- Blocked `agent` role from modifying their own 'fullName' string in the Profile UI.
- Cleaned up the requireRole middleware across all Funnel and Origin API routes to strictly allow only 'admin' and 'super_admin' to perform structural changes.
- Updated the tenant creation script to assign the 'admin' role to new signups instead of 'owner'.
- The backend was returning 403 Forbidden when a token expired, causing the frontend apiFetch interceptor (which listens for 401) to ignore it and crash the session.
- Refactored POST /auth/login to issue a 15-minute Access Token and a 30-day Refresh Token.
- Added POST /auth/refresh endpoint to automatically issue new Access Tokens and extend the Refresh Token's lifespan by 30 days upon use (Sliding Expiration).
- Built an HTTP interceptor wrapper (apiFetch) in dataService.ts that automatically catches 401 Unauthorized errors, calls the refresh endpoint, updates localStorage, and silently retries the original request without logging the user out.
- Updated Dashboard origin chart to strictly reflect only configured origins, grouping unmapped data into an 'Outros' category.
- Added GET /api/integration/funnels and GET /api/integration/origins endpoints to allow external AIs to dynamically map stages and lead sources.
- Fixed database initialization where default origins were seeded without color_classes.
- Added a visual color picker to the Origens admin page to allow users to assign colors to origin tags.
- Updated Dashboard Pie Chart to read the color classes correctly and display them.
- Dropped simple origins table in favor of origin_groups and origin_items to match the Funnels architecture.
- Added origin_group_id to teams table to assign specific origins to specific teams.
- Updated /admin/origins page to support creating origin groups, adding origin items to them, and assigning teams to groups.
- Updated Dashboard and UserDetail pages to dynamically load the exact origin items belonging to the active team/user.
- Updated AuthGuard to intercept navigation to the standard dashboard ('/') for users with the 'super_admin' role and automatically redirect them to '/super-admin'.
- Updated Login.tsx to automatically redirect users to the dashboard if a valid token is already present in localStorage.
- Refactored getUserById to properly throw server/network errors instead of silently returning undefined.
- Updated AuthGuard in App.tsx to gracefully handle network errors without destroying the user's valid localStorage tokens.
- Fixed a bug where selecting a date in the native date picker resulted in the previous day being selected due to the browser converting the 'YYYY-MM-DD' string to UTC midnight and then shifting it back to local time (e.g. UTC-3 in Brazil).
- Explicitly parsed the date string and constructed the Date object using local time coordinates to ensure visual and data consistency.
- Updated the DateRangePicker component to visually display dates in DD/MM/YYYY format using a focus/blur technique, overriding the browser's default OS language formatting.
- Removed all hardcoded MOCK_ATTENDANCES, USERS, and TENANTS generators from constants.ts since the system is now production-ready.
- Renamed 'summary' to 'title' in the database and across all frontend components for clarity.
- Added 'full_summary' to the attendances schema to explicitly store the large, detailed AI analysis texts from n8n.
- Updated the 'Resumo da Interação' UI to render the 'full_summary' without adding any artificial filler text.
- Localized all dates and times across the dashboard to Brazilian formatting (pt-BR).
- Extracted API Key generation and management from UserProfile to a new /super-admin/api-keys route.
- Added cross-tenant selection in the new ApiKeys page so Super Admins can manage integrations for any organization.
- Added api_keys table to database schema.
- Added API Key authentication middleware to express router.
- Created GET /api/integration/users endpoint for n8n to map agents.
- Created POST /api/integration/attendances endpoint to accept webhooks from n8n.
- Added UI in UserProfile (for Admins/Owners) to generate, view, and revoke API keys.