chore(docs): consolidate legacy documentation into new structure
Test Suite / backend-pr-quick (push) Has been skipped
Test Suite / quick-import-pr-quick (push) Has been skipped
Test Suite / backend-full (push) Successful in 2m57s
Test Suite / flutter-quality (push) Failing after 1m16s

- Removed outdated documentation files (MVP_CHECKLISTA.md, NEXT_STEPS.md, README.md, TEKNISK_BESKRIVNING.md, filanalys.md, flyerimporter.md, kilo.json, plan-dokumentation.md)
- Added new centralized documentation structure under docs/ directory
- Added .kilo/ directory for Kilo AI agent configuration and plans

BREAKING CHANGE: Legacy documentation files removed and replaced with new centralized structure
This commit is contained in:
Nils-Johan Gynther
2026-05-25 08:14:35 +02:00
parent 2a87a18edd
commit 9e513c2f5e
9 changed files with 27 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
# MVP-checklista: Recipe App (maj 2026)
## 1. Funktionell sluttestning (produktion/lik miljö)
- [ ] Testa inventarie: skapa, ändra, ta bort, ändra kategori, filtrera, konsumera, historik.
- [ ] Testa baslager: lägg till/ta bort, ändra kategori, filtrera, grupperad vy.
- [ ] Testa receptimport: länk, PDF, bild, Markdown. Kontrollera parser, fallback, och matchning.
- [ ] Testa produktadmin: merge, bulk-kategorisering, AI-kategorisering, dubblett-hantering, statuskö.
- [ ] Testa alias: skapa, ta bort, user/global, badge i UI.
- [ ] Testa seed-data: kontrollera att nya kategorier finns efter deploy.
- [ ] Testa navigation: admin-knapp i profilmeny, alla länkar och vyer.
## 2. Säkerhet och access ✅
- [x] Verifiera user-scope och IDOR-skydd på alla endpoints. (86 tests, PASS)
- [x] Testa rollbaserad access (admin/user). (86 tests, PASS)
- [x] Kontrollera JWT, throttling, och inputvalidering. (86 tests, PASS)
## 3. Regression och buggrättning ✅
[ ] Fixa eventuella UI-buggar (scroll, dropdown, state).
[ ] Slutgiltig README och teknisk beskrivning.
- [ ] Kontrollera .env-exempel och seed-instruktioner.
## 5. UI/UX-polish
- [ ] Loading states, felmeddelanden, mobilanpassning.
- [ ] Extra tester för bulk-operationer, AI-förslag, aliasradering.
## 6. Release
- [ ] Tagga release i git.
- [ ] Deploy till produktion.
- [ ] Bekräfta drift och funktion i live-miljö.
+223
View File
@@ -0,0 +1,223 @@
## Utforda steg (2026-05-20)
- [x] **Deploy-script uppdaterat:** `deploy.sh` forenklat genom att ta bort `--migrate`; `--clean-database` kor nu migrering explicit innan rensning.
- [x] **Prisma-integrering i deploy:** `--clean-database` kor `prisma migrate deploy` i `recipe-api` med explicit schema-parameter for att sakerstalla uppdaterat schema fore SQL-rensning.
- [x] **Loggsynlighet for Prisma Client:** `deploy.sh` visar nu output fran `npx prisma generate` i terminalen vid migreringsrelaterade deployfloden.
- [x] **Databasrensning standardiserad:** Ny underhallsfil `backend/prisma/maintenance/clean-database.sql` skapad for reset som bevarar kategorier.
- [x] **Produktionsnara fel rattat:** `clean-database.sql` korrigerad efter serverfel (`Table 'ShoppingList' doesn't exist`).
- [x] **Tabellista hardad:** SQL-filen anvander nu existerande tabeller i nuvarande Prisma-schema och tar bort beroenden i saker ordning med `FOREIGN_KEY_CHECKS`.
## Utförda steg (2026-05-21)
- [x] **Flyer AI-trace persisteras:** `AiFlyerParserService` returnerar trace-data (prompt/rawOutput/chunkCount/retryCount) och `FlyerImportService` sparar detta i `AiTrace` med `source=flyer`.
- [x] **Admin AI observability utökad:** `AiTraceService` hämtar kompletterande flyer-trace via `sessionId` och exponerar prompt/output/retry/chunk i detaljvyn.
- [x] **Maskning i trace-detail:** känslig data maskas konsekvent i prompt/raw output/normaliserad output innan retur till admin-UI.
- [x] **Flyer-kvalitet:** dedupe justerad för att minska dubletter utan att slå ihop olika kampanjer; hårdostnamn använder korrekt åäö.
- [x] **Kontextstyrd OCR-korrigering:** kända fel (ex. `Pröd`) korrigeras endast i relevant textkontext för att minska falska rättningar.
- [x] **Flutter Admin AI-panel UX:** selekterbar prompt/output, varningspanel med kopiering och output-trunkering med expandera/kollapsa.
# Nasta steg
Detta ar huvudroadmap for Recipe App.
All detaljhistorik och djup teknisk bakgrund finns i respektive tekniska dokument.
## Dokumentstatus (2026-05-03)
- Fokus: en gemensam prioriteringslista for produkt, utveckling och drift.
- Delplaner for underomraden ska referera hit, inte duplicera hela roadmapen.
## MVP-plan (2026-05-10)
MVP ar uppnadd nar en vanlig anvandare kan importera, granska och spara kvitto/recept utan manuella specialsteg, och admin kan underhalla produkt- och kategoridata stabilt i drift.
### Fas 1 - Scopefrysning och releasekandidater
1. Las MVP-scope till foljande floden:
- Kvittoimport end-to-end (parse -> granska -> spara).
- Receptimport end-to-end (url/pdf/ocr/markdown -> granska -> spara).
- Admin inventarie/product-hantering (CRUD, merge, filter, restore).
2. Markera uttryckligen allt annat som post-MVP i denna fil (t.ex. EAN/Open Food Facts, utokad AI, storre webbsakerhetsomlaggning).
3. Faststall releasekandidat for backend + flutter med versionsetikett.
### Fas 2 - Hard validering i produktionslik miljo
1. Kor manuell verifiering av aliasstrategi med riktiga kvitton (privat alias, global fallback, prioriteringsordning).
2. Kor fulla regressionsfloden for import, matchning, kategorisering, merge och spara.
3. Verifiera deployflode och driftkommandon pa server med healthcheck efter release.
### Fas 3 - MVP-release
1. Publicera releasekandidat nar alla gransvarden ar godkanda.
2. Folj upp med kort hypercare-period (felrattning med hog prioritet, inga nya features).
### Exit-kriterier (Definition of Done for MVP)
- End-to-end importfloden fungerar stabilt for minst ett representativt urval av kvitton och receptkallor.
- Aliasprioritering fungerar deterministiskt: user alias -> global alias -> ordmatchning -> AI.
- User-scope och IDOR-skydd ar verifierat i kritiska domaner.
- Admin kan hantera produkter/inventarie utan datakorruption eller behov av manuella DB-ingrepp.
- Deploy, healthcheck och testkorning ar reproducerbara i driftmiljo.
## Nyligen klart
## Utförda steg (2026-05-19)
- [x] **Flyerimport-sessioner i backend:** Implementerat session-endpoints för senaste och specifik session.
- [x] **Flyerimport-persistens i Flutter:** Lättviktig lagring i `SharedPreferences` med `sessionId` + vald state.
- [x] **Hydreringsflöde i klient:** Restore lokalt -> hämta via sessionId -> fallback till latest-session.
- [x] **HTTP-semantik + optimering:** 404 för saknad session och single-query för latest-session.
- [x] **Regressionstester:** Backendtester för flyer-sessioner tillagda och gröna (3/3).
## Utförda steg (2026-05-18)
- [x] **ESLint i backend + CI:** ESLint-konfiguration tillagd i backend och CI-workflow uppdaterad med lint-step för PR/push.
- [x] **Dart lint-konfig aktiverad:** `flutter/analysis_options.yaml` tillagd för att säkerställa `flutter_lints` i analyskörningar.
- [x] **Prisma query logging styrbar per miljö:** `PRISMA_LOG_QUERIES` implementerad i backend samt kopplad i `compose.yml`.
- [x] **Dokumenterat aktivering av query-loggar:** Instruktion att sätta `PRISMA_LOG_QUERIES=1` och starta om `recipe-api` i test/staging.
- [x] **Korrigerat testförväntan i receipt-import:** Security-test för saknat användar-id uppdaterat till `UnauthorizedException`.
## Utförda steg (2026-05-13)
- [x] **Centralt hjälptextsystem (backend):** Nytt `HelpTextsModule` med service, controller och DTO. `GET /api/help-texts/:key` returnerar rätt hjälptext baserat på användarroll (prioritetsordning: admin → user → default). `PUT /api/help-texts/:key/:scope` kräver admin-roll.
- [x] **Prisma-migration:** `20260513150000_add_help_texts``HelpText`-tabell med `@@unique([key, scope])`-constraint och index. Seed-data för `receipt_import` (default + admin-scope) på svenska.
- [x] **Flutter — "Läs hjälp"-knapp:** `TextButton.icon` i receipt_import_tab hämtar hjälptext från backend och visar AlertDialog med scopeindikator och datum.
- [x] **Deploy och verifiering:** Migration tillämpad på produktionsserver (`recipe-api` ombyggd och omstartad). Backend och Flutter live och funktionellt.
- [x] **Copilot-instruktioner:** `.github/copilot-instructions.md` tillagd i samtliga tre repos med robust `.env`-läsningsmönster.
## Utförda steg (2026-05-12)
- [x] **Alias-scopehantering (admin):** Admin kan höja privat alias → globalt via PATCH-endpoint. Backend blockerar omvänd riktning utan owner (`BadRequestException`). Vanliga användare blockeras med `ForbiddenException`.
- [x] **Admin alias-UI:** Switch i edit-dialog begränsad till privat → global (låst om redan globalt). Temporär bekräftelse-chip visas 6 s i listan.
- [x] **Kategori-chip fallback:** "okänd"-chip borttagen globalt fallback returnerar `SizedBox.shrink()`.
- [x] **Beroendehärdning:** Nest 11 + multer 2.1.1. `npm audit --audit-level=high` = 0 sårbarheter i recipe-app backend.
- [x] **Quality-gates:** `prisma:validate`, `typecheck`, `audit:high`, `quality:ci` tillagda som npm-scripts. CI kör nu typecheck i PR- och push-jobb.
- [x] **Tester:** Ny testtäckning för alias-scope i `receipt-alias.service.spec.ts` och `receipt-alias.security.spec.ts` (16/16 passerar).
## Utförda steg (2026-05-11)
- [x] Löste Flutter web build-fel och säkerställde att Docker-build går igenom på både lokal och server.
- [x] Dokumenterade rutiner för hantering av build-artifacts och merge-konflikter.
- [ ] Säkerställ att .gitignore exkluderar alla genererade Flutter-filer.
- **2026-05-10:** Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR.
- Kvittoimport: förbättrad antal/förpackningsinferens och robustare regelmotor.
- Kategorisering: utökade brödregler + contradiction guards och nya regler för pasta, grädde, ägg, juice, godis, och potatis.
- Kategoriträd: nya noder `Korvbröd` under `Fastfoodbröd` och `Grädde` under `Matlagning` i seed-data.
- Flutter: klientpersistens för pågående kvittoimport.
- Produktmodell: user-scoped produkter och seed renodlad till kategorier.
- Testinfrastruktur: parametriserade enhetstester för kvittoimport (18 testfall).
- CI/CD: GitHub Actions-pipeline för automatiserad testkörning vid push och pull request.
- **Node.js versionsparitet:** `package-lock.json` spåras nu i git för båda repos; Dockerfiles kör `npm ci` — reproducerbara byggen i alla miljöer.
- **PDF-kvittoimport stabiliserad:** `pdf-parse` CJS-fix + `pdfjs-dist/legacy` fallback löser `DOMMatrix`-fel i Node.js.
- **Felkods-forwarding fixad:** `receipt-import.service.ts` i recipe-api vidarebefordrar nu 503 från importer-api som `ServiceUnavailableException` istället för att alltid returnera 400.
- **AI-optimering (PDF):** `looksLikeReceiptProductLine()` i importer-api filtrerar bort header/footer-rader — Mistral anropas enbart för rader som faktiskt kan vara produkter.
- **Receptparser hardening:** gemensam parserutility, intervall/parantes/brak-forbattringar samt testtackning for parsern.
- **Receptsakerhet och dataintegritet:** aktiv-produktvalidering, transaktion vid update, orphan-fil-cleanup och striktare owner-hantering av legacy-recept.
- **Alternativa ingredienser (Option A):** lagring i `alternativeProductIds` (JSON), matchning mot flera alternativ och lagerkoll som inkluderar alternativ.
- **Flutter felhantering:** kopierbara felmeddelanden i snackbar + global textselektion for enklare support/felsokning.
- **Kvittoimport — Simplified Matching Logic (2026-05-09):** Unified matcher som konsoliderar product matching + categorization i en explicit flödestre. Eliminar split mellan `matchProducts()` och `enrichWithAiCategories()`. Ger tydligare trace-logging och bättre debuggability för varför ett item matchades på ett visst sätt. Systemet är nu mer underhållsbart och framtida förbättringar på matching/kategorisering går snabbare.
## Huvudprioriteringar
1. 🟡 Aliasstrategi i kvittoimport: DELVIS GENOMFÖRD (2026-05-09)
- Målbild:
- Vanliga användare skapar och använder privata alias som bara gäller deras egna importer.
- Admin kan dessutom skapa globala alias som fungerar som fallback för alla användare.
- Matchningsordning ska alltid vara: user alias -> global alias -> vanlig produktmatchning.
- Genomfört nu:
- Gemensam aliasnormalisering införd för lookup, upsert och alias-inlärning.
- Guardrails införda för tomma alias och brusalias som `rabatt`, `summa`, `pant`.
- Receipt import lär inte längre in alias automatiskt; användaren måste välja det explicit i edit-dialogen.
- Aliasöversikter i Flutter visar nu scope tydligare (`privat` vs `global fallback`).
- Tester tillagda för normalisering, prioritet och behörighet.
- Kvar:
- Manuell verifiering i produktionslik miljö av aliasflödet under riktig receipt import.
- Eventuell vidareutveckling av separat aliasöversikt om behov uppstår.
- Backend:
- Centralisera normalisering av `receiptName` så samma regler används i lookup, upsert och alias-inlärning.
- Härda guardrails för alias: blockera tomma alias, uppenbart brus (`rabatt`, `summa`, `pant`) och andra olämpliga kvittonamn.
- Säkerställ deterministisk prioritet mellan privata och globala alias i receipt-import.
- Behåll nuvarande schema i första fasen; ingen ny migration behövs så länge nuvarande `ReceiptAlias`-modell räcker.
- Flutter:
- Lägg alias-lärande nära manuell korrigering i receipt-import så användaren explicit kan välja att spara matchningen för framtida importer.
- Lägg en enkel aliasöversikt där användaren kan se och ta bort sina privata alias.
- Admin-UI ska kunna skapa globala alias utan att blanda ihop dem med vanliga användares privata alias.
- Tester:
- Verifiera att user alias alltid prioriteras före global alias för samma `receiptName`.
- Verifiera att global alias används när user alias saknas.
- Verifiera att vanlig användare inte kan skapa globala alias eller ta bort andras alias.
- Verifiera att manuell korrigering + `learnAlias` ger direkt träff vid nästa import.
- Verifiera att normalisering gör alias robust mot versaler, whitespace och enklare stavningsvariationer.
- Leveransordning:
- ✅ Fas 1: backend-hardening + tester.
- ✅ Fas 2: UI-stöd i receipt import för alias-inlärning.
- 🟡 Fas 3: separat aliasöversikt för användare och admin (grund finns, kan vidareutvecklas vid behov).
2.**[CLEANUP] Receipt import legacy code (2026-05-09):** KLART
- Borttaget: `matchProducts()`, `enrichWithAiCategories()`, `findWordMatch()` (gammal), m.fl.
- Tester uppdaterade och gröna (66/66)
- Se `SESSION_2026-05-09_RECEIPT_IMPORT.md` för detaljer
3.**[FEATURE] Product Management & Scroll Fix (2026-05-09):** KLART
- Scroll-issue i kvittoimport fixat (7 rader nu synliga)
- Admin rename/merge endpoints implementerade
- Private rename/merge endpoints för users implementerade
- Kodduplicering i products.service.ts eliminerad (~80 rader)
- admin_products_panel optimerad (cache, parallell restore, expression switches)
- Deploy-script förbättrad med selektiv build och seed-kontroll
- Se `SESSION_2026-05-09_RECEIPT_IMPORT.md` för detaljer
- **Todo:** Deploy till prod, testa i live miljö, ev. add UI för user private rename/merge
4. Verifiera flyerimportens sessionhydrering end-to-end i test/staging (tab-byte + app-omstart).
5. Lägg till retention-policy och schemalagd rensning för `AiTrace` (receipt/flyer) för att styra datalivslängd i produktion.
6. Lägg till API-stöd för filtrering av trace-lista på `status` och fri textsökning i varningskoder.
7. Lokalisera kvarvarande stora Flutter-vyer i import/inventarie.
8. Förbereda avancerad AI-integration med tydlig loggning/audit.
9. Påbörja EAN-stöd via Open Food Facts.
## Beslut som styr arbetet
- User-scope for data som ar personligt agd.
- Backend-kontrakt ar sanningskalla; klienter foljer kontrakten.
- Importfunktionalitet ar delegerad till microservice-importer dar det ar beslutat.
## Framtida förbättringsområden
### Säkerhet: httpOnly cookies för Flutter Web
Idag lagras JWT-token i localStorage via SharedPreferences i Flutter Web. För att minska XSS-risk bör backend och Flutter Web stödja httpOnly-cookies för tokens. Detta kräver:
- Backend: endpoint för att sätta och läsa httpOnly-cookie vid login.
- Flutter Web: anpassning så att token inte läses från localStorage utan session hanteras via cookie.
Detta är en större arkitekturändring och endast relevant för webben.
### Säkerhet: Gitea webhook-signaturvalidering
Om Gitea-webhooks används, implementera endpoint i backend som validerar `X-Gitea-Signature` med timing-safe jämförelse. Lägg till `GITEA_WEBHOOK_SECRET` i .env.example. Se säkerhetshärdningsplanen för kodexempel.
### Alternativa ingredienser — migrering till relationsmodell (Option B)
Nuläge: `RecipeIngredient.alternativeProductIds` lagras som JSON-kolumn (Option A).
Detta fungerar men saknar referensintegritet — om en alternativ produkt tas bort uppdateras inte kolumnen automatiskt.
Framtida lösning: Ersätt JSON-kolumnen med en separat tabell:
```prisma
model RecipeIngredientAlternative {
id Int @id @default(autoincrement())
recipeIngredientId Int
recipeIngredient RecipeIngredient @relation(fields: [recipeIngredientId], references: [id], onDelete: Cascade)
productId Int
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
}
```
Fördelar: FK-integritet, möjlig sortering/prioritering av alternativ, lättare att querrya.
Förutsättning: migration som konverterar befintlig JSON-data till rader i tabellen.
## Relaterade dokument
- `README.md` - anvandarperspektiv.
- `TEKNISK_BESKRIVNING.md` - teknisk huvudreferens.
- [produktlansering.md](_archive/docs/produktlansering.md) - releasechecklista i arkiv.
- [migrering-MSI.md](_archive/docs/migrering-MSI.md) - migreringshistorik for importer i arkiv.
- [flutter/next_steps_flutter.md](_archive/docs/flutter/next_steps_flutter.md) - Flutter-specifik plan i arkiv.
- `_archive/microservice-ai/AI-FUNKTIONER.md` - AI-strategi och historik.
## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR.
+459
View File
@@ -0,0 +1,459 @@
# Nyheter och förbättringar (2026-05-24)
- **Supply-chain-skydd för npm i backend:** `backend/.npmrc` innehåller nu `min-release-age=1`, vilket kräver att paketversioner är minst 1 dag gamla innan `npm install`/`npm ci` tillåts.
- **CI påverkas automatiskt:** Backend-jobben i GitHub Actions använder redan `npm ci` i `backend/` och följer därmed policyn utan workflow-ändringar.
- **Driftpolicy:** Vid blockerad akut uppgradering väntar vi normalt ut cooldown-fönstret i stället för att öppna generell policy.
- **Deprecation-kedja åtgärdad i backend-teststacken:** `jest` uppgraderad till 30.x och backend använder en kontrollerad `overrides` för `test-exclude`, vilket tar bort `inflight@1.0.6` och `glob@7` från dependency-trädet.
- **Felsökning av transitiva varningar:** Kör `npm ls <paket>` i `backend/` för att se exakt toppnivåkälla innan åtgärd (uppdatera direkt beroende först, `overrides` endast vid behov).
- **Uppdateringspolicy för dependencies:** Säkerhets- och deprecation-relaterade backend-beroenden prioriteras löpande och ska normalt hanteras i närmast följande utvecklingscykel.
# Nyheter och förbättringar (2026-05-21)
- **Flyer AI-trace end-to-end:** flyer-importen sparar nu prompt/output/metadata i `AiTrace` (source=`flyer`) och adminpanelen kan visa detaljerad trace per session.
- **Bättre produktkvalitet vid flyer-import:** dedupe förbättrad för att minska dubletter, hårdostnamn normaliseras med korrekt åäö, samt kontextstyrd OCR-korrigering för kända fel.
- **Admin AI-panel förbättrad:** model output och prompt är selekterbara, varningar visas med detaljer + kopieringsstöd, och status har tooltip med förklaring.
- **Stora outputs hanteras bättre i UI:** outputkortet trunkerar stora JSON-svar och låter admin expandera vid behov.
# Nyheter och forbattringar (2026-05-20)
- **Deploy-flode for migrering/rensning uppdaterat:** `deploy.sh` kor automatisk migrering vid vanlig deploy, medan `--clean-database` nu forst kor explicit `prisma migrate deploy` och sedan rensnings-SQL. Flaggan `--migrate` ar borttagen.
- **Prisma Client-output i deploy-logg:** Vid migreringsrelaterat deployflode skrivs output fran `npx prisma generate` ut i terminalen (inklusive versionsnotiser), sa att status syns direkt i `deploy.sh`.
- **Ny underhallsfil:** `backend/prisma/maintenance/clean-database.sql` infordes for kontrollerad reset av data i test/staging.
- **Serververifiering och fix:** Rensningsskriptet uppdaterades efter verkligt driftfel (`ShoppingList` saknades) och pekar nu pa tabeller som faktiskt finns i schema/databas.
# Nyheter och förbättringar (2026-05-19)
- **Flyerimport-sessioner i backend:** Nya endpoints `GET /api/flyer-import/sessions/latest` och `GET /api/flyer-import/sessions/:sessionId` för att återhämta senaste eller specifik importsession per användare.
- **Persistens i Flutter för flyerimport:** `flyer_import_session.dart` sparar nu endast `sessionId`, `fileName` och valda rader i `SharedPreferences` för lättviktig cache.
- **Hydrering vid återöppning:** Flutter-tabben återläser lokalt tillstånd och hämtar därefter full session från backend, med fallback till senaste session.
- **Robustare felsemantik:** Backend returnerar `NotFoundException` (404) för saknade sessioner i stället för `BadRequestException`.
- **Verifiering:** Backend typecheck och tjänstetester (`flyer-import.service.spec.ts`, 3/3) passerar.
# Nyheter och förbättringar (2026-05-18)
- **CI: ESLint för backend:** ESLint är infört i backend (`backend/eslint.config.mjs`) och körs i GitHub Actions (`.github/workflows/test.yml`) via steget `Lint backend`.
- **CI: Dart lints aktiverade:** `flutter/analysis_options.yaml` är tillagd med `include: package:flutter_lints/flutter.yaml`, så `flutter analyze` använder explicita lint-regler.
- **Prisma query logging i test/staging:** Backend stödjer nu env-styrd query-loggning via `PRISMA_LOG_QUERIES` i `backend/src/prisma/prisma.service.ts`.
- **Compose-stöd för loggning:** `compose.yml` har `PRISMA_LOG_QUERIES: "${PRISMA_LOG_QUERIES:-0}"` för säker default av.
- **Testfix receipt-import:** Säkerhetstestet för saknat användar-id i `upsertUnitMapping` är uppdaterat till `UnauthorizedException`, i linje med controllerns beteende.
# Nyheter och förbättringar (2026-05-13)
- **Centralt hjälptextsystem:** Nytt backend-modul (`HelpTextsModule`) med `GET /api/help-texts/:key` (rollmedveten) och `PUT /api/help-texts/:key/:scope` (admin). Stöd för scopade hjälptexter: `admin`, `user`, `default` med prioritetsordning beroende på användarroll.
- **Prisma-migration:** `20260513150000_add_help_texts` — skapar `HelpText`-tabell och seedar initiala hjälptexter för kvittoimport (standard + admin-variant) på svenska.
- **Flutter — "Läs hjälp"-knapp i kvittoimport:** Nytt `TextButton.icon` med `Icons.help_outline` i headern på receipt_import_tab. Hämtar hjälptext från backend vid klick och visar den i en AlertDialog med titel, innehåll (selekterbart), scope-chip och uppdateringsdatum.
- **Copilot-instruktioner:** `.github/copilot-instructions.md` tillagd i alla tre repos för att alltid använda robust `.env`-läsningsmönster (grep/sed/tr) vid databas-kommandon.
# Nyheter och förbättringar (2026-05-10)
- **Admin-inventarie:** Full CRUD, merge, filter, sortering, preview och säkerhet för admin i inventarietabellen. Endast admin kan se och hantera alla användares inventarieposter via nya endpoints och adminpanel i Flutter.
- **User-scope och IDOR-skydd:** Inventory och produkter är nu strikt user-scopade. Alla operationer kräver och filtrerar på userId. Tester verifierar att åtkomst nekas vid försök till IDOR.
- **Säkerhetshärdning:** DTO-validering, guard-ordning, logging, throttling, merge abuse-skydd, och rollbaserad access är implementerat och testat.
- **Optimeringar:** DRY i service-lager, striktare query parsing, preview-cache, API-cleanup, och kodduplication eliminerad.
- **Testtäckning:** Utökade enhets-, integrations- och säkerhetstester för alla kritiska flöden.
# Session 2026-05-06: User-scoped AI-fallback, admin-toggles och premium-funktioner
Under denna session har Recipe App fått:
- **User-scoped AI-fallback:** AI-förslag för ingrediens- och kategorimatchning aktiveras nu per användare (premium). Endast användare med premium-tillgång får AI-hints vid import.
- **Admin-toggles:** Admin kan slå på/av AI-funktioner per användare via backend och UI.
- **Premium-scope:** Flutter och backend respekterar premium-flagga och AI-tillgång i alla flöden.
- **Rematch och manuell produkt:** Flutter har stöd för ommatchning och manuell produkt vid import.
- **Arkitektur:** Fallback-first AI, strikt separation av analys/import/matchning, user-scoped produktdata.
Se [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md) för teknisk genomgång och [NEXT_STEPS.md](NEXT_STEPS.md) för roadmap.
# Recipe App
En fullstack-applikation för hantering av hemmavaror och recept. Håll koll på vad du har hemma, spara recept och se direkt om du har allt du behöver för att laga en rätt.
> För teknisk detaljinformation, se [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md).
> För förslag på nästa steg i projektet, se [NEXT_STEPS.md](NEXT_STEPS.md).
> För planerade AI-funktioner, se [_archive/microservice-ai/AI-FUNKTIONER.md](_archive/microservice-ai/AI-FUNKTIONER.md).
## Dokumentkarta
- [README.md](README.md): användaröversikt och funktioner.
- [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md): teknisk referens för drift och utveckling.
- [NEXT_STEPS.md](NEXT_STEPS.md): gemensam roadmap och prioriteringar.
- [produktlansering.md](_archive/docs/produktlansering.md): releasechecklista i arkiv.
- Migrerings- och driftinstruktioner finns nu i [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md). Tidigare migreringsdokument finns i [_archive/docs/migrering-MSI.md](_archive/docs/migrering-MSI.md).
- [flutter/README.md](_archive/docs/flutter/README.md): Flutter ur användarperspektiv i arkiv.
- [flutter/teknisk_beskrivning_flutter.md](_archive/docs/flutter/teknisk_beskrivning_flutter.md): Flutter teknisk referens i arkiv.
- [flutter/next_steps_flutter.md](_archive/docs/flutter/next_steps_flutter.md): Flutter roadmap i arkiv.
## Dokumentstatus (2026-05-11)
# Nyheter och förbättringar (2026-05-11)
# Nyheter och förbättringar (2026-05-11)
- **Flutter web build:** Löste dart2js-kompilationsfel i Flutter-webbappen (adminpanel). Fixade runtime-beroende i meny, deklarerade saknade state-fält i formulärdialoger för inventarie och baslager.
- **Git och deploy:** Rensade build-artifacts från versionshantering och dokumenterade rekommenderad .gitignore för Flutter build-mappar.
- **Stabiliserad deploy:** Dokumenterat rutiner för att hantera merge-konflikter orsakade av genererade filer vid serveruppdatering.
- **Seed-data:** Nya kategorier under `Skafferi > Sylt, mos & marmelad`: `Marmelad`, `Sylt`, `Mos` tillagda i seed.
- **Navigation/UI:** Admin-knappen flyttad från sidomenyn till profilmenyn ovanför logout.
- **Deploy och seed:** Förtydligande om att seed-data körs automatiskt vid `./deploy.sh --backend` och att seed-kontroll sker i deploy-scriptet. Hur man verifierar att seed körts och att nya kategorier finns.
- **Kodförenklingar/optimeringar:** Samtliga tre förenklingar/optimeringar från senaste commit är nu implementerade (se SESSION_2026-05-09_RECEIPT_IMPORT.md för detaljer).
### Målgrupp
Detta dokument är skrivet för användare och produktägare. Fokus är vad som fungerar i appen och vad som förbättrats i det dagliga flödet.
### Nytt sedan senaste sessionerna
- **Alias-strategi för kvittoimport:**
- Backend och Flutter har nu stöd för användarspecifika alias (user-alias) och globala alias (admin).
- Varje rad i kvittoimporten visar nu en badge som anger hur matchningen skedde: **Alias**, **Ordmatch** eller **AI-kategori**.
- Alla användare kan spara egna alias direkt vid import ("Spara som alias"), admins kan spara globala alias.
- Ny profilsida: användare kan se och radera sina alias.
- Admin-panelen för alias visar nu produkt-ID och tydligare radstruktur.
- Kvittoimporten har blivit mer träffsäker för förpackningar och mängder (t.ex. rader med multipack och "2st").
- Kategorisering av brödrelaterade produkter har förbättrats så att färre varor hamnar fel.
- Ny underkategori i kategoriträdet: `Bröd & Kakor > Bröd > Fastfoodbröd > Korvbröd`.
- Importerat kvitto i Flutter ligger kvar i klientens session vid navigering/refresh, så användaren kan fortsätta utan att börja om.
- Produkter är user-scopade (personliga per användare), vilket minskar felmatchningar mellan olika användare.
- Ingen ny serverlagring infördes för kvitto-sessionen; persistensen sker i klienten.
---
### Funktioner
### Kvittoimport och alias
- **Alias-badge:** Varje rad i kvittoimporten visar nu en badge som anger om matchningen skedde via Alias, Ordmatch eller AI-kategori.
- **Spara som alias:** Alla användare kan spara egna alias direkt vid import. Admins kan spara globala alias.
- **Alias-hantering:** Användare kan se och radera sina alias på profilsidan. Admins har en förbättrad panel med produkt-ID och tydligare radstruktur.
- **Prioritering:** Systemet prioriterar användarens egna alias före globala alias och ordmatchning.
### Inventarie (Hemmavaror)
- **Lägg till, redigera och ta bort varor** — hantera produkt, kvantitet, enhet, plats, märke och bäst före-datum
- **Filtrera och sortera** — efter plats (kyl, frys, skafferi), bäst före-datum, och namn (A–Ö)
- **Konsumera varor** — registrera förbrukad mängd med eventuell kommentar
- **Konsumtionshistorik** — spåra vad som använts när och i vilken mängd
- **Utförlig information** — stöd för varumärke, lagringsnot, tillkomsttid och mer
### Baslager
- **Ständigt lager** — markera produkter du alltid räknar med att ha hemma
- **Grupperat per kategori** — produkterna i baslagret visas grupperade under kategorirubrik
- **Lägg till och ta bort** — välj från produktlistan via sökbar dropdown, ta bort med ett klick
----
### 📌 Så använder du Inventarie och Baslager
Dessa två funktioner fyller olika syften och kompletterar varandra:
#### Inventarie — ”vad du faktiskt har hemma”
Inventariet är en **aktiv förrådsbok** över varor du just nu har hemma. Här registrerar du:
- Exakt mängd (t.ex. 500 g pasta, 1,5 liter mjolk)
- Var varan förvaras (kyl, frys, skafferi)
- Bäst före-datum
- Om förpackningen är öppnad
#### Praktiskt flöde
| Du vill se vad du behöver köpa | **Matplanen** — inköpslistan jämför mot båda |
| Du tog slut på mjolk | Ta bort från inventariet (baslagret påverkas inte) |
- **Portionsjustering** — ange antal portioner vid skapandet; matplanen räknar automatiskt om ingrediensmängder om du lagar fler eller färre portioner
- **Receptjämförelse mot inventorie** — se direkt vilka ingredienser du har hemma, vad som saknas och om enheter är inkompatibla
- **Importera recept från Markdown** — klistra in ett recept i enkelt format, låt systemet matcha ingredienser, granska och spara med ett klick
- **Importera recept från PDF, bild eller länk** — stöd för PDF-textutvinning, OCR av bilder och webbimport via snabbimport
- **Intelligenta matchningar** — Levenshtein-baserad likhetsbedömning hittar rätt produkt även vid osäker stavning
- **Enhetskonvertering** — automatisk konvertering mellan viktenheter (g/kg), volymenheter (ml/dl) och portionsenheter (tsk/msk)
- **Inköpslista** — genereras automatiskt utifrån veckans planerade recept; ingrediensmängder skalas proportionellt om portioner justerats
- **Inventariejämförelse** — jämför inköpslistans ingredienser mot vad du faktiskt har hemma (aggregerat per vecka)
> Obs: Destruktiva åtgärder (merge, ta bort, återställ, bulk-uppdatera, återställ all data) kräver admin-roll.
**Admin: Produkter (fliken Databas i /profil)**
Produktadmin är nu uppdelad i tre undertabbar:
- **🗑️ Papperskorg** — visa mjukraderade produkter, återställ eller radera permanent
- Redigera produkter — uppdatera namn, canonical name, kategori (hierarkisk dropdown) och varumärke inline
- Bulk-kategorisering — filtrera fram okategoriserade produkter, markera flera och sätt kategori på alla markerade
- AI-kategorisering per produkt och bulk — "✨ Fråga AI" för kategori
- Hitta dubbletter och slå ihop produkter (merge)
- Förhandsvisning av merge
- Ta bort (mjukradera) och återställ produkter
- **Produktförslags-kö** — produkter med status `pending` samlas på sidan `/admin/products/pending` (länk "⏳ Förslag" i navigeringen)
- **Godkänn eller avvisa** — admin kan godkänna (status → `active`) eller avvisa (status → `rejected`) varje förslag med ett klick
- **Min profil** — redigera förnamn, efternamn och e-postadress
- **Databas** — hantera inventarie och baslager (se nedan)
**Enbart admin:**
- **Användare** — fullständig användarhantering:
- Skapa ny användare (användarnamn, e-post, lösenord, roll)
- Ändra roll via dropdown direkt i tabellen
- Ändra **plan** (Free / Paid ✨) via dropdown — styr tillgång till premium-AI-funktioner
- Ändra e-postadress inline
- Återställ lösenord — genererar ett tillfälligt lösenord och visar ett kopierings-redo meddelande
- Ta bort användare (skyddad: kan inte ta bort sig själv)
- **Databas** — produktdatabasen: redigera, merga, bulk-kategorisera och återställa produkter
### Autentisering och roller
- **Rollbaserad åtkomstkontroll** — systemet har två roller: `user` (standard) och `admin`
- **Premium-plan** — `isPremium`-flagga på användaren styr tillgång till AI-funktioner (kvittoimport AI-hints m.fl.); administreras via Plan-kolumnen i användarhanteringen
- **Automatisk bootstrap** — fyra användare skapas eller uppdateras automatiskt när backend startar, baserat på miljövariabler:
- `Nadmin` (admin), `Padmin` (admin), `user1` (user), `user2` (user)
- **Skyddade admin-endpoints** — destruktiva produkt-endpoints och all användarhantering kräver `admin`-roll; försök utan rätt roll ger 403 Förbjuden
- **Navigering** — admin-länkarna "⚙️ Admin", "⏳ Förslag" och "👥 Användare" visas enbart för inloggade administratörer
---
## Kom igång
### Förutsättningar
- Docker och Docker Compose
- En extern `proxy`-nätverk i Docker för Caddy (rekommenderat) eller localhost-konfiguration
### Starta applikationen
```bash
# Bygg alla images (första gånger)
docker compose build
# Starta alla tjänster i bakgrunden
docker compose up -d
```
Frontend är tillgänglig på `http://localhost:3000` (eller via Caddy proxy)
Backend API är tillgänglig på `http://localhost:8080` (eller via Caddy proxy)
> Stacken använder lokala Docker-images, hälsokontroller och startordning mellan databasen, API:t och frontend för stabilare uppstarter och Portainer-deployer.
### Drift-snabbguide
Använd dessa kommandon konsekvent beroende på vilken del av systemet som ska vara uppe.
**Huvudappen (recept.gynther.se):**
```bash
docker compose build recipe-frontend recipe-api
docker compose up -d recipe-db recipe-api recipe-frontend
```
**Endast backend:**
```bash
docker compose build recipe-api
docker compose up -d recipe-db recipe-api
```
**Flutter-spåret (test.gynther.se):**
```bash
docker compose -f compose.yml -f compose.flutter.yml build recipe-flutter
docker compose -f compose.yml -f compose.flutter.yml up -d --no-deps recipe-flutter
```
**Viktigt:** `docker compose build ...` bygger bara image. Tjänsten startar först efter `docker compose up -d ...`.
**Om orphan-varningen:**
- Varning om orphan-containers är väntad när huvudappen körs med bara `compose.yml` men Flutter tidigare startats med `compose.flutter.yml`.
- Det är normalt ofarligt.
- Kör inte `docker compose down --remove-orphans` om du inte avser att även stoppa Flutter-spåret.
### Bygg bara backend eller frontend om behövligt
```bash
# Bygg enbart backend (t.ex. efter kodändringar)
docker compose build recipe-api
# Starta bara backend (övriga tjänster fortsätter)
docker compose up -d recipe-api
# Liknande för frontend
docker compose build recipe-frontend
docker compose up -d recipe-frontend
```
### Kontrollera hälsa
```bash
# Hälsokontroll via HTTP (backend måste köra)
curl http://localhost:8080/api/health
# Databasspecifik hälsokontroll
curl http://localhost:8080/api/health/db
```
### Databas (one-liners via .env)
Anvand dessa kommandon vid drift/felsokning for att alltid lasa MariaDB-credentials direkt fran `.env`.
```bash
# Visa senaste Prisma-migreringar
docker exec -i recipe-db mariadb -uroot -p"$(grep -E '^[[:space:]]*MARIADB_ROOT_PASSWORD[[:space:]]*=' .env | tail -n1 | sed -E 's/^[^=]*=[[:space:]]*//; s/[[:space:]]+$//; s/^["'\''']|["'\''']$//g' | tr -d '\r')" "$(grep -E '^[[:space:]]*MARIADB_DATABASE[[:space:]]*=' .env | tail -n1 | sed -E 's/^[^=]*=[[:space:]]*//; s/[[:space:]]+$//; s/^["'\''']|["'\''']$//g' | tr -d '\r')" -e "SELECT migration_name, finished_at FROM _prisma_migrations ORDER BY finished_at DESC LIMIT 10;"
# Kontrollera att HelpText-tabellen finns
docker exec -i recipe-db mariadb -uroot -p"$(grep -E '^[[:space:]]*MARIADB_ROOT_PASSWORD[[:space:]]*=' .env | tail -n1 | sed -E 's/^[^=]*=[[:space:]]*//; s/[[:space:]]+$//; s/^["'\''']|["'\''']$//g' | tr -d '\r')" "$(grep -E '^[[:space:]]*MARIADB_DATABASE[[:space:]]*=' .env | tail -n1 | sed -E 's/^[^=]*=[[:space:]]*//; s/[[:space:]]+$//; s/^["'\''']|["'\''']$//g' | tr -d '\r')" -e "SHOW TABLES LIKE 'HelpText';"
```
---
## Lägga till recept
### Snabbimport
På sidan "Lägg till nytt recept" finns ett **snabbimportfält** längst upp:
```
Snabbimport: Klistra in länk eller fil
[https://www.ica.se/recept/...] [→]
```
Klistra in:
- **ICA-receptlänk** — systemet skrapar automatiskt receptet och importerar det
- **Andra receptlänkar** — fallback till generisk HTML/JSON-LD-parser
- En lyckad import omdirigeras till "Skriv in recept" med förifylld Markdown
**Stödda källor:**
- ICA.se — Recept skrapas automatiskt
- Andra webbplatser — Generic HTML-parser (JSON-LD först, sedan HTML-fallback)
- PDF-filer — textutvinning från uppladdad PDF
- Bildfiler — OCR via Tesseract (`swe+eng`) för PNG, JPG, JPEG, WEBP och BMP
**Felmeddelandena vägleder dig:**
- "Länken är inte från ICA.se" — Försöker Generic parser istället
> **Notering:** Snabbimport-logiken är också tillgänglig som en **[standalone microservice](../microservice-importer/README.md)** för integrations- eller API-använding.
---
## Arkitektur: Recipe App + Microservice Importer
Recipe App är uppbyggd i två komponenter:
### Recipe App (detta repo)
**Fullstack-applikation:** Frontend (Next.js), Backend (NestJS), Databas (MariaDB)
Innehåller:
- Inventorie-hantering (CRUD, konsumtion, history)
- Recept-hantering (CRUD, matchning mot inventorie)
- Produktadmin (merge, duplicates, canonical names)
- **Quick-import** (ICA-skrapning integrerad i `/recipes/create`)
### Microservice Importer (separat repo)
**Standalone-tjänst:** Frontend (Next.js), Backend (NestJS, INGEN databas)
Innehåller:
- **URL-scraping:** ICA.se + generic HTML-parser
- **Markdown-parsing:** Samma parser-logik som recipe-app
- Eget kontrollpanel på `/import`
**Användningsfall:**
- Extern API-integration (POST `http://microservice:3001/api/quick-import`)
- Oberoende snabbimport-webb-UI
- Muligt att scalea separat från recipe-app
**Repo:** [`microservice-importer`](../microservice-importer/)
- "Kunde inte hämta recept från ICA: ..." — Länken är bruten eller receptet kunde inte parsas
- "Du måste ange en URL eller filsökväg" — Fältet var tomt
### Välja mellan alternativen
Klicka på **Lägg till nytt recept** i receptmenyn. Du får ett val mellan:
1. **Skriv in recept** — Skriv receptet i Markdown-format med ingredienser och instruktioner
2. **Importera från fil** — Ladda upp PDF, bild eller ange receptlänk för automatisk tolkning
### Skriv in recept (Markdown)
Navigera till **Lägg till nytt recept → Skriv in recept**
**Steg 1: Skriv receptet**
Använd detta format:
```markdown
# Köttfärssås
En klassisk köttfärssås med massa smak.
## Ingredienser
- 500 g köttfärs
- 1 st lök
- 2 msk tomatpuré
- 1 dl grädde (vispgrädde)
- salt och peppar
## Tillvägagångssätt
Hacka löken och stek den mjuk i lite olja. Tillsätt köttfärsen och bräsera tills den är genomstekt. Tillsätt tomatpuré och låt det småkoka ett par minuter innan du tillsätter grädde. Smaka av med salt och peppar.
```
**Steg 2: Granska**
Systemet:
- Tolkar receptnamn, beskrivning och instruktioner
- Försöker matcha varje ingrediens mot databasen (Levenshtein-likhet)
- Visar förslag för varje ingrediens i prioriteringsordning
Du kan:
- Redigera Namnet, beskrivning och instruktioner
- Välj rätt produkt från förslagen för varje ingrediens
- Ta bort ingredienser som inte behövs
- Ändra kvantiteter och enheter
**Steg 3: Spara**
Klicka "Spara recept" — receptet sparas med dina valida ingredienser
### Importera från fil eller länk
Navigera till **Lägg till nytt recept → Importera från fil**
I denna sektion kan du:
- Ladda upp PDF-filer med inbyggd text
- Ladda upp bilder (`png`, `jpg`, `jpeg`, `webp`, `bmp`) som tolkas med OCR
- Ange URL till en receptsida eller blogg
- Låta systemet omvandla resultatet till Markdown och öppna det i redigeringsläget
> **Notering:** Importen använder PDF-textutvinning och Tesseract OCR för att ge en första receptversion som sedan kan granskas och sparas.
### Receptformat — regler
| Sektion | Beskrivning |
|---------|------------|
| **H1 (# titel)** | Receptnamn |
| **Text efter H1, före ## Ingredienser** | Receptbeskrivning (valfritt) |
| **## Ingredienser** | Rubrik för ingredienslistan |
| **Ingrediensrader** | Mönster: `- ANTAL ENHET NAMN` eller `- ANTAL NAMN` (standard: st) |
| **Parentes i ingrediens** | Text i `(parentes)` sparas som ingrediensnot, t.ex. `(vispgrädde)`, `(eller crème fraiche)` |
| **## Tillvägagångssätt** (eller `## Instruktioner`) | Rubrik för tillagningsinstruktioner |
| **Text under instruktioner** | Instruktionstexten (kan fortsätta över flera rader) |
### Matchningsalgoritm
Systemet använder tre metoder för att hitta rätt produkt:
1. **Exakt match** (100 poäng)
- Ingrediensnamn matchar exakt efter normalisering (lowercase, utan skiljetecken)
2. **Delsträng-match** (70 poäng)
- Ingrediensnamn förekommer som del av produktnamnet eller vice versa
3. **Levenshtein-likhet** (40100 poäng)
- Likhetspoäng baserat på tecknenskillnad
- Mindre än 40 poäng filtreras bort
Systemet visar upp till 5 bästa förslag per ingrediens.
---
## Projektstruktur
```
recipe-app/
├── frontend/ # Next.js (App Router)
├── backend/ # NestJS REST API
├── recipe-document-converter/ # Markdown-parserbibliotek
├── db/init/ # SQL-initialiseringsskript
├── compose.yml # Docker Compose
└── backup_recipe_app.sh # Backupskript
```
---
## Backup
```bash
bash backup_recipe_app.sh
```
Säkerhetskopierar källkod och Docker-images till konfigurerad backupmapp.
## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR.
File diff suppressed because it is too large Load Diff