# SearchAuditEntries

## Overview

SearchAuditEntries searches and filters audit entries using multiple criteria: actor identity (actorType, actorId), entity reference (entityType, entityId), operation type, date range, company scope, and correlationId. Results are returned in chronological order by default and support pagination for efficient retrieval of large result sets.

This query requires the `viewAuditHistory` permission at the appropriate scope.

## Business Rules

- All filter parameters are optional; at least one must be provided
- Querying by actorId returns only entries for that actor
- Querying by entityType and entityId returns the full change history for a specific record
- Querying by operationType filters entries to only the specified operation
- Querying by date range returns only entries whose timestamp falls within the range
- An optional `scope` parameter accepts COMPANY, GLOBAL, or ALL to control which entries are returned
- When `scope` is COMPANY (or companyId is provided without explicit scope), returns only entries scoped to that company; companyId is required in this case
- When `scope` is GLOBAL (or companyId is omitted without explicit scope), returns only global (company-unscoped) entries
- When `scope` is ALL, returns combined results for all scopes the caller is authorized for; if companyId is also provided, it acts as an additional filter within the combined results
- When `scope` is ALL, the caller must hold `viewAuditHistory` at each scope they wish to see — unauthorized scopes are silently excluded from the result
- An invalid `scope` value is rejected with INVALID_SCOPE
- `scope` is COMPANY but no companyId is provided is rejected with VALIDATION_ERROR
- Results are returned in chronological order by default
- Large result sets support pagination
- Caller must hold `viewAuditHistory` permission at the appropriate scope
- A caller with company-scoped permission can only retrieve entries for their assigned companies

## Process Flow

```mermaid
flowchart TD
    A[Receive search request] --> B{Caller has viewAuditHistory?}
    B -->|No| C[Return error: INSUFFICIENT_PERMISSION]
    B -->|Yes| D[Build query from filter criteria]
    D --> D2{At least one filter provided?}
    D2 -->|No| D3[Return error: VALIDATION_ERROR]
    D2 -->|Yes| E{Determine scope}
    E -->|scope=COMPANY or companyId provided| F[Scope to company entries]
    E -->|scope=GLOBAL or no companyId| G[Scope to global entries]
    E -->|scope=ALL| G2[Combine company + global entries\nfor scopes caller is authorized for]
    F --> H[Apply remaining filters]
    G --> H
    G2 --> H
    H --> I[Order by timestamp ascending]
    I --> J[Apply pagination]
    J --> K[Return paginated results]
```

## External Dependencies

- None

## Error Scenarios

- **INSUFFICIENT_PERMISSION**: Caller lacks `viewAuditHistory` permission
- **UNAUTHORIZED**: Caller's permission scope does not cover the requested company scope
- **VALIDATION_ERROR**: No filter parameters provided (at least one is required)
- **VALIDATION_ERROR**: `scope` is COMPANY but no companyId is provided
- **INVALID_SCOPE**: `scope` is not one of COMPANY, GLOBAL, or ALL

## Test Cases

- returns entries filtered by actorId
- returns entries filtered by actorType and actorId
- returns entries filtered by entityType
- returns entries filtered by entityType and entityId
- returns entries filtered by operationType
- returns entries filtered by date range
- returns entries filtered by companyId
- returns global entries when companyId is omitted
- returns only company entries when scope is COMPANY
- returns only global entries when scope is GLOBAL
- returns combined company and global entries when scope is ALL
- restricts combined results to scopes the caller is authorized for when scope is ALL
- returns only company entries in combined scope when caller lacks global permission
- returns only global entries in combined scope when caller lacks company permission
- filters combined scope results by companyId when both scope=ALL and companyId are provided
- rejects scope=COMPANY when companyId is not provided
- rejects invalid scope value
- returns entries filtered by correlationId
- combines multiple filter criteria
- returns results in chronological order
- paginates large result sets
- returns empty list when no entries match
- rejects when no filter parameters are provided
- rejects when caller lacks viewAuditHistory permission
- rejects when caller lacks permission for requested company scope
- restricts company-scoped caller to their company even when scope=GLOBAL
- restricts company-scoped caller to their company even when scope=ALL
- restricts global-scoped caller to global entries even when scope=COMPANY
- restricts global-scoped caller to global entries even when scope=ALL
