Commit Graph

75 Commits

Author SHA1 Message Date
Shaun Arman
cf1d5adb83 docs(analysis): document zip-slip safety guarantee in extract_docx_text
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m35s
Test / frontend-typecheck (pull_request) Successful in 2m16s
Test / frontend-tests (pull_request) Successful in 2m13s
Test / rust-clippy (pull_request) Failing after 3m43s
PR Review Automation / review (pull_request) Successful in 4m11s
Test / rust-tests (pull_request) Successful in 4m59s
Only a single hardcoded entry (word/document.xml) is ever accessed from
the ZIP archive; no arbitrary path extraction occurs, so path traversal
attacks cannot apply. Add a comment to make this invariant explicit for
future maintainers.
2026-05-31 13:57:38 -05:00
Shaun Arman
ed2e25f835 chore: update Cargo.lock for lopdf, zip, quick-xml deps 2026-05-31 13:51:08 -05:00
Shaun Arman
f47ec90d05 feat(upload): add safe file extension validation and binary text extraction
- Add extension allowlist (SAFE_TEXT_EXTENSIONS + SAFE_BINARY_EXTENSIONS)
  rejecting unsupported file types at both upload_log_file and
  upload_log_file_by_content entry points
- Add extract_text_content() with PDF text extraction via lopdf and
  DOCX extraction via zip+quick-xml
- Binary files (PDF/DOCX) get extracted text written to .extracted.txt
  for downstream PII detection
- Expand frontend file input accept list and add collapsible
  supported-formats disclosure element
- Add 11 unit tests covering allowlist logic and extraction paths
2026-05-31 13:50:59 -05:00
Shaun Arman
cd67a09a6a fix(ai,search): load history across all conversations; deep search related tables
AI history continuity: Changed the history-load query in chat_message to
JOIN ai_conversations and select by issue_id instead of single conversation_id.
This preserves full context when provider/model changes mid-triage.

Deep search: Added DISTINCT to list_issues SELECT and extended the search
filter with EXISTS subqueries covering ai_messages, resolution_steps,
log_files, and timeline_events. Ensures comprehensive search without
duplicate results.

Includes 11 new unit tests covering both features.
2026-05-31 13:50:29 -05:00
Shaun Arman
28cfcf1ef4 fix(mcp): add timeouts, delete audit log, OAuth state nonce; improve PR review prompt
All checks were successful
Test / frontend-typecheck (pull_request) Successful in 1m54s
Test / rust-fmt-check (pull_request) Successful in 2m0s
Test / frontend-tests (pull_request) Successful in 1m53s
Test / rust-clippy (pull_request) Successful in 3m33s
PR Review Automation / review (pull_request) Successful in 4m54s
Test / rust-tests (pull_request) Successful in 4m57s
- call_tool: 30s hard timeout via tokio::time::timeout
- discover_server: 60s hard timeout wrapping full connect+discover sequence
- delete_mcp_server: write_audit_event before cascade delete, capturing
  server name, tool count, and resource count
- initiate_mcp_oauth: append cryptographically random state nonce for CSRF
- pr-review.yml: rewrite prompt to require line-quoted evidence for every
  finding and eliminate hallucinated false positives
2026-05-23 17:08:23 -05:00
Shaun Arman
a779756e48 style(mcp): apply rustfmt formatting
Some checks failed
PR Review Automation / review (pull_request) Has been cancelled
Test / rust-fmt-check (pull_request) Successful in 1m46s
Test / frontend-typecheck (pull_request) Successful in 1m39s
Test / frontend-tests (pull_request) Successful in 1m39s
Test / rust-clippy (pull_request) Successful in 3m26s
Test / rust-tests (pull_request) Successful in 4m54s
2026-05-23 16:48:26 -05:00
Shaun Arman
3588399dfd feat(mcp): add MCP Server Support with TDD implementation
Some checks failed
Test / rust-fmt-check (pull_request) Failing after 2m12s
Test / frontend-typecheck (pull_request) Successful in 2m23s
Test / frontend-tests (pull_request) Successful in 2m22s
Test / rust-clippy (pull_request) Successful in 3m55s
Test / rust-tests (pull_request) Successful in 5m10s
PR Review Automation / review (pull_request) Failing after 11m6s
Adds full Model Context Protocol (MCP) server management, enabling the
AI assistant to discover and call tools from external MCP servers during
triage conversations.

