# Search Features Documentation

**Last Updated:** 2026-05-07
**Status:** Active Maintenance Documentation

**Note:** This document consolidates content from multiple search-related files:

- `search-functionality-fixes.md` - Search modes, behavior by service, troubleshooting.
- `search-path-column-feature.md` - Path column implementation.
- `FEATURE-first-search-info-banner.md` - First search banner feature.
- `EXPLANATION-onedrive-search-banner-behavior.md` - OneDrive banner behavior.
- Various bugfix and update files (BUGFIX-_, FIX-_, UPDATE-\*).

## Table of Contents

1. [Overview](#overview)
2. [Search Modes](#search-modes)
3. [Search Behavior by Service](#search-behavior-by-service)
4. [First Search Info Banner](#first-search-info-banner)
5. [Search Path Column](#search-path-column)
6. [Service and Account Facets](#service-and-account-facets)
7. [OneDrive Search Behavior](#onedrive-search-behavior)
8. [OneDrive Search Performance Optimization](#onedrive-search-performance-optimization)
9. [Troubleshooting](#troubleshooting)
10. [Related Files](#related-files)

---

## Overview

This document consolidates all search-related features in Stratofusion, including:

- **Search Modes** - Basic, Full-Text, and AI search capabilities.
- **Search Behavior by Service** - Google Drive, OneDrive, and Dropbox search characteristics.
- **First Search Info Banner** - Session-aware informational banner for first-time searches.
- **Search Path Column** - Displays full folder paths in search results.
- **Service and Account Facets** - Restricts search execution and displayed results to selected service/account context.
- **OneDrive Search Behavior** - Service-specific search implementation and limitations.
- **OneDrive Search Performance Optimization** - 3-tier search strategy for 10-30x performance improvement.
- **Troubleshooting** - Common search issues and solutions.

---

## Search Modes

### Basic Search (Free)

**What it searches:** File and folder names only
**Use when:** You know the filename or part of it
**Example:** Searching "budget" finds "Budget_2024.xlsx"

**How it works:**

- Searches file and folder names using metadata.
- Fast and efficient (typically < 1 second).
- Available on all cloud services.
- No subscription required.

### Full-Text Search (Premium)

**What it searches:** File contents AND filenames
**Use when:** You remember what's inside a file but not its name
**Example:** Searching "quarterly revenue" finds files containing that phrase

**How it works:**

- Searches inside document content.
- Supports 30+ file types (PDF, DOCX, XLSX, TXT, etc.).
- Requires premium subscription.
- Performance varies by service (1-30 seconds).

**Supported File Types:**

- Documents: PDF, DOC, DOCX, TXT, RTF, ODT.
- Spreadsheets: XLS, XLSX, CSV, ODS.
- Presentations: PPT, PPTX, ODP.
- Code: JS, TS, PY, JAVA, CPP, CS, GO, RB, PHP.
- Web: HTML, CSS, JSON, XML, YAML.
- And more...

### AI Search

**Status:** Implemented behind runtime rollout flags
**Availability:** Pro and Unlimited plans when `AI_SEARCH_ENABLED` and the provider-specific AI flags are enabled
**What it searches:** Indexed semantic chunks plus keyword fallback results
**Use when:** You want meaning-aware results over supported indexed files
**Example:** "Find the deployment rollback notes" can match a document that discusses release recovery even if the exact words differ
**Developer reference:** [AI Search Architecture](./developer/modules/AI_SEARCH_ARCHITECTURE.md)

**Implemented Features:**

- Runtime-gated semantic search for Google Drive, OneDrive, and Dropbox.
- Account and folder scoped AI indexing with visible progress.
- Deterministic PDF text extraction for PDFs that contain embedded text.
- Deterministic DOCX text extraction for DOCX files with extractable plain text.
- Deterministic XLSX text extraction for visible worksheets with extractable cell values.
- Deterministic PPTX text extraction for non-hidden slides and speaker notes.
- Export-based Google Workspace indexing for Google Docs, Sheets, Slides, and Drawings.
- Opt-in local OCR for standalone PNG/JPEG images when `AI_SEARCH_OCR_ENABLED=true`.
- Durable indexing diagnostics with per-job progress, extraction method breakdowns, error taxonomy, retryability guidance, and file-level status.
- Hybrid semantic and keyword result merging.
- Safe keyword fallback when semantic infrastructure is unavailable.
- Ask AI responses that return only citation-backed answers when RAG is enabled.

**Current Status:**
AI search infrastructure is disabled by default. Internal rollout requires `AI_SEARCH_ENABLED=true`, configured embedding and vector backends, and at least one provider flag such as `AI_SEARCH_GOOGLE_DRIVE_ENABLED=true`. Indexing is intentionally limited to deterministic formats in v1: plain text, Markdown/MDX, source code, JSON/YAML/XML/CSV/TSV/HTML/SVG, similar explicit text-like allow-list entries, PDFs that contain extractable embedded text, DOCX files with extractable text, XLSX spreadsheets with extractable visible cell values, PPTX presentations with extractable slide text and speaker notes, standalone PNG/JPEG images when OCR is enabled, and Google Workspace files exported from Google Drive before extraction. Google Docs export to DOCX, Google Sheets export to XLSX, Google Slides export to PPTX, and Google Drawings export to PDF. Exported bytes are not cached; each indexing run exports fresh content, enforces the configured extraction byte limit on exported content, and preserves the original Workspace file metadata for indexed chunks.

OCR is disabled by default and is controlled by the AI-search namespaced flag `AI_SEARCH_OCR_ENABLED`. When enabled, standalone PNG/JPEG files are processed by the local `tesseract.js` provider with the configured timeout, confidence threshold, and image/page limits. OCR adds indexing latency and accuracy varies with image quality, language, resolution, and layout. OCR output may include recognition errors that affect semantic search quality.

PDF indexing does not render pages for OCR in Phase 6A because safe Node PDF rasterization would require additional native canvas dependencies and Fly.io/Vercel deployment validation. Scanned PDFs, Google Drawings exported as image-only PDFs, and PDFs with no embedded text therefore remain unsupported with a renderer-unavailable reason when OCR is enabled. DOCX indexing uses `mammoth.extractRawText` for plain text extraction, preserving paragraph breaks and basic reading order where Mammoth provides it. Legacy `.doc`, password-protected/encrypted documents, embedded image extraction, OCR, charts, SmartArt, complex formatting preservation, tracked-change/comment metadata, RTF, ODT, and broad Office parsing remain unsupported. Empty DOCX files produce empty extractor output and are skipped as no-text items; corrupt DOCX files fail with `extraction_docx_parse_failed`, and encrypted DOCX files fail or skip with `extraction_docx_encrypted`. XLSX indexing reads visible worksheets in workbook order, prefixes each non-empty sheet with a `--- Sheet: SheetName ---` delimiter, joins non-empty cell values row by row with tabs, uses cached/displayed formula results when present, and does not index formula syntax. Empty XLSX files skip with `extraction_xlsx_no_text`, corrupt or timed-out XLSX extraction fails with `extraction_xlsx_parse_failed`, and encrypted XLSX skips or fails with `extraction_xlsx_encrypted`; all messages are sanitized. PPTX indexing reads slide order from `ppt/presentation.xml`, follows presentation relationships to each slide, emits non-empty slides as `Slide N:` blocks in presentation order, and follows slide relationships to extract speaker notes from identifiable notes-body placeholders. Hidden PPTX slides are skipped when the slide root reliably marks `show="0"` or `show="false"`; if a producer stores hidden state elsewhere, the slide may still be extracted. Empty PPTX files skip with `extraction_pptx_no_text`, encrypted PPTX files skip with `extraction_pptx_encrypted`, and corrupt, malformed, or timed-out PPTX parsing fails with `extraction_pptx_parse_failed`; all PPTX taxonomy messages are sanitized and do not expose raw XML, raw parser details, file paths, stack traces, or slide text. Google Forms, Sites, Maps, Jamboard, Apps Script, Shortcuts, third-party Drive app files, legacy `.xls`, legacy `.ppt`, ODP, Keynote, ODS, Numbers, other Office formats, media, archives, charts, SmartArt, images, macros, embedded presentation media, animations, transitions, speaker timings, OCR-only PDF content, master slide/layout template text, image alt text, GIF, TIFF, BMP, WebP, HEIC, cloud OCR providers, OCR caching, preprocessing, handwriting guarantees, complex table structure extraction, form field detection, mathematical equation extraction, and other binary formats remain unsupported without indexing raw bytes.

PPTX extraction is a narrow server-side OpenXML path, chosen over generator-oriented or broad document-parser packages to keep production behavior deterministic and sanitized. It uses `jszip` under the package's MIT license option and `fast-xml-parser` under MIT; both provide TypeScript types and work in the Vitest and Next.js server build paths without external Office binaries.

Google Workspace export uses the Google Drive `files.export()` path for the source account and a configurable default 30 second export timeout. Permission, quota, network/provider, timeout, unsupported-type, and invalid-provider failures fail the individual indexing item with sanitized messages and stable taxonomy codes. Export network, quota/permission, and timeout failures are retryable; unsupported Workspace types and invalid-provider requests are not retryable. Successful exports that contain no extractable text are skipped as unsupported. Unsupported Google Workspace types include Forms, Sites, Maps, Fusion Tables, Jamboard, Apps Script, Shortcuts, and third-party Drive app files.

AI indexing records durable item-level telemetry for diagnostics: processing stage, extraction method, timing, text length, token/chunk counts, embedding and semantic-upsert timings, OCR metadata, and sanitized taxonomy codes. Before discovery, indexing verifies that the configured semantic index backend can bootstrap its collection; if that backend is unavailable, the run fails fast with a semantic-index failure reason instead of marking every eligible file failed. `/user/ai-indexing` exposes a compact health summary and a diagnostics dialog with progress, ETA when enough throughput data exists, method and error breakdowns, retryable/non-retryable counts, latency percentiles, unsupported file-type groups, and capped affected-item samples using authorized file names from user-owned rows. Health percentages use eligible-file coverage while unsupported-by-policy files are counted separately. The Properties dialog can show current indexing status for a single file when the file browser already has service/account/resource identity. Diagnostics avoid raw provider paths, extracted text, stack traces, OAuth tokens, and raw provider errors.

---

## Search Behavior by Service

### Google Drive ⭐⭐⭐⭐⭐

| Feature         | Basic Search     | Full-Text Search |
| --------------- | ---------------- | ---------------- |
| **Speed**       | Very Fast (< 1s) | Fast (1-3s)      |
| **Accuracy**    | Excellent        | Excellent        |
| **File Types**  | All              | 30+ types        |
| **Limitations** | None             | None             |

**Strengths:**

- ✅ Fastest search across all services.
- ✅ Excellent full-text indexing.
- ✅ Supports all file types.
- ✅ No API limitations.

### OneDrive ⭐⭐⭐⭐

| Feature         | Basic Search  | Full-Text Search         |
| --------------- | ------------- | ------------------------ |
| **Speed**       | Fast (< 1-3s) | Variable (3-30s)         |
| **Accuracy**    | Excellent     | Good                     |
| **File Types**  | All           | Limited for MSA accounts |
| **Limitations** | None          | MSA account restrictions |

**Strengths:**

- ✅ Fast filename search (optimized with 3-tier strategy).
- ✅ Good full-text search for business accounts.
- ✅ Reliable metadata search.

**Known Issues:**

- ⚠️ **Personal Accounts (MSA):** Limited content indexing for code/config files.
- ⚠️ **First Search:** May be slower due to indexing (mitigated with optimization).
- ℹ️ This is a Microsoft API limitation, not a bug in our implementation.

**Optimization:**
See [OneDrive Search Performance Optimization](#onedrive-search-performance-optimization) for details on the 3-tier search strategy.

### Dropbox ⭐⭐⭐⭐

| Feature         | Basic Search | Full-Text Search       |
| --------------- | ------------ | ---------------------- |
| **Speed**       | Fast (< 2s)  | Fast (2-5s)            |
| **Accuracy**    | Excellent    | Good                   |
| **File Types**  | All          | 30+ types              |
| **Limitations** | None         | File type restrictions |

**Strengths:**

- ✅ Fast and reliable search.
- ✅ Good full-text search support.
- ✅ Consistent performance.

**Known Issues:**

- ⚠️ Full-text search limited to specific file types.

### Recommendations for Users

**When to Use Basic Search:**

- ✅ You know the filename or part of it.
- ✅ You want fast results.
- ✅ You're searching for folders.
- ✅ You're on a free plan.

**When to Use Full-Text Search:**

- ✅ You remember content but not the filename.
- ✅ You're searching for specific phrases or keywords.
- ✅ You need comprehensive results.
- ✅ You have a premium subscription.

**Best Practices:**

1. **Start with Basic Search** - It's faster and often sufficient
2. **Use specific keywords** - More specific = better results
3. **Try different variations** - "budget" vs "Budget_2024"
4. **Check file types** - Some services have limitations
5. **Be patient on first search** - Indexing may take time

---

## First Search Info Banner

### Purpose

Provides users with context about potentially slower first searches due to server-side initialization processes like indexing, caching, and service authentication.

### Implementation

**Component:** `src/components/search/FirstSearchInfoBanner.tsx`

**Key Features:**

- **Session Tracking**: Uses `sessionStorage` with key `first-search-info-seen`.
- **Automatic Display**: Shows when `isSearching` becomes true for the first time in a session.
- **Manual Dismissal**: Users can close the banner with an X button.
- **Accessibility**: Includes ARIA attributes and screen reader announcements.
- **Mobile-Responsive**: Optimized for small screens.

### Session Storage Behavior

**How It Works:**

1. **On Component Mount:**
   - Checks `sessionStorage.getItem('first-search-info-seen')`.
   - If `"true"`, banner won't show.
   - If `null`, banner can show on first search.

2. **When First Search Starts:**
   - If not seen before AND search is active.
   - Shows the banner.
   - Immediately sets `sessionStorage.setItem('first-search-info-seen', 'true')`.
   - Sets internal state to prevent re-showing.

3. **When User Dismisses:**
   - Hides the banner visually.
   - sessionStorage already set to `"true"`.
   - Banner stays hidden for rest of session.

4. **New Browser Session:**
   - sessionStorage resets.
   - Banner appears on first search again.

### Message Content

> **First search of the session** may take a bit longer while we initialize indexing and caching. Subsequent searches will be faster.

### Visual Design

- **Color Scheme:** Blue info theme (not warning or error).
- **Border:** `border-blue-500/50`.
- **Background:** `bg-blue-50 dark:bg-blue-950/20`.
- **Icon:** Info icon from lucide-react.

### Accessibility Features

- `role="status"` on Alert component.
- `aria-live="polite"` for non-intrusive announcements.
- `aria-label` on dismiss button.
- `aria-hidden="true"` on decorative icons.
- Keyboard accessible dismiss button.
- Screen reader support with sr-only announcements.

### Testing

**Test Coverage:** 13 tests, all passing ✅

**Categories:**

1. Visibility Logic (4 tests)
2. Dismiss Functionality (3 tests)
3. Content and Styling (3 tests)
4. Error Handling (2 tests)
5. Session Behavior (1 test)

**Storybook Stories:** 8 stories covering different states and scenarios

### Related Files

- `src/components/search/FirstSearchInfoBanner.tsx` - Component implementation.
- `src/components/search/FirstSearchInfoBanner.stories.tsx` - Storybook stories.
- `src/components/search/__tests__/FirstSearchInfoBanner.test.tsx` - Test suite.
- `src/components/DriveUI.tsx` - Integration point.

---

## Search Path Column

### Purpose

Displays the full folder path for each file or folder in search results, helping users identify file locations across different folders and services.

### Implementation

**Path Utilities:** `src/lib/utils/path-utils.ts`, `src/lib/utils/item-paths.ts`

**Functions:**

- `formatPath(path, maxLength)` - Formats paths with intelligent truncation.
- `getFullPathForTooltip(path)` - Returns full path for tooltip display.
- `getParentPath(path)` - Extracts parent folder path.
- `getFilenameFromPath(path)` - Extracts filename from path.
- `toCanonicalItemPath(path)` - Normalizes provider service paths to `/parent/item`.

### Path Formatting Features

**Intelligent Truncation:**

1. For paths under max length: Display with readable separators (" / ")
2. For longer paths: Show first segment + "..." + last segment
3. For very long segments: Truncate individual segments with ellipsis in middle
4. Always preserve context by showing beginning and end

**Example Truncations:**

- Short: `Documents / Work` (no truncation).
- Medium: `Documents / ... / Projects` (middle folders hidden).
- Long: `Very Long Fold... / ... / Final Folder` (segments and folders truncated).

### Service-Specific Path Resolution

#### Google Drive

- Uses `buildFolderPathCache` method to resolve parent folder paths.
- Fetches folder information in parallel using Promise.all.
- Resolves complete parent chains with caching.
- Emits canonical paths with a leading `/`.

**Path Examples:**

- Root file: `/document.pdf`.
- Nested file: `/Documents/document.pdf`.
- Deeply nested file: `/Documents/Work/Projects/document.pdf`.

#### OneDrive

- Extracts path from `parentReference.path` (already in API response).
- Uses cached parent folder lookups for Microsoft Search results that omit `parentReference.path`.
- Works for both files and folders.

**Path Examples:**

- Root file: `/document.pdf`.
- Nested file: `/Documents/Work/document.pdf`.

#### Dropbox

- Uses `path_display` from API response.
- Preserves user-visible casing where possible.
- Emits canonical paths with a leading `/`.
- No additional API calls needed.

**Path Examples:**

- Root file: `/document.pdf`.
- Nested file: `/Documents/Work/document.pdf`.

### UI Integration

**DriveTable Component Updates:**

- Added "Path" column header (only visible when `isRecursiveSearch` is true).
- Adjusted column widths for search mode.
  - Name: 35% → 25%.
  - Path: 20% (new).
  - Modified: 20% → 15%.
- Added path sorting support (case-insensitive alphabetical).

**DriveItemRow Component:**

- Conditional path cell (only rendered in search mode).
- Displays formatted path with truncation (max 40 characters).
- Tooltip showing full path on hover.
- Uses TooltipProvider from shadcn/ui.

### Performance Considerations

**Google Drive:**

- Additional API calls: ~5-10 per search (depends on unique parent folders).
- Optimization: Parallel fetching, deduplication, memoized parent traversal.
- User impact: Minimal (< 500ms additional latency in most cases).

**OneDrive:**

- Additional API calls: 0.
- User impact: None.

**Dropbox:**

- Additional API calls: 0.
- User impact: None.

### Testing

**Test Coverage:** 34 tests for path utilities, all passing ✅

**Categories:**

- Path formatting with various lengths.
- Truncation behavior.
- Edge cases (undefined, empty, whitespace-only).
- Path separator normalization (Windows/Unix).
- Tooltip formatting.
- Parent path extraction.
- Filename extraction.

### Related Files

- `src/lib/utils/path-utils.ts` - Path formatting utilities.
- `src/lib/utils/path-utils.test.ts` - Test suite.
- `src/components/DriveTable.tsx` - Table component with path column.
- `src/components/DriveItemRow.tsx` - Row component with path cell.
- `src/services/GoogleDriveService.ts` - Google Drive path resolution.
- `src/services/OneDriveService.ts` - OneDrive path extraction.
- `src/lib/data-transformers.ts` - Dropbox path formatting.

---

## Service and Account Facets

### Summary

Search now honors the currently selected `Service` and `Account` filters.

- If no filter is selected: search runs across all connected accounts.
- If only a service is selected: search runs only for accounts in that service.
- If service + account are selected: search runs only for that account.

This applies to:

- Basic search (`/api/search`).
- Enhanced search (`/api/search/enhanced`).
- Streaming search (`/api/search/stream`).

### API Query Parameters

- `services`: comma-separated provider IDs (example: `google,onedrive`).
- `accountIds`: comma-separated connected account IDs.

Both parameters are optional. If provided, they are validated and used to filter active accounts before any provider search calls are dispatched.

### UI Behavior

- The `Service` and `Account` selectors remain the primary search facets.
- Search result rows are still rendered through the same table pipeline, and facet filtering is applied consistently in search mode and non-search mode.
- Search reruns triggered by mode changes or post-operation refreshes keep the same facet constraints.

---

## OneDrive Search Behavior

### Overview

OneDrive search behavior varies significantly based on account type. This section explains the implementation, limitations, and banner display logic.

### Account Type Detection

**Method:** Microsoft Graph API `driveType` property

**Implementation:**

```typescript
async function getOneDriveDriveType(
  token: TokenData,
): Promise<"personal" | "business" | "unknown"> {
  const response = await fetch("https://graph.microsoft.com/v1.0/me/drive", {
    headers: { Authorization: `Bearer ${token.access_token}` },
  });
  const driveData = await response.json();
  return driveData.driveType; // 'personal' or 'business'
}
```

**Why Not Email Pattern Matching:**

- Microsoft 365 Family accounts can use ANY email address (not just @outlook/@hotmail/@live/@msn).
- Email domain alone cannot distinguish between account types.
- Graph API `driveType` is the official, reliable method.

### Search Behavior by Account Type

| Account Type                  | DriveType  | Search API Used       | Content Indexing                     |
| ----------------------------- | ---------- | --------------------- | ------------------------------------ |
| Personal (Free)               | `personal` | Basic Search Endpoint | Limited (excludes code/config files) |
| Microsoft 365 Family/Personal | `personal` | Basic Search Endpoint | Limited (excludes code/config files) |
| OneDrive for Business         | `business` | Microsoft Search API  | Comprehensive                        |

### Content Indexing Limitations (Personal Accounts)

Personal OneDrive accounts have limited indexing for:

- **Code files:** .py, .js, .java, .cs, .cpp, .go, .rb, .php, etc.
- **Configuration files:** .json, .xml, .yaml, .env, .config, .ini, etc.
- **Web files:** .html, .css, .scss, .sass, .less, etc.

These files may not appear in full-text search results even if they contain matching content.

### SearchLimitationBanner Display Logic

**Current Implementation:**

- Shows for ALL OneDrive accounts in full-text mode.
- Uses blue "info" styling (not yellow "warning").
- Title: "OneDrive Search Information".

**Display Conditions:**

1. Service is OneDrive
2. Search mode is "fulltext" (not "basic" or "ai")

**Why Show for All Accounts:**

- Personal accounts (free + M365 Family) have documented limitations.
- M365 Family accounts can use any email address.
- Frontend doesn't currently receive `driveType` from backend.
- Showing banner for business accounts won't hurt (they have comprehensive search anyway).

**Future Improvement:**
Pass `driveType` from backend to frontend for more accurate banner display.

### Debugging OneDrive Search Issues

**Check Account Type:**

1. Look at OneDrive account email
2. If @outlook/@hotmail/@live/@msn → Likely MSA account
3. If custom domain (e.g., @company.com) → Likely Work/School account
4. Check browser console for `[ONEDRIVE] Detected drive type:` log message

**Check Search Mode:**

1. Look at search mode indicator in UI
2. "Basic Search" = filename-only search
3. "Full-text Search" = content search (where banner may appear)

**Check Browser Console:**
Look for log messages:

```
[ONEDRIVE FULL-TEXT] Account type detection { driveType: 'personal', ... }
[ONEDRIVE FULL-TEXT] Detected personal OneDrive account, using basic search endpoint
```

### Recommendations

**For Personal Account Users:**

1. **For Document Search:** Full-text search works well for .docx, .pdf, .txt, .pptx, .xlsx files
2. **For Code/Config Files:** Use Basic search (filename-only) or consider Google Drive
3. **For Best Results:** Use descriptive filenames, organize files in well-named folders

**For Work/School Account Users:**

1. Full-text search should work well for all file types
2. If not seeing results, check if files are in personal OneDrive or SharePoint
3. Verify access permissions with IT administrator

### Related Files

- `src/components/search/SearchLimitationBanner.tsx` - Banner component.
- `src/app/api/search/enhanced/route.ts` - Search API with OneDrive implementation.
- `src/services/OneDriveService.ts` - OneDrive service implementation.
- `src/hooks/useBannerDismissal.ts` - Banner dismissal state management.

---

## OneDrive Search Performance Optimization

**Date:** October 2025
**Status:** ✅ Implemented and Deployed
**Performance Improvement:** 10-30x faster for typical filename searches

### Problem Statement

OneDrive's first search was extremely slow, often taking 10-30 seconds or more to return results. This was caused by OneDrive's `/me/drive/root/search(q='...')` endpoint triggering full-text content indexing even when users only wanted to search filenames.

### Root Cause Analysis

The original implementation used OneDrive's standard search endpoint:

```typescript
const searchQuery = "/me/drive/root/search(q='" + query + "')";
```

**Issues with this approach:**

1. **Full-Text Indexing** - OneDrive indexes file content, not just filenames
2. **First-Search Penalty** - Initial searches trigger indexing, causing 10-30+ second delays
3. **Inefficient Filtering** - Client-side filtering after receiving results wastes bandwidth
4. **Inconsistent UX** - Much slower than Google Drive and Dropbox basic searches

### Solution: Three-Tier Search Strategy

The optimization implements an intelligent routing system that selects the fastest search method based on the search context.

#### 1. Folder-Specific Search (Fastest) ⚡

**When to use:** Searching within a specific folder (`folderId` provided, `fullText=false`)

**Implementation:**

```typescript
const filterQuery = `contains(name, '${escapedQuery}')`;
const response = await client
  .api(`/me/drive/items/${folderId}/children`)
  .filter(filterQuery)
  .select(OneDriveService.ONEDRIVE_ITEM_FIELDS)
  .top(maxResults)
  .get();
```

**Benefits:**

- ✅ No content indexing - searches only filenames.
- ✅ Instant results (typically < 1 second).
- ✅ Uses OData `$filter` with `contains()` function.
- ✅ Most efficient for folder-specific searches.

**API Endpoint:** `/me/drive/items/{folderId}/children?$filter=contains(name, 'query')`

**Documentation:** [OneDrive API - List Children](https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_list_children)

#### 2. Global Filename Search (Fast) 🚀

**When to use:** Global search across all files (`folderId` not provided, `fullText=false`)

**Implementation:**

```typescript
const kqlQuery = `filename:${query}`;
const searchRequest = {
  requests: [
    {
      entityTypes: ["driveItem"],
      query: { queryString: kqlQuery },
      from: 0,
      size: maxResults,
      fields: OneDriveService.SEARCH_REQUEST_FIELDS,
    },
  ],
};
const response = await client.api("/search/query").post(searchRequest);
```

**Benefits:**

- ✅ Searches only filenames using KQL `filename:` operator.
- ✅ Fast results (typically 1-3 seconds).
- ✅ Uses Microsoft Search API with targeted queries.
- ✅ Avoids full-text content indexing.

**API Endpoint:** `/search/query` with KQL query

**Documentation:** [Microsoft Search API](https://learn.microsoft.com/en-us/graph/api/resources/search-api-overview)

#### 3. Full-Text Search (Comprehensive) 📚

**When to use:** Content search requested (`fullText=true`)

**Implementation:**

```typescript
const searchQuery = `/me/drive/root/search(q='${query}')`;
const response = await client
  .api(searchQuery)
  .select(OneDriveService.ONEDRIVE_ITEM_FIELDS)
  .top(maxResults)
  .get();
```

**Benefits:**

- ✅ Searches file content, not just filenames.
- ✅ Comprehensive results including document text.
- ✅ Fallback for when fast methods fail.

**Performance:** 3-30 seconds (depending on indexing state)

### Search Routing Logic

The service automatically routes to the optimal search method:

```typescript
async search(options: SearchOptions): Promise<CloudStorageResponse<SearchResponse>> {
  const { query, folderId, fullText, maxResults = 100, accountId = "default" } = options;

  // Route to appropriate search method
  if (!fullText && folderId) {
    // Tier 1: Folder-specific search (fastest)
    return this.performFolderFilterSearch(client, accountId, folderId, query, maxResults);
  } else if (!fullText && !fileTypes?.length) {
    // Tier 2: Global filename search (fast)
    return this.performGlobalFilenameSearch(client, accountId, query, maxResults);
  } else {
    // Tier 3: Full-text search (comprehensive)
    return this.performBasicSearch(client, accountId, query, maxResults);
  }
}
```

### Performance Comparison

| Search Type       | Before | After | Improvement          |
| ----------------- | ------ | ----- | -------------------- |
| Folder-specific   | 10-30s | < 1s  | **10-30x faster**    |
| Global filename   | 10-30s | 1-3s  | **3-30x faster**     |
| Full-text content | 10-30s | 3-30s | Same (comprehensive) |

### Implementation Details

**Helper Methods:**

```typescript
// Query escaping for OData filters
private escapeODataQuery(query: string): string {
  return query.replace(/'/g, "''");
}

// KQL query construction
private buildFilenameKqlQuery(query: string): string {
  return `filename:${query}`;
}

// Standardized response building
private buildSearchResponse(
  items: DriveItemUnion[],
  accountId: string,
  nextPageToken?: string,
): CloudStorageResponse<SearchResponse> {
  return {
    success: true,
    data: { items, nextPageToken, hasMore: !!nextPageToken },
    metadata: { service: this.serviceType, accountId, timestamp: new Date().toISOString() },
  };
}
```

**Field Selection Constants:**

```typescript
private static readonly ONEDRIVE_ITEM_FIELDS =
  "id,name,folder,file,size,lastModifiedDateTime,parentReference,webUrl,thumbnails";

private static readonly SEARCH_REQUEST_FIELDS = [
  "id", "name", "folder", "file", "size",
  "lastModifiedDateTime", "parentReference", "webUrl"
];
```

### Error Handling & Fallbacks

Each optimized search method includes fallback to basic search:

```typescript
try {
  // Attempt optimized search
  return await this.performFolderFilterSearch(...);
} catch (error) {
  logger.warn('[ONEDRIVE FOLDER FILTER] Failed, falling back to basic search:', error);
  return this.performBasicSearch(client, accountId, query, maxResults);
}
```

**Fallback Scenarios:**

- API endpoint unavailable.
- Permission issues.
- Malformed queries.
- Network errors.

### Testing

**Test Coverage:** 34 OneDrive tests, all passing ✅

**Test Categories:**

1. **Search Optimization Tests** (9 tests)
   - Folder-specific search routing.
   - Global filename search routing.
   - Query escaping.
   - Fallback mechanisms.
   - Response formatting.

2. **Integration Tests** (17 tests)
   - Personal Vault filtering.
   - Filename matching.
   - Case-insensitive search.
   - Result limiting.

3. **Rename Tests** (8 tests)
   - File and folder renaming.
   - Error handling.

**Test File:** `src/services/__tests__/OneDriveService.search-optimization.test.ts`

### Code Quality Improvements

As part of this implementation, several code quality improvements were made following DRY principles and SOLID design:

**Refactorings Applied:**

- ✅ Extracted field selection constants (eliminates 6 instances of magic strings).
- ✅ Created `buildSearchResponse()` helper (eliminates ~40 lines of duplication).
- ✅ Created query escaping utilities (centralizes query construction).
- ✅ Improved separation of concerns with focused helper methods.

**Impact:**

- ~70 lines of duplicated code reduced to ~15 lines of reusable helpers.
- Single source of truth for field selections and response formatting.
- Better maintainability and testability.

See [Code Reviews - OneDrive Search Optimization](#onedrive-search-optimization-review) for detailed code review.

### Usage Examples

**Basic filename search in current folder:**

```typescript
const result = await oneDriveService.search({
  query: "report",
  folderId: "folder123",
  fullText: false,
  accountId: "default",
});
// Uses Tier 1: Folder-specific search (< 1s)
```

**Global filename search:**

```typescript
const result = await oneDriveService.search({
  query: "budget",
  fullText: false,
  accountId: "default",
});
// Uses Tier 2: Global filename search (1-3s)
```

**Full-text content search:**

```typescript
const result = await oneDriveService.search({
  query: "quarterly results",
  fullText: true,
  accountId: "default",
});
// Uses Tier 3: Full-text search (3-30s)
```

### Monitoring & Metrics

**Logging:**
All search operations include detailed logging:

```
[ONEDRIVE SEARCH] Using fast folder filter search { accountId, folderId, query, method }
[ONEDRIVE FOLDER FILTER] Search completed { accountId, folderId, query, totalResults, maxResults }
```

**Performance Tracking:**

- Search method used (Tier 1/2/3).
- Response time.
- Result count.
- Fallback occurrences.

### Future Enhancements

**Potential Improvements:**

1. **Caching** - Cache folder-specific search results for repeated queries
2. **Prefetching** - Prefetch common folder searches
3. **Query Suggestions** - Suggest queries based on filename patterns
4. **Performance Metrics** - Track and display search performance to users

### Related Files

- `src/services/OneDriveService.ts` - Main implementation.
- `src/services/__tests__/OneDriveService.search-optimization.test.ts` - Test suite.
- `docs/ONEDRIVE_SEARCH_OPTIMIZATION.md` - Original detailed documentation (archived).
- `docs/CODE_REVIEW_ONEDRIVE_SEARCH.md` - Code review documentation (archived).

### References

- [OneDrive API - List Children](https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_list_children).
- [Microsoft Search API](https://learn.microsoft.com/en-us/graph/api/resources/search-api-overview).
- [OData Filter Query Syntax](https://learn.microsoft.com/en-us/graph/query-parameters#filter-parameter).
- [KQL (Keyword Query Language)](https://learn.microsoft.com/en-us/sharepoint/dev/general-development/keyword-query-language-kql-syntax-reference).

---

## Troubleshooting

### "OneDrive returns fewer results than Google Drive"

**Cause:** OneDrive Personal (MSA) accounts have limited content indexing for certain file types.

**Solution:**

1. **Use Basic Search** - Searches filenames only, works for all file types
2. **Upgrade to Business Account** - Full-text search works better on OneDrive for Business
3. **Try Google Drive** - If you need comprehensive full-text search for code/config files

**Technical Details:**

- Microsoft Graph API limitation for MSA accounts.
- Affects: Code files (.js, .py, .java), config files (.json, .yaml, .env).
- Not a bug in Stratofusion - this is a Microsoft API restriction.

### "First search is very slow"

**Cause:** Cloud services need to initialize indexing on first search.

**Solution:**

1. **Be patient** - First search may take 10-30 seconds
2. **Subsequent searches are faster** - Indexing is cached
3. **Use folder-specific search** - Faster than global search
4. **Check the info banner** - Explains why first search is slower

**OneDrive Optimization:**

- Stratofusion uses a 3-tier search strategy for OneDrive.
- Folder-specific searches: < 1 second.
- Global filename searches: 1-3 seconds.
- Full-text searches: 3-30 seconds (depending on indexing state).

### "Search results don't include a file I know exists"

**Possible Causes:**

1. **File is in a filtered location** (e.g., OneDrive Personal Vault)
2. **File type not supported** for full-text search
3. **Permissions issue** - File not accessible to your account
4. **Indexing delay** - Recently uploaded files may not be indexed yet

**Solutions:**

1. **Try Basic Search** - Searches all files by name
2. **Check file location** - Some folders are excluded from search
3. **Verify permissions** - Ensure you have access to the file
4. **Wait and retry** - Give indexing time to complete (5-10 minutes)

### "Search is not working at all"

**Troubleshooting Steps:**

1. **Check authentication** - Ensure you're connected to the service
2. **Verify network connection** - Search requires internet access
3. **Try different search terms** - Use simpler, more specific keywords
4. **Check service status** - Cloud service may be experiencing issues
5. **Clear browser cache** - Sometimes helps with UI issues
6. **Contact support** - If problem persists

### "Path column shows '-' instead of folder path"

**Cause:** The provider service did not emit a canonical `path` for that item.

**Solution:**

- Search results should normally include `/parent/item` paths from the service layer.
- Check provider logs for folder path resolution failures.
- The UI should not perform breadcrumb lookups to repair missing item paths.

### Performance Tips

**For Faster Searches:**

1. **Use folder-specific search** when possible (faster than global)
2. **Start with Basic Search** (faster than Full-Text)
3. **Use specific keywords** (reduces result set)
4. **Limit search scope** (search in specific folder vs. entire drive)

**For Better Results:**

1. **Use multiple keywords** ("budget 2024" vs. just "budget")
2. **Try variations** ("resume" vs. "cv" vs. "curriculum vitae")
3. **Check spelling** (typos won't match)
4. **Use quotes for exact phrases** (in Full-Text search)

---

## Related Files

### Components

- `src/components/search/FirstSearchInfoBanner.tsx`.
- `src/components/search/SearchLimitationBanner.tsx`.
- `src/components/DriveTable.tsx`.
- `src/components/DriveItemRow.tsx`.

### Utilities

- `src/lib/utils/path-utils.ts`.

### Services

- `src/services/GoogleDriveService.ts`.
- `src/services/OneDriveService.ts`.
- `src/lib/data-transformers.ts`.

### API Routes

- `src/app/api/search/enhanced/route.ts`.

### Tests

- `src/components/search/__tests__/FirstSearchInfoBanner.test.tsx`.
- `src/lib/utils/path-utils.test.ts`.
- `src/services/__tests__/search-path-resolution.test.ts`.
