tftsr-devops_investigation/TICKET_PERSISTENT_WEBVIEWS.md
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

10 KiB

Ticket Summary - Persistent Browser Windows for Integration Authentication

Description

Implement persistent browser window sessions for integration authentication (Confluence, Azure DevOps, ServiceNow). Browser windows now persist across application restarts, eliminating the need to extract HttpOnly cookies via JavaScript (which fails due to browser security restrictions).

This follows a Playwright-style "piggyback" authentication approach where the browser window maintains its own internal cookie store, allowing the user to log in once and have the session persist indefinitely until they manually close the window.

Acceptance Criteria

  • Integration browser windows persist to database when created
  • Browser windows are automatically restored on app startup
  • Cookies are maintained automatically by the browser's internal store (no JavaScript extraction of HttpOnly cookies)
  • Windows can be manually closed by the user, which removes them from persistence
  • Database migration creates persistent_webviews table
  • Window close events are handled to update database and in-memory tracking

Work Implemented

1. Database Migration for Persistent Webviews

Files Modified:

  • src-tauri/src/db/migrations.rs:154-167

Changes:

  • Added migration 013_create_persistent_webviews to create the persistent_webviews table
  • Table schema includes:
    • id (TEXT PRIMARY KEY)
    • service (TEXT with CHECK constraint for 'confluence', 'servicenow', 'azuredevops')
    • webview_label (TEXT - the Tauri window identifier)
    • base_url (TEXT - the integration base URL)
    • last_active (TEXT timestamp, defaults to now)
    • window_x, window_y, window_width, window_height (INTEGER - for future window position persistence)
    • UNIQUE constraint on service (one browser window per integration)

2. Webview Persistence on Creation

Files Modified:

  • src-tauri/src/commands/integrations.rs:531-591

Changes:

  • Modified authenticate_with_webview command to persist webview state to database after creation
  • Stores service name, webview label, and base URL
  • Logs persistence operation for debugging
  • Sets up window close event handler to remove webview from tracking and database
  • Event handler properly clones Arc fields for 'static lifetime requirement
  • Updated success message to inform user that window persists across restarts

3. Webview Restoration on App Startup

Files Modified:

  • src-tauri/src/commands/integrations.rs:793-865 - Added restore_persistent_webviews function
  • src-tauri/src/lib.rs:60-84 - Added .setup() hook to call restoration

Changes:

  • Added restore_persistent_webviews async function that:
    • Queries persistent_webviews table for all saved webviews
    • Recreates each webview window by calling authenticate_with_webview
    • Updates in-memory tracking map
    • Removes from database if restoration fails
    • Logs all operations for debugging
  • Updated lib.rs to call restoration in .setup() hook:
    • Clones Arc fields from AppState for 'static lifetime
    • Spawns async task to restore webviews
    • Logs warnings if restoration fails

4. Window Close Event Handling

Files Modified:

  • src-tauri/src/commands/integrations.rs:559-591

Changes:

  • Added on_window_event listener to detect window close events
  • On CloseRequested event:
    • Spawns async task to clean up
    • Removes service from in-memory integration_webviews map
    • Deletes entry from persistent_webviews database table
    • Logs all cleanup operations
  • Properly handles Arc cloning to avoid lifetime issues in spawned task

5. Removed Auto-Close Behavior

Files Modified:

  • src-tauri/src/commands/integrations.rs:606-618

Changes:

  • Removed automatic window closing in extract_cookies_from_webview
  • Windows now stay open after cookie extraction
  • Updated success message to inform user that window persists for future use

6. Frontend UI Update - Removed "Complete Login" Button

Files Modified:

  • src/pages/Settings/Integrations.tsx:371-409 - Updated webview authentication UI
  • src/pages/Settings/Integrations.tsx:140-165 - Simplified handleConnectWebview
  • src/pages/Settings/Integrations.tsx:167-200 - Removed handleCompleteWebviewLogin function
  • src/pages/Settings/Integrations.tsx:16-26 - Removed unused extractCookiesFromWebviewCmd import
  • src/pages/Settings/Integrations.tsx:670-677 - Updated authentication method comparison text

Changes:

  • Removed "Complete Login" button that tried to extract cookies via JavaScript
  • Updated UI to show success message when browser opens, explaining persistence
  • Removed confusing two-step flow (open browser → complete login)
  • New flow: click "Open Browser" → log in → leave window open (that's it!)
  • Updated description text to explain persistent window behavior
  • Mark integration as "connected" immediately when browser opens
  • Removed unused function and import for cookie extraction

7. Unused Import Cleanup

Files Modified:

  • src-tauri/src/integrations/webview_auth.rs:2
  • src-tauri/src/lib.rs:13 - Added use tauri::Manager;

Changes:

  • Removed unused Listener import from webview_auth.rs
  • Added Manager trait import to lib.rs for .state() method

Testing Needed

Manual Testing

  1. Initial Browser Window Creation

    • Navigate to Settings > Integrations
    • Configure a Confluence integration with base URL
    • Click "Open Browser" button
    • Verify browser window opens with Confluence login page
    • Complete login in the browser window
    • Verify window stays open after login
  2. Window Persistence Across Restarts

    • With Confluence browser window open, close the main application
    • Relaunch the application
    • Verify Confluence browser window is automatically restored
    • Verify you are still logged in (cookies maintained)
    • Navigate to different pages in Confluence to verify session works
  3. Manual Window Close

    • With browser window open, manually close it (X button)
    • Restart the application
    • Verify browser window does NOT reopen (removed from persistence)
  4. Database Verification

    • Open database: sqlite3 ~/Library/Application\ Support/trcaa/data.db
    • Run: SELECT * FROM persistent_webviews;
    • Verify entry exists when window is open
    • Close window and verify entry is removed
  5. Multiple Integration Windows

    • Open browser window for Confluence
    • Open browser window for Azure DevOps
    • Restart application
    • Verify both windows are restored
    • Close one window
    • Verify only one is removed from database
    • Restart and verify remaining window still restores
  6. Cookie Persistence (No HttpOnly Extraction Needed)

    • Log into Confluence browser window
    • Close main application
    • Relaunch application
    • Navigate to a Confluence page that requires authentication
    • Verify you are still logged in (cookies maintained by browser)

Automated Testing

# Type checking
npx tsc --noEmit

# Rust compilation
cargo check --manifest-path src-tauri/Cargo.toml

# Rust tests
cargo test --manifest-path src-tauri/Cargo.toml

# Rust linting
cargo clippy --manifest-path src-tauri/Cargo.toml -- -D warnings

Edge Cases to Test

  • Application crash while browser window is open (verify restoration on next launch)
  • Database corruption (verify graceful handling of restore failures)
  • Window already exists when trying to create duplicate (verify existing window is focused)
  • Network connectivity lost during window restoration (verify error handling)
  • Multiple rapid window open/close cycles (verify database consistency)

Architecture Notes

Problem: HttpOnly cookies cannot be accessed via JavaScript (document.cookie), which broke the original cookie extraction approach for Confluence and other services.

Solution: Instead of extracting cookies, keep the browser window alive across app restarts:

  • Browser maintains its own internal cookie store (includes HttpOnly cookies)
  • Cookies are automatically sent with all HTTP requests from the browser
  • No need for JavaScript extraction or manual token management
  • Matches Playwright's approach of persistent browser contexts

Lifecycle Flow

  1. Window Creation: User clicks "Open Browser" → authenticate_with_webview creates window → State saved to database
  2. App Running: Window stays open, user can browse freely, cookies maintained by browser
  3. Window Close: User closes window → Event handler removes from database and memory
  4. App Restart: restore_persistent_webviews queries database → Recreates all windows → Windows resume with original cookies

Database Schema

CREATE TABLE persistent_webviews (
    id TEXT PRIMARY KEY,
    service TEXT NOT NULL CHECK(service IN ('confluence','servicenow','azuredevops')),
    webview_label TEXT NOT NULL,
    base_url TEXT NOT NULL,
    last_active TEXT NOT NULL DEFAULT (datetime('now')),
    window_x INTEGER,
    window_y INTEGER,
    window_width INTEGER,
    window_height INTEGER,
    UNIQUE(service)
);

Future Enhancements

  • Save and restore window position/size (columns already exist in schema)
  • Add "last_active" timestamp updates on window focus events
  • Implement "Close All Windows" command for cleanup
  • Add visual indicator in main UI showing which integrations have active browser windows
  • Implement session timeout logic (close windows after X days of inactivity)
  • src-tauri/src/db/migrations.rs - Database schema migration
  • src-tauri/src/commands/integrations.rs - Webview persistence and restoration logic
  • src-tauri/src/integrations/webview_auth.rs - Browser window creation
  • src-tauri/src/lib.rs - App startup hook for restoration
  • src-tauri/src/state.rs - AppState structure with integration_webviews map

Security Considerations

  • Cookie storage remains in the browser's internal secure store (not extracted to database)
  • Database only stores window metadata (service, label, URL)
  • No credential information persisted beyond what the browser already maintains
  • Audit log still tracks all integration API calls separately

Migration Path

Users upgrading to this version will:

  1. See new database migration 013_create_persistent_webviews applied automatically
  2. Existing integrations continue to work (migration is additive only)
  3. First time opening a browser window will persist it for future sessions
  4. No manual action required from users