Each user can now store their own personal Tempo API token in their
profile settings. Time is logged using each user's own credentials.
Backend:
- Migration b044: adds tempo_api_token column to users table
- User model: adds tempo_api_token column
- UserPreferencesUpdate: adds tempo_api_token field (write-only)
- UserOut: adds tempo_api_token (excluded) + tempo_token_set bool;
@model_validator derives both jira_token_set and tempo_token_set
- users router: handles tempo_api_token same as jira_api_token
(empty string clears it, never returned in responses)
- tempo_service: refactored to per-user token; has_tempo_configured(),
get_user_tempo_client(user) use user.tempo_api_token; global
TEMPO_ENABLED still acts as kill-switch
- system router: /system/tempo-test now uses current user's personal
token (any role); removed global TEMPO_API_TOKEN dependency
Frontend:
- settings.ts: UserPreferencesUpdate.tempo_api_token, UserMeOut.tempo_token_set
- SettingsPage ProfileSection: Tempo Integration section with password
field, show/hide toggle, configured badge, and Test Tempo button —
mirrors the Jira token UX exactly
- JiraConfigSection: removed stale global Tempo test block
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Jira URL fix:
- JiraLinkPanel now fetches the configured Jira base URL via getJiraConfig()
instead of hardcoding https://jira.atlassian.com; falls back to the old
value if config is not yet loaded
Description fix:
- _build_test_description: renamed 'h3. Procedure' -> 'h3. Proof of Concept'
so the procedure/tool block maps to the correct Jira field label
Tempo debug:
- New POST /system/tempo-test endpoint: checks TEMPO_ENABLED, token,
user jira_account_id, and makes a real API call; always returns HTTP 200
with status field (Cloudflare-safe)
- docker-compose.prod.yml: added TEMPO_ENABLED, TEMPO_API_TOKEN,
TEMPO_DEFAULT_WORK_TYPE env vars (default off, ready to enable)
- SettingsPage: added 'Test Tempo Connection' button in Jira admin tab
with clear feedback showing what's missing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- jira-test now returns {status: "ok"|"error", message: ...} with
HTTP 200 so Cloudflare never intercepts the response
- jira_service strips trailing slash from URL before creating Jira
client (avoids double-slash in REST paths)
- Frontend reads data.status field instead of HTTP status code
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Users can now set a separate Atlassian email for Jira authentication
in Settings → Profile → Jira Integration. Falls back to the Aegis
account email when not set, so existing setups are unaffected.
- Migration b043: adds jira_email column to users table
- User model/schema: expose jira_email read/write
- jira_service: _effective_jira_email() uses jira_email ?? email
- Frontend: replaces read-only email display with editable input
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- backend: add parent_ticket field to JiraConfigOut/JiraConfigUpdate/_JIRA_KEYS
- backend: add get_jira_parent_ticket() helper in jira_service; use it in auto_create_test_issue() to set issue parent
- frontend/api: add jira_token_set to UserMeOut, jira_api_token to UserPreferencesUpdate, and full JiraConfigOut/Update types with getJiraConfig/updateJiraConfig/testJiraConnection functions
- frontend: expand ProfileSection with Jira API token password field (show/hide), token status badge, and account-id field
- frontend: add JiraConfigSection component (admin): enabled toggle, URL, project key, parent ticket, save + test connection
- frontend: add Jira tab (admin-only) with Link2 icon in SettingsPage sidebar