# 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")?
