- Re-add migration 014_create_ai_providers to create ai_providers table
- Add test_create_ai_providers_table() to verify table schema
- Add test_store_and_retrieve_ai_provider() to verify CRUD operations
- Bump version to 0.2.49 in tauri.conf.json
Fixes missing AI provider data when upgrading from v0.2.42
- Add use_datastore_upload field to ProviderConfig for enabling datastore uploads
- Add upload_file_to_datastore and upload_file_to_datastore_any commands
- Add upload_log_file_by_content and upload_image_attachment_by_content commands for drag-and-drop without file paths
- Add multipart/form-data support for file uploads to GenAI datastore
- Add support for image/bmp MIME type in image validation
- Add x-generic-api-key header support for GenAI API authentication
This addresses:
- Paste fails to attach screenshot (clipboard)
- File upload fails with 500 error when using GenAI API
- GenAI datastore upload endpoint support for non-text files
- Use test-specific key derivation instead of env vars
- Add helper functions encrypt_token_with_key/decrypt_token_with_key
- Avoid conflicts when tests run in parallel
- Add debug logging to OpenAI provider for troubleshooting
- Trim trailing periods from model names
- Fix HTTP error handling to capture response details
- Register missing AI provider commands (save/load/delete)
- Fix authenticateWithWebviewCmd to accept optional projectName parameter
- Delete internal vendor API documentation and handoff docs
- Remove vendor-specific AI gateway URLs from CSP whitelist
- Replace vendor-specific log prefixes and comments with generic 'Custom REST'
- Remove vendor-specific default auth header from custom REST implementation
- Remove vendor-specific client header from HTTP requests
- Remove backward-compat vendor format identifier from is_custom_rest_format()
- Remove LEGACY_API_FORMAT constant and normalizeApiFormat() helper
- Update test to not reference legacy format identifier
- Update wiki docs to use generic enterprise gateway configuration
- Update architecture diagrams and ADR-003 to remove vendor references
- Add Buy Me A Coffee link to README
- Update .gitignore to exclude internal user guide and ticket files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes clippy::uninlined_format_args warnings by using inline
variable formatting (e.g., {e} instead of {}, e).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes two critical issues preventing Mac release builds from working:
1. Database encryption key auto-generation: Release builds now
auto-generate and persist the SQLCipher encryption key to
~/.../trcaa/.dbkey (mode 0600) instead of requiring the
TFTSR_DB_KEY env var. This prevents 'file is not a database'
errors when users don't set the env var.
2. Plain SQLite to encrypted migration: When a release build
encounters a plain SQLite database (from a previous debug build),
it now automatically migrates it to encrypted SQLCipher format
using ATTACH DATABASE + sqlcipher_export. Creates a backup at
.db.plain-backup before migration.
3. Credential encryption key auto-generation: Applied the same
pattern to TFTSR_ENCRYPTION_KEY for encrypting AI provider API
keys and integration tokens. Release builds now auto-generate
and persist to ~/.../trcaa/.enckey (mode 0600) instead of
failing with 'TFTSR_ENCRYPTION_KEY must be set'.
4. Refactored app data directory helper: Moved dirs_data_dir()
from lib.rs to state.rs as get_app_data_dir() so it can be
reused by both database and auth modules.
Testing:
- All unit tests pass (db::connection::tests + integrations::auth::tests)
- Verified manual migration from plain to encrypted database
- No clippy warnings
Impact: Users installing the Mac release build will now have a
working app out-of-the-box without needing to set environment
variables. Developers switching from debug to release builds will
have their databases automatically migrated.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit implements two major features:
1. Integration Search as Primary AI Data Source
- Confluence, ServiceNow, and Azure DevOps searches execute before AI queries
- Search results injected as system context for AI providers
- Parallel search execution for performance
- Webview-based fetch for HttpOnly cookie support
- Persistent browser windows maintain authenticated sessions
2. AI Tool-Calling (Function Calling)
- Allows AI to automatically execute functions during conversation
- Implemented for OpenAI-compatible providers and Custom REST provider
- Created add_ado_comment tool for updating Azure DevOps tickets
- Iterative tool-calling loop supports multi-step workflows
- Extensible architecture for adding new tools
Key Files:
- src-tauri/src/ai/tools.rs (NEW) - Tool definitions
- src-tauri/src/integrations/*_search.rs (NEW) - Integration search modules
- src-tauri/src/integrations/webview_fetch.rs (NEW) - HttpOnly cookie workaround
- src-tauri/src/commands/ai.rs - Tool execution and integration search
- src-tauri/src/ai/openai.rs - Tool-calling for OpenAI and Custom REST provider
- All providers updated with tools parameter support
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- AIProviders: hide top model row when custom_rest active (dropdown lower in form handles it);
clear auth header prefill on format switch; rename User ID / CORE ID → Email Address
- Dashboard + Ollama: add border-border/bg-card classes to Refresh buttons for dark-bg contrast
- Security + settingsStore: wire PII toggle state to persisted Zustand store so pattern
selections survive app restarts
- App: add Sun/Moon theme toggle button to sidebar footer (always visible when collapsed)
- system.rs: add install_ollama_from_bundle command (copies bundled binary to /usr/local/bin)
- auto-tag.yml: add Download Ollama step to all 4 platform build jobs with SHA256 verification
- tauri.conf.json: add resources/ollama/* to bundle resources
- docs: add install_ollama_from_bundle to IPC-Commands wiki
Security: CI download steps verify SHA256 against Ollama's published sha256sums.txt before bundling.
- Rename Cargo package from 'tftsr' to 'trcaa' — installed command
becomes 'trcaa' instead of 'tftsr'
- Update app data directories to ~/.local/share/trcaa (Linux),
~/Library/Application Support/trcaa (macOS), %APPDATA%/trcaa (Windows)
- Update bundle identifier to com.trcaa.app
- Auto-generate per-installation DB encryption key on first launch and
persist to <data_dir>/.dbkey (mode 0600 on Unix) — removes the hard
requirement for TFTSR_DB_KEY to be set before the app will start
analyze_logs() was reading the original log file from disk and sending its
full contents to external AI providers, completely bypassing the redaction
pipeline. The redacted flag in log_files and the .redacted file on disk were
written by apply_redactions() but never consulted on the read path.
Fix: query the redacted column alongside file_path. If the file has not been
redacted, return an error to the caller before any AI provider call is made.
When redacted, read from {path}.redacted instead of the original.
Adds redacted_path_for() helper and two unit tests covering the rejection
and happy-path cases.
Rust's `regex` crate does not support lookaround assertions. The hostname
pattern `(?=.{1,253}\b)` caused a panic on every `PiiDetector::new()` call,
failing all four PII detector tests in CI (rust-fmt-check, rust-clippy,
rust-tests). Removed the lookahead; the remaining pattern correctly matches
valid FQDNs without the RFC 1035 length pre-check.
Also reformatted analysis.rs:253 to satisfy `rustfmt` (line break after `=`).
All 127 Rust tests pass and `cargo fmt --check` and `cargo clippy -- -D
warnings` are clean.
Remove high-risk defaults and tighten data handling across auth, storage, IPC, provider calls, and capabilities so sensitive data is better protected by default. Also update README/wiki security guidance and add targeted tests for the new hardening behaviors.
Made-with: Cursor
Rename custom API format handling from custom_rest to custom_rest with backward compatibility, add guided model selection with custom entry in provider settings, and rebrand app naming to Troubleshooting and RCA Assistant across UI, metadata, and docs.
Made-with: Cursor
Apply canonical rustfmt formatting in files touched by the clippy format-args cleanup so cargo fmt --check passes consistently in CI.
Made-with: Cursor
Inline format arguments across Rust modules to satisfy clippy -D warnings, and configure Cargo to prefer system OpenSSL so clippy builds do not fail on missing vendored Perl modules.
Made-with: Cursor
Replace format!("msg: {}", var) with format!("msg: {var}") across 8 files
to satisfy the uninlined_format_args lint (-D warnings) in CI run 178.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
## Integration Settings Persistence
- Add database commands to save/load integration configs (base_url, username, project_name, space_key)
- Frontend now loads configs from DB on mount and saves changes automatically
- Fixes issue where settings were lost on app restart
## Persistent Browser Window Architecture
- Integration browser windows now stay open for user browsing and authentication
- Extract fresh cookies before each API call to handle token rotation
- Track open windows in app state (integration_webviews HashMap)
- Windows titled as "{Service} Browser (TFTSR)" for clarity
- Support easy navigation between app and browser windows (Cmd+Tab/Alt+Tab)
- Gracefully handle closed windows with automatic cleanup
## Bug Fixes
- Fix Rust formatting issues across 8 files
- Fix clippy warnings:
- Use is_some_and() instead of map_or() in openai.rs
- Use .to_string() instead of format!() in integrations.rs
- Add missing OptionalExtension import for .optional() method
## Tests
- Add test_integration_config_serialization
- Add test_webview_tracking
- Add test_token_auth_request_serialization
- All 6 integration tests passing
## Files Modified
- src-tauri/src/state.rs: Add integration_webviews tracking
- src-tauri/src/lib.rs: Register 3 new commands, initialize webviews HashMap
- src-tauri/src/commands/integrations.rs: Config persistence, fresh cookie extraction (+151 lines)
- src-tauri/src/integrations/webview_auth.rs: Persistent window behavior
- src/lib/tauriCommands.ts: TypeScript wrappers for new commands
- src/pages/Settings/Integrations.tsx: Load/save configs from DB
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement working cookie extraction using Tauri's IPC event system:
**How it works:**
1. Opens embedded browser window for user to login
2. User completes authentication (including SSO)
3. User clicks "Complete Login" button in UI
4. JavaScript injected into webview extracts `document.cookie`
5. Parsed cookies emitted via Tauri event: `tftsr-cookies-extracted`
6. Rust listens for event and receives cookie data
7. Cookies encrypted and stored in database
**Technical implementation:**
- Uses `window.__TAURI__.event.emit()` from injected JavaScript
- Rust listens via `app_handle.listen()` with Listener trait
- 10-second timeout with clear error messages
- Handles empty cookies and JavaScript errors gracefully
- Cross-platform compatible (no platform-specific APIs)
**Cookie limitations:**
- `document.cookie` only exposes non-HttpOnly cookies
- HttpOnly session cookies won't be captured via JavaScript
- For HttpOnly cookies, services must provide API tokens as fallback
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement three authentication methods for Confluence, ServiceNow, and Azure DevOps:
1. **OAuth2** - Traditional OAuth flow for enterprise SSO environments
2. **Embedded Browser** - Webview-based login that captures session cookies/tokens
- Solves VPN constraints: users authenticate off-VPN via web UI
- Extracted credentials work on-VPN for API calls
- Based on confluence-publisher agent pattern
3. **Manual Token** - Direct API token/PAT input as fallback
**Changes:**
- Add webview_auth.rs module for embedded browser authentication
- Implement authenticate_with_webview and extract_cookies_from_webview commands
- Implement save_manual_token command with validation
- Add AuthMethod enum to support all three modes
- Add RadioGroup UI component for mode selection
- Complete rewrite of Integrations settings page with mode-specific UI
- Add secondary button variant for UI consistency
**VPN-friendly design:**
Users can authenticate via webview when off-VPN (web UI accessible), then use extracted cookies for API calls when on-VPN (API requires VPN). Addresses enterprise SSO limitations where OAuth app registration is blocked.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Added max_tokens and temperature fields to ProviderConfig
- Custom REST providers now send modelConfig with temperature and max_tokens
- OpenAI-compatible providers now use configured max_tokens/temperature
- Both formats fall back to defaults if not specified
- Bumped version to 0.2.9
This allows users to configure response length and randomness for all
AI providers, including Custom REST providers which require modelConfig format.
Fixes:
- Added shell:allow-open permission to fix OAuth integration flows
- Added user_id field to ProviderConfig for Custom REST provider CORE ID
- Added UI field for user_id when api_format is custom_rest
- Made userId optional in Custom REST provider requests (only sent if provided)
- Added X-msi-genai-client header to Custom REST provider requests
- Updated CSP to include Custom REST provider domains
- Bumped version to 0.2.6
This fixes:
- OAuth error: 'Command plugin:shell|open not allowed by ACL'
- Missing User ID field in Custom REST provider configuration UI
- Extended ProviderConfig with optional custom fields for non-OpenAI APIs
- Added custom_endpoint_path, custom_auth_header, custom_auth_prefix fields
- Added api_format field to distinguish between OpenAI and Custom REST provider formats
- Added session_id field for stateful conversation APIs
- Implemented chat_custom_rest() method in OpenAI provider
- Custom REST provider uses different request format (prompt+sessionId) and response (msg field)
- Updated TypeScript types to match Rust schema
- Added UI controls in Settings/AIProviders for custom provider configuration
- API format selector auto-populates appropriate defaults (OpenAI vs Custom REST provider)
- Backward compatible: existing providers default to OpenAI format
Phase 2.2: OAuth2 flow - Part 3 (Callback server) COMPLETE ✅
Implemented:
- Local HTTP server on localhost:8765 using warp
* GET /callback?code=...&state=... - OAuth redirect handler
* GET /health - Health check endpoint
* Graceful shutdown with oneshot channel
- Automatic callback handling
* Server auto-starts on first initiate_oauth call
* Background task listens for OAuth redirects
* Automatically exchanges code for token
* Stores encrypted token in database
* Logs audit event for each successful OAuth
- Updated initiate_oauth command
* Starts callback server if not running
* Stores (service, verifier) tuple in OAuth state
* Returns auth URL to open in browser/webview
- Updated handle_oauth_callback_internal
* Accepts AppState reference (not State)
* Called automatically by callback server
* Exchanges code, encrypts token, stores in DB
- Beautiful success/error HTML pages
* Green checkmark on success
* Auto-closes window after 3 seconds
* Clear error messages on failure
- Global state management
* OAUTH_STATE: Maps state key -> (service, verifier)
* CALLBACK_SERVER_SHUTDOWN: Holds shutdown channel
* Thread-safe with Mutex wrappers
Dependencies added:
- warp 0.3 - Lightweight HTTP framework
TDD tests (7 passing with --test-threads=1):
Callback server tests:
* Health endpoint verification
* Callback parameter parsing
* Missing/partial parameter handling
* Graceful shutdown
Integration command tests:
* OAuth state storage and retrieval
* Multiple key management
* OAuthInitResponse serialization
COMPLETE OAUTH2 FLOW:
1. User calls initiate_oauth("confluence")
2. Callback server starts (if not running)
3. Frontend receives auth URL
4. User opens URL in browser/webview
5. User authorizes, redirected to localhost:8765/callback?code=...
6. Callback server receives redirect
7. Token exchanged automatically
8. Token encrypted and stored in DB
9. Success page shown to user
10. Window auto-closes
Next: Frontend components (AuthWindow, Settings UI, CSP updates)
Replace pandoc-based DOCX export with native Rust implementation
using docx-rs crate. DOCX export now works out of the box without
requiring users to install external tools.
Changes:
- Added docx-rs dependency to Cargo.toml
- Implemented export_docx() in exporter.rs
- Removed pandoc subprocess calls from docs.rs
- Uses same markdown parsing as PDF export
- Handles titles, headings, and normal text with appropriate styling
Tested:
- Rust compilation ✓
- Rust formatting ✓
- TypeScript types ✓
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1. Download Button Visibility:
- Changed from variant=outline to default variant (solid background)
- Provides better contrast and icon visibility in both themes
- Removed unnecessary text-foreground class
2. DOCX Export Support:
- Added DOCX export via pandoc conversion
- Writes temp markdown file, converts with pandoc, cleans up
- Returns clear error if pandoc not installed
- Supports same workflow as MD/PDF exports
3. Triaging Status Investigation:
- triaging status is defined in schema and used in dashboard counts
- Currently not automatically set when entering triage
- Kept in filter dropdown as part of the data model
Tested: Rust compilation, TypeScript types, Rust formatting
Note: DOCX export requires pandoc to be installed on the system.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix download icons (PDF/DOCX) not visible in dark theme by adding text-foreground class
- Fix "Read-only file system" error by using Downloads directory for exports with proper fallback
- Fix Search button visibility in History page by changing variant and adding icon
- Fix domain-only filtering in History page by adding missing filter.domain handling
- Enhance audit log to capture full transmitted data (provider details, messages, content previews)
- Add dirs crate dependency for cross-platform directory detection
- Add success/error feedback for document exports with file path display
- Update Security page to display pretty-printed JSON audit details
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- db.rs: add get_issue_messages command (joins ai_conversations + ai_messages)
- tauriCommands.ts: fix updateIssueCmd to pass updates as nested object
(was spreading inline — Rust expects {issueId, updates}); fix addFiveWhyCmd
parameter names to match Rust (stepOrder, whyQuestion, answer, evidence);
add getIssueMessagesCmd and IssueMessage interface
- Dashboard: X button on each open issue row to close (mark resolved) inline
- Triage: restore conversation history from DB when revisiting existing issues;
detect close intent patterns and mark issue resolved + navigate home;
auto-save resolution step via addFiveWhyCmd when AI advances why level
- tests: add issueActions.test.ts covering IPC arg structure and close intent
Previously cipher_page_size was set AFTER the verification SELECT,
making it a no-op (SQLCipher locks page size on first access). This
caused two bugs:
1. Databases were created with the default page size regardless of the
setting, then flushed on close using misaligned 4KB mmap pages on
16KB kernel → corrupted file → SQLITE_NOTADB on reopen.
2. Reopening an existing DB used default (potentially wrong) page size
for the initial read → decryption failure.
Fix: batch all cipher settings (key, page_size, kdf_iter, algorithms)
into a single execute_batch call BEFORE the first SELECT. This ensures:
- New databases are created with 16KB pages (aligned to Asahi kernel)
- Existing 16KB-page databases are reopened with the correct page size
- Close/flush operations use properly aligned mmap → no corruption
Note: existing 4KB-page databases (from v0.1.0) remain incompatible
and must be deleted once on upgrade.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Two startup crashes on first-party Tauri plugin init:
- tauri-plugin-updater registered with no plugins.updater config → removed
- tauri-plugin-cli was already removed in a prior commit
SQLCipher page size fix:
- cipher_page_size 4096 → 16384
- 4KB SQLCipher pages cause malloc() failures on Linux kernels with
16KB page size (Asahi Linux aarch64+16k, Apple Silicon)
- 16384 is a valid page size that works on both 4KB and 16KB page kernels
- New installs get a 16KB-page database; existing 4KB-page DBs must
be deleted for the new page size to take effect
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
tauri-plugin-cli was registered in lib.rs but tauri.conf.json had no
plugins.cli configuration, causing PluginInitialization panic at startup.
The CLI plugin is not needed for a GUI desktop app — removed.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>