# Spec Delta

## Purpose

Help authenticated users find Pilot Plant entities, inventory spareparts and maintenance work orders from the application header and open the matching record directly.

## ADDED Requirements

### Requirement: Authenticated bounded search
The system SHALL expose GET /api/v1/search with a trimmed q of 2-100 Unicode code points. It SHALL preserve existing read authorization and response envelopes and return at most three results per Pilot Plant, Inventory and Work Orders group with a hasMore indicator.

#### Scenario: Valid grouped search
- **WHEN** an authenticated reader searches for a valid phrase
- **THEN** the response contains query, the three groups with items and hasMore, and meta.requestId
- **AND** empty groups are present with empty arrays and hasMore false

#### Scenario: Invalid or unauthenticated request
- **WHEN** q is missing, repeated as an array, too short or too long after trimming
- **THEN** the API returns the existing validation error response
- **WHEN** authentication is absent or expired
- **THEN** the API returns 401 without search results

### Requirement: Search fields and deterministic ranking
Search SHALL match category/equipment/item name or code, sparepart name/SKU/part number, and WO number/description. It SHALL rank exact identities, exact names/descriptions, prefixes, then substrings, with stable ties. Matching SHALL be case-insensitive and punctuation/wildcard characters SHALL be treated literally.

#### Scenario: Exact SKU and duplicate names
- **WHEN** one part exactly matches the SKU while several parts have similar names
- **THEN** the exact SKU precedes the other matches
- **AND** each result carries its own ID and identifying code

#### Scenario: Ranking before limiting
- **WHEN** more than three matches exist and an exact code match is not among the first inserted records
- **THEN** the exact match is still included ahead of lower ranked results
- **AND** hasMore is true

### Requirement: Domain visibility and historical records
Search SHALL exclude archived master records and Pilot children with archived ancestors. It SHALL exclude soft-deleted, unreleased and legacy calibration WOs. Nondeleted completed/cancelled WOs and active spareparts with zero stock SHALL remain searchable. Search SHALL NOT mutate operational data.

#### Scenario: Hidden ancestors and deleted WO
- **WHEN** an item has an archived category or a matching WO has deletedAt populated
- **THEN** neither appears in search results

#### Scenario: Retained history and unavailable stock
- **WHEN** a completed or cancelled WO is retained, or a matching active part has zero stock
- **THEN** it remains eligible under normal read permissions
- **AND** the search does not alter stock, reports or WO status

### Requirement: Header interaction and current results
The header SHALL search after 300 ms of idle typing for valid input, present grouped results with identity/context, and support keyboard selection and dismissal. Loading, empty and error states SHALL be distinct. Results SHALL correspond to the current query and authenticated user only.

#### Scenario: Fast typing or account change
- **WHEN** an earlier response arrives after a newer query, or the authenticated user changes
- **THEN** earlier query/user results are not presented as current results

#### Scenario: Keyboard and failure handling
- **WHEN** a user opens results and uses arrows, Enter or Escape
- **THEN** they can navigate, select or dismiss the results with accessible focus behavior
- **WHEN** search fails
- **THEN** an error and retry action are displayed rather than a false empty result

#### Scenario: More results exist
- **WHEN** a group has more than three matches
- **THEN** the header indicates more matches and asks the user to refine their query

### Requirement: Direct navigation to selected records
Selecting a search result SHALL open the selected entity using its ID, independent of list pagination or filters. Inventory and Pilot Plant selections SHALL survive refresh and browser back/forward using URLs. Maintenance SHALL reuse its existing WO detail URL. Closing detail SHALL preserve unrelated URL parameters.

#### Scenario: Inventory and WO destinations
- **WHEN** a user selects a part or WO
- **THEN** /inventory?part=<id> or /maintenance?wo=<id> opens its current detail

#### Scenario: Pilot Plant hierarchy
- **WHEN** a user selects a category, equipment or item
- **THEN** its category, equipment or item URL parameter resolves the necessary ancestors and opens the corresponding existing hierarchy/detail view
- **AND** navigating back/forward restores the selected context

#### Scenario: Invalid or unavailable destination
- **WHEN** a destination is archived, missing, forbidden, or has conflicting Pilot target parameters
- **THEN** the page displays an actionable error without opening an unrelated entity

### Requirement: Category detail resolution
The API SHALL provide authenticated GET /api/v1/pilot-plant/categories/:id returning the existing CategoryDto envelope for active categories and the existing not-found error for unavailable categories. It SHALL apply the same read permissions as Pilot Plant lists.

#### Scenario: Resolve an active category by ID
- **WHEN** a permitted reader requests an active category not on the current list page
- **THEN** the API returns that category by ID without requiring a list search

#### Scenario: Archived category
- **WHEN** the requested category is archived or missing
- **THEN** the API returns the existing 404 error envelope
