GET /search/query
Execute a structured search query against the local encrypted search index. Every query requires an unlocked session because result rendering decrypts the encrypted payload.
ADR-008 wire change: total/hasMore are no longer top-level siblings of the envelope — they are folded INTO the data payload alongside the renamed items array (SearchQueryResultDto). The response is the canonical ApiEnvelope<SearchQueryResultDto> ({ data: { items, total, hasMore, state }, ts }).
Index-not-ready handling is query-type-aware (§4.7): a filter-less browse degrades to a direct main-store read and returns HTTP 200 with state: "degraded"; a keyword or filtered query instead returns HTTP 503 index_rebuilding.
Query parameters
Required free-text query string.
Optional explicit operator: "and" or "or".
Optional time preset: today, yesterday, last_24h, last_7d, last_30d, this_week, this_month.
Absolute range start (ms since epoch). Must be paired with to_ms.
Absolute range end (ms since epoch). Must be paired with from_ms.
Comma-separated file types (text, html, file, image, other). image here is the physical type of a pure bitmap; copied image files are file and matched via the image tag instead (see tags).
Comma-separated file extensions (e.g. "md,txt").
Comma-separated source device ids; restricts results to those origins.
Comma-separated tag ids (e.g. "link,favorited,image"); restricts results to entries carrying any of them. Custom tag ids require an unlocked session.
Maximum results. Default 50, clamped to 200.
Pagination offset. Default 0.
Response
Search results page (state ready or degraded)