# Sökrobusthet för matvaror i hushållslagret > Målbild: användaren kan ställa en fritextfråga om vad som finns hemma och få ett svar som känns mänskligt, visar exakt lagring (FoodTwin) och ärligt berättar hur säker appen är – utan att hitta på något. ## Befintliga motorer ### Sökmotor: `/v1/inventory` - Enkel `ILIKE` mot `inventory_items.display_name` och `brand`. - Inga synonymer, ingen fonetisk matchning, ingen felstavningstolerans. - Filtrering på `storage_location_id`, `expiry_status`, paginering. ### Förbättrad sökmotor: `/v1/inventory/natural-search` - Kombinerar `unaccent(...) ILIKE unaccent(...)` med PostgreSQL `pg_trgm`-similarity. - Söker även mot kanoniska ingrediensnamn (`name_sv`, `name_en`). - Sorterar på `GREATEST(similarity(...))`. - Returnerar både strukturerade träffar och ett naturligt-språkligt svar. ### Trust-motor (`@app/inventory-engine`) - `computeTrust(...)` ger `trustState` (`trusted`/`decaying`/`stale`/`unverified`) och `trustScore` 0–100. - Baserat på `confidence`, `verifiedByUser`, ålder och förruttnelseprofil. - Används redan i `/v1/inventory` och vid skanning/konsumtion. ### FoodTwin-data - `storage_locations`: namn, typ, sublocations. - `inventory_items`: `storage_location_id`, `sublocation`, kvantitet, enhet, `trust_state`. - `canonical_ingredients`: kanoniskt namn, synonymer, hållbarhetsriktlinjer. ## Svarsformat `GET /v1/inventory/natural-search?q=mjölk&languageTag=sv-SE` ```json { "query": "mjölk", "response": "Jag hittade **Mjölk** i Kylen (mellanmålshyllan). Jag är ganska säker på att den finns kvar.", "items": [ { "id": "...", "displayName": "Mjölk", "quantity": 1, "unit": "LITER", "locationName": "Kylen", "locationType": "fridge", "sublocation": "mellanmålshyllan", "trustState": "trusted", "trustScore": 95 } ] } ``` ## i18n Server-sidan använder en minimal katalog i `apps/api/src/lib/inventorySearchResponse.ts`. Stödja språk (12): sv, en, da, de, es, fi, fr, it, nb, nl, pl, pt. Vid okänt språk faller vi tillbaka till engelska och sedan svenska. ## Hårda regler 1. **Inga påhittade fakta.** Om sublocation saknas visas inte "på hylla X". 2. **Trust-hedge måste matcha `trustState`.** `stale` ger en osäker formulering; `trusted` ger en trygg. 3. **Noll träffar** ska erkänna det och erbjuda att lägga till. 4. **Flera träffar** ska lista dem med lagring och peka på listan för trust-score. ## Nästa steg / öppna frågor - Ska vi också söka i `canonical_ingredients.aliases` (array)? Kräver en `unnest`/`CROSS JOIN LATERAL` eller en trigram-index på en materialiserad vy. - Ska vi lägga till fonetisk matchning (`fuzzystrmatch`) för vanliga felstavningar? - Ska svaret också inkludera hållbarhetsstatus för träffarna? - Behövs en separat vector/embedding-sökning för semantiska matchningar (t.ex. "mjölkprodukter")?