Backend (Rust):
- rmcp 1.7.0 dependency (client + stdio + Streamable HTTP transports)
- Migration 018: mcp_servers, mcp_tools, mcp_resources tables with
  CHECK constraints for transport_type, auth_type, discovery_status
- src/mcp/ module: models, store, client, adapter, discovery, commands,
  transport/{stdio,http}
- AppState gains mcp_connections: Arc<TokioMutex<HashMap<...>>>
- .setup() hook auto-discovers enabled servers at startup
- 8 new Tauri commands wired into invoke_handler
- execute_mcp_tool_call: PII scan + mandatory audit_log before execution
- Auth values encrypted at rest via integrations::auth::encrypt_token();
  scrubbed before any frontend response

Frontend:
- MCPServers.tsx settings page (/settings/mcp) with server list,
  status badges, Discover Now, Add/Edit modal, enable/disable toggle
- tauriCommands.ts: McpServer, McpTool, McpServerStatus types + 8 cmds
- App.tsx: Plug icon, /settings/mcp route, sidebar nav entry

Tests (TDD): 15 new tests, all green
- 5 migration tests (written before migration, red → green)
- 5 store CRUD + encryption tests
- 5 adapter sanitization + conversion tests

Verification: 185/185 Rust, 94/94 Vitest, clippy -D warnings: 0
2026-05-23 16:23:48 -05:00
Shaun Arman
0b7f1cd9ab feat(ai): add devops-incident-responder agent with domain auto-detection
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m29s
Test / frontend-typecheck (pull_request) Successful in 1m28s
Test / frontend-tests (pull_request) Successful in 1m30s
Test / rust-clippy (pull_request) Successful in 3m33s
Test / rust-tests (pull_request) Successful in 4m54s
PR Review Automation / review (pull_request) Failing after 8m49s
- Implement AgentRegistry system with devops-incident-responder agent
- Add domain detection based on conversation keywords
- Inject devops-incident-responder as primary system prompt
- Auto-switch domain prompts silently when context shifts
- Fix version update script to handle JSON format correctly
- Always display version in bottom-left corner
- Add release notes fallback to git commits if CHANGELOG empty

This implements the full devops-incident-responder agent as the primary
system prompt, with domain-specific SME prompts layered on top based on
conversation content analysis. The version display bug is fixed by removing
the collapsed condition, and release notes now have a fallback mechanism.
2026-04-29 19:41:47 -05:00
Shaun Arman
8b0cbc3ce8 fix: harden timeline event input validation and atomic writes
Address security review findings:
- Validate event_type against whitelist of 7 known types (M-3)
- Validate metadata is valid JSON and under 10KB (M-2, M-4)
- Include metadata in audit log details (M-2)
- Wrap timeline insert + audit write + timestamp update in a
  SQLite transaction for atomicity (M-5)
- Fix TypeScript TimelineEvent interface: add issue_id, metadata
  fields and correct created_at type to string (L-3)
- Add timeline_events to IssueDetail TypeScript interface (L-4)
2026-04-19 18:25:53 -05:00
Shaun Arman
13c4969e31 feat: wire incident response methodology into AI and record triage events
Add INCIDENT_RESPONSE_FRAMEWORK to domainPrompts.ts and append it to
all 17 domain prompts via getDomainPrompt(). Add system_prompt param
to chat_message command so frontend can inject domain expertise. Record
UTC timeline events (triage_started, log_uploaded, why_level_advanced,
root_cause_identified, rca_generated, postmortem_generated,
document_exported) at key moments with non-blocking calls.

Update tauriCommands.ts with getTimelineEventsCmd, optional metadata on
addTimelineEventCmd, and systemPrompt on chatMessageCmd.

12 new frontend tests (9 domain prompts, 3 timeline events).
2026-04-19 18:13:47 -05:00
Shaun Arman
79a623dbb2 feat: populate RCA and postmortem docs with real timeline data
Add format_event_type() and calculate_duration() helpers to convert
raw timeline events into human-readable tables and metrics. RCA now
includes an Incident Timeline section and Incident Metrics (event
count, duration, time-to-root-cause). Postmortem replaces placeholder
timeline rows with real events, calculates impact duration, and
auto-populates What Went Well from evidence.

10 new Rust tests covering timeline rendering, duration calculation,
and event type formatting.
2026-04-19 18:13:30 -05:00
Shaun Arman
107fee8853 feat: add timeline_events table, model, and CRUD commands
- Add migration 017_create_timeline_events with indexes
- Update TimelineEvent struct with issue_id, metadata, UTC string timestamps
- Add TimelineEvent::new() constructor with UUIDv7
- Add timeline_events field to IssueDetail
- Rewrite add_timeline_event to write to new table + audit_log (dual-write)
- Add get_timeline_events command for ordered retrieval
- Update get_issue to load timeline_events
- Update delete_issue to clean up timeline_events
- Register get_timeline_events in generate_handler
- Add migration tests for table, indexes, and cascade delete
- Fix flaky derive_aes_key test (env var race condition in parallel tests)
2026-04-19 18:02:38 -05:00
Shaun Arman
8c35e91aef Merge branch 'master' into fix/version-dynamic-build
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 1m8s
Test / frontend-typecheck (pull_request) Successful in 1m17s
Test / frontend-tests (pull_request) Successful in 1m23s
PR Review Automation / review (pull_request) Failing after 2m11s
Test / rust-clippy (pull_request) Successful in 6m11s
Test / rust-tests (pull_request) Successful in 9m7s
2026-04-14 21:09:11 -05:00
Shaun Arman
bc50a78db7 fix: correct WIQL syntax and escape_wiql implementation
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 10s
Test / frontend-typecheck (pull_request) Successful in 1m11s
Test / frontend-tests (pull_request) Successful in 1m12s
PR Review Automation / review (pull_request) Successful in 3m6s
Test / rust-clippy (pull_request) Successful in 3m49s
Test / rust-tests (pull_request) Successful in 5m4s
- Replace CONTAINS with ~ operator (correct WIQL syntax for text matching)
- Remove escaping of ~, *, ? which are valid WIQL wildcards
- Update tests to reflect correct escape_wiql behavior
2026-04-14 20:38:21 -05:00
Shaun Arman
e6d1965342 security: address all issues from automated PR review
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 10s
Test / frontend-typecheck (pull_request) Successful in 1m9s
Test / frontend-tests (pull_request) Successful in 1m13s
PR Review Automation / review (pull_request) Successful in 2m58s
Test / rust-clippy (pull_request) Successful in 3m50s
Test / rust-tests (pull_request) Successful in 5m12s
- Add missing CQL escaping for &, |, +, - characters
- Improve escape_wiql() to escape more dangerous characters: ", \, (, ), ~, *, ?, ;, =
- Sanitize HTML in excerpts using strip_html_tags() to prevent XSS
- Add unit tests for escape_wiql, escape_cql, canonicalize_url functions
- Document expand_query() behavior (always returns at least original query)
- All tests pass (158/158), cargo fmt and clippy pass
2026-04-14 20:26:05 -05:00
Shaun Arman
708e1e9c18 security: fix query expansion issues from PR review
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 12s
Test / frontend-typecheck (pull_request) Successful in 1m11s
Test / frontend-tests (pull_request) Successful in 1m16s
PR Review Automation / review (pull_request) Successful in 3m0s
Test / rust-clippy (pull_request) Successful in 3m50s
Test / rust-tests (pull_request) Successful in 5m0s
- Use MAX_EXPANDED_QUERIES constant in confluence_search.rs instead of hardcoded 3
- Improve escape_wiql() to escape more dangerous characters: ", \, (, ), ~, *, ?, ;, =
- Fix logging to show expanded_query instead of search_url in confluence_search.rs

All tests pass (142/142), cargo fmt and clippy pass.
2026-04-14 20:07:59 -05:00
Shaun Arman
5b45c6c418 fix(integrations): security and correctness improvements
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 12s
Test / frontend-typecheck (pull_request) Successful in 1m18s
Test / frontend-tests (pull_request) Successful in 1m21s
Test / rust-clippy (pull_request) Successful in 3m56s
PR Review Automation / review (pull_request) Successful in 4m20s
Test / rust-tests (pull_request) Successful in 5m22s
- Add url canonicalization for deduplication (strip fragments/query params)
- Add WIQL injection escaping for Azure DevOps work item searches
- Add CQL injection escaping for Confluence searches
- Add MAX_EXPANDED_QUERIES constant for consistency
- Fix logging to show expanded_query instead of search_url
- Add input validation for empty queries
- Add url crate dependency for URL parsing

All 142 tests pass.
2026-04-14 19:55:32 -05:00
Shaun Arman
096068ed2b feat(integrations): implement query expansion for semantic search
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 12s
Test / frontend-typecheck (pull_request) Successful in 1m11s
Test / frontend-tests (pull_request) Successful in 1m15s
PR Review Automation / review (pull_request) Successful in 3m13s
Test / rust-clippy (pull_request) Successful in 3m45s
Test / rust-tests (pull_request) Successful in 5m9s
- Add query_expansion.rs module with product synonyms and keyword extraction
- Update confluence_search.rs to use expanded queries
- Update servicenow_search.rs to use expanded queries
- Update azuredevops_search.rs to use expanded queries
- Update webview_fetch.rs to use expanded queries
- Fix extract_keywords infinite loop bug for non-alphanumeric endings

All 142 tests pass.
2026-04-14 19:37:27 -05:00
Shaun Arman
9e1a9b1d34 feat: implement dynamic versioning from Git tags
Some checks failed
Test / rust-clippy (pull_request) Failing after 15s
Test / rust-tests (pull_request) Failing after 19s
Test / rust-fmt-check (pull_request) Successful in 55s
Test / frontend-typecheck (pull_request) Successful in 1m22s
Test / frontend-tests (pull_request) Successful in 1m26s
PR Review Automation / review (pull_request) Successful in 2m57s
- Add build.rs to read version from git describe --tags
- Create update-version.mjs script to sync version across files
- Add get_app_version() command to Rust backend
- Update App.tsx to use custom version command
- Run version update in CI before Rust checks
2026-04-13 16:12:03 -05:00
Shaun Arman
8e1d43da43 fix: address critical AI review issues
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 28s
Test / frontend-typecheck (pull_request) Successful in 1m29s
Test / frontend-tests (pull_request) Successful in 1m31s
PR Review Automation / review (pull_request) Successful in 3m28s
Test / rust-clippy (pull_request) Successful in 4m29s
Test / rust-tests (pull_request) Successful in 5m42s
- Fix linuxdeploy AppImage extraction using --appimage-extract
- Remove 'has no column named' from duplicate column error handling
- Use strftime instead of datetime for created_at default format
2026-04-13 08:50:34 -05:00
Shaun Arman
2d7aac8413 fix: address AI review findings
All checks were successful
Test / rust-fmt-check (pull_request) Successful in 15s
Test / frontend-typecheck (pull_request) Successful in 1m21s
Test / frontend-tests (pull_request) Successful in 1m25s
PR Review Automation / review (pull_request) Successful in 3m32s
Test / rust-clippy (pull_request) Successful in 4m1s
Test / rust-tests (pull_request) Successful in 5m18s
- Add -L flag to curl for linuxdeploy redirects
- Split migration 015 into 015_add_use_datastore_upload and 016_add_created_at
- Use separate execute calls for ALTER TABLE statements
- Add idempotency test for migration 015
- Use bool type for use_datastore_upload instead of i64
2026-04-13 08:38:43 -05:00
Shaun Arman
84c69fbea8 fix: add missing ai_providers columns and fix linux-amd64 build
Some checks failed
Test / rust-fmt-check (pull_request) Successful in 15s
Test / rust-clippy (pull_request) Failing after 17s
Test / frontend-typecheck (pull_request) Successful in 1m23s
Test / frontend-tests (pull_request) Successful in 1m23s
PR Review Automation / review (pull_request) Successful in 3m16s
Test / rust-tests (pull_request) Successful in 4m19s
- Add migration 015 to add use_datastore_upload and created_at columns
- Handle column-already-exists errors gracefully
- Update Dockerfile to install linuxdeploy for AppImage bundling
- Add fuse dependency for AppImage support
2026-04-13 08:22:08 -05:00
Shaun Arman
68d815e3e1 fix: add missing ai_providers migration (014)
All checks were successful
Test / frontend-tests (pull_request) Successful in 1m13s
Test / frontend-typecheck (pull_request) Successful in 1m15s
Test / rust-fmt-check (pull_request) Successful in 2m48s
Test / rust-clippy (pull_request) Successful in 18m34s
Test / rust-tests (pull_request) Successful in 20m17s
- 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
2026-04-10 12:03:22 -05:00
Shaun Arman
6ebe3612cd fix: lint fixes and formatting cleanup
All checks were successful
Test / frontend-tests (pull_request) Successful in 1m9s
Test / frontend-typecheck (pull_request) Successful in 1m15s
Test / rust-fmt-check (pull_request) Successful in 2m44s
Test / rust-clippy (pull_request) Successful in 24m22s
Test / rust-tests (pull_request) Successful in 25m43s
- Fix TypeScript lint errors in setup.ts and LogUpload
- Remove unused imports and variables
- Fix duplicate Separator exports in ui/index.tsx
- Apply cargo fmt formatting to Rust code
- Update ESLint configuration
2026-04-09 20:42:40 -05:00
Shaun Arman
420411882e feat: support GenAI datastore file uploads and fix paste image upload
Some checks failed
Test / frontend-tests (pull_request) Successful in 59s
Test / frontend-typecheck (pull_request) Successful in 1m5s
Test / rust-fmt-check (pull_request) Failing after 2m25s
Test / rust-clippy (pull_request) Failing after 18m25s
Test / rust-tests (pull_request) Successful in 19m42s
- 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
2026-04-09 18:05:44 -05:00
Shaun Arman
e83dc19dcc chore: Format Rust code after merge
All checks were successful
Test / frontend-typecheck (pull_request) Successful in 59s
Test / frontend-tests (pull_request) Successful in 57s
Test / rust-fmt-check (pull_request) Successful in 2m13s
Test / rust-clippy (pull_request) Successful in 16m57s
Test / rust-tests (pull_request) Successful in 18m36s
2026-04-08 21:03:36 -05:00
Shaun Arman
d83e8598e0 Merge branch 'bug/branch-creation' into feat/image-attachments
Some checks failed
Test / frontend-typecheck (pull_request) Successful in 1m4s
Test / frontend-tests (pull_request) Successful in 57s
Test / rust-fmt-check (pull_request) Failing after 2m19s
Test / rust-tests (pull_request) Has been cancelled
Test / rust-clippy (pull_request) Has been cancelled
2026-04-08 20:58:25 -05:00
Shaun Arman
f6f48b934b fix: Fix encryption test race condition with parallel tests
Some checks failed
Test / frontend-tests (pull_request) Failing after 59s
Test / frontend-typecheck (pull_request) Failing after 1m1s
Test / rust-fmt-check (pull_request) Failing after 2m8s
Test / rust-clippy (pull_request) Has been cancelled
Test / rust-tests (pull_request) Has been cancelled
- 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
2026-04-08 20:55:37 -05:00
Shaun Arman
9f6cab2436 fix: OpenWebUI provider connection and missing command registrations
- 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
2026-04-08 20:44:51 -05:00
Shaun Arman
19cc78a05f feat: add image attachment support with PII detection
Some checks failed
Test / frontend-tests (pull_request) Successful in 1m4s
Test / frontend-typecheck (pull_request) Failing after 1m6s
Test / rust-fmt-check (pull_request) Successful in 2m42s
Test / rust-clippy (pull_request) Successful in 19m1s
Test / rust-tests (pull_request) Failing after 20m7s
- Add image_attachments table to database schema (migration 013)
- Implement image upload, list, delete, and clipboard paste commands
- Add image file PII detection with user approval workflow
- Register image attachment commands in Tauri IPC
- Update TypeScript types and frontend components
- Add unit tests for image attachment functionality
- Update README and wiki documentation
2026-04-08 20:03:34 -05:00
Shaun Arman
9a132cce74 fix(fmt): apply rustfmt formatting to webview_fetch.rs
Some checks failed
Test / frontend-tests (pull_request) Successful in 2m10s
Test / frontend-typecheck (pull_request) Failing after 2m16s
Test / rust-fmt-check (pull_request) Has been cancelled
Test / rust-tests (pull_request) Has been cancelled
Test / rust-clippy (pull_request) Has been cancelled
Adjusted line breaks to match rustfmt conventions

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-04-07 09:47:57 -05:00
Shaun Arman
ead585f583 fix(lint): resolve all clippy warnings for CI compliance
Fixed 42 clippy warnings across integration and command modules:
- unnecessary_lazy_evaluations: Changed unwrap_or_else to unwrap_or
- uninlined_format_args: Modernized format strings to use inline syntax
- needless_borrows_for_generic_args: Removed unnecessary borrows
- only_used_in_recursion: Prefixed unused recursive param with underscore

All files now pass cargo clippy -- -D warnings

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-04-07 09:47:57 -05:00
Shaun Arman
1de50f1c87 chore: remove all proprietary vendor references for public release
- 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>
2026-04-07 09:46:25 -05:00
Shaun Arman
d294847210 fix(lint): use inline format args in auth.rs
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>
2026-04-07 09:35:35 -05:00
Shaun Arman
f0358cfb13 fix(db,auth): auto-generate encryption keys for release builds
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>
2026-04-07 09:35:34 -05:00
Shaun Arman
9e8db9dc81 feat(ai): add tool-calling and integration search as AI data source
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>
2026-04-07 09:35:34 -05:00
Shaun Arman
9175faf0b4 refactor(ollama): remove download/install buttons — show plain install instructions only 2026-04-05 20:53:57 -05:00
Shaun Arman
2d02cfa9e8 style: apply cargo fmt to install_ollama_from_bundle 2026-04-05 19:41:59 -05:00
Shaun Arman
dffd26a6fd fix(security): add path canonicalization and actionable permission error in install_ollama_from_bundle 2026-04-05 19:34:47 -05:00
Shaun Arman
215c0ae218 feat(ui): fix model dropdown, auth prefill, PII persistence, theme toggle, and Ollama bundle
- 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.
2026-04-05 19:30:41 -05:00
Shaun Arman
d87b01b154 feat(rebrand): rename binary to trcaa and auto-generate DB key
- 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
2026-04-05 17:50:16 -05:00
Shaun Arman
abab5c3153 fix(security): enforce PII redaction before AI log transmission
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.
2026-04-05 10:08:16 -05:00
Shaun Arman
0a25ca7692 fix(pii): remove lookahead from hostname regex, fix fmt in analysis test
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.
2026-04-05 09:59:19 -05:00
Shaun Arman
281e676ad1 fix(security): harden secret handling and audit integrity
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
2026-04-04 23:37:05 -05:00
Shaun Arman
c4ea32e660 feat: add custom_rest provider mode and rebrand application name
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
2026-04-04 15:35:58 -05:00
Shaun Arman
0bc20f09f6 style: apply rustfmt output for clippy-related edits
Apply canonical rustfmt formatting in files touched by the clippy format-args cleanup so cargo fmt --check passes consistently in CI.

Made-with: Cursor
2026-04-04 15:10:17 -05:00
Shaun Arman
85a8d0a4c0 fix: resolve clippy format-args failures and OpenSSL vendoring issue
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
2026-04-04 15:05:13 -05:00
Shaun Arman
bdb63f3aee fix: resolve clippy uninlined_format_args in integrations and related modules
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>
2026-04-04 12:27:26 -05:00
Shaun Arman
a7903db904 fix: persist integration settings and implement persistent browser windows
Some checks failed
Release / build-macos-arm64 (push) Successful in 4m52s
Release / build-linux-amd64 (push) Has been cancelled
Release / build-linux-arm64 (push) Has been cancelled
Release / build-windows-amd64 (push) Has been cancelled
## 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>
2026-04-04 09:57:22 -05:00
Shaun Arman
fbce897608 feat: complete webview cookie extraction implementation
Some checks failed
Release / build-macos-arm64 (push) Successful in 5m4s
Release / build-windows-amd64 (push) Has been cancelled
Release / build-linux-amd64 (push) Has been cancelled
Release / build-linux-arm64 (push) Has been cancelled
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>
2026-04-03 17:31:48 -05:00