diff --git a/NEXT_STEPS.md b/NEXT_STEPS.md index dc7f1330..4c561e52 100644 --- a/NEXT_STEPS.md +++ b/NEXT_STEPS.md @@ -43,6 +43,15 @@ MVP ar uppnadd nar en vanlig anvandare kan importera, granska och spara kvitto/r ## Nyligen klart +## 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. diff --git a/TEKNISK_BESKRIVNING.md b/TEKNISK_BESKRIVNING.md index ff4eab33..f9c03935 100644 --- a/TEKNISK_BESKRIVNING.md +++ b/TEKNISK_BESKRIVNING.md @@ -2026,3 +2026,46 @@ Microservice-importer ska använda SQLite som databas, av samma skäl som co ## 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. +## 2026-05-12: Alias-scopehantering (admin), kategori-chip, beroendehärdning och quality-gates + +### Alias-scopehantering (admin → global) + +- **Ny backend-regel:** Admin kan ändra ett privat alias till globalt via `PATCH /receipt-alias/:id`. Vanliga användare blockeras med `ForbiddenException` om de försöker ändra `isGlobal`. +- **Global → privat skyddad:** Om ett globalt alias saknar `ownerId` returneras `BadRequestException` vid försök att göra det privat — systemet hindrar föräldralösa privata alias. +- **DTO utökat:** `UpdateReceiptAliasDto` har fått `isGlobal?: boolean` med `@IsBoolean()`. +- **Admin-UI:** Admin alias-panelen visar nu en switch för att höja ett privat alias till globalt. Switchen är låst (disabled) om aliaset redan är globalt — riktning är enbart privat → global. Bekräftelse-chip visas temporärt (6 s) i listan efter scope-byte. +- **Tester:** Nya tester täcker: + - Admin kan höja privat → global. + - Vanlig användare blockeras från scope-ändring. + - Global → privat utan owner ger `BadRequestException`. + - Controller delegerar korrekt DTO med `isGlobal` till service. + +### Kategori-chip + +- Fallback-chip för tom kategoriväg returnerar nu `SizedBox.shrink()` globalt i den gemensamma chip-buildern — "okänd"-chip visas inte längre i admin- eller importpaneler. + +### Beroendehärdning (Nest 11 + multer 2.1.1) + +- Backend uppgraderat till **NestJS 11** (`@nestjs/common/core/platform-express/testing/jwt/passport` 11.x). +- `multer` uppgraderat till **2.1.1** — eliminerar tidigare high-severity CVE i transitivt beroende. +- `@types/express` uppgraderat till **5.0.5**, `@nestjs/cli` **11.0.21**, `@nestjs/schematics` **11.1.0**. +- `JWT_SECRET` fail-fast check tillagd i `jwt.strategy.ts`; `JWT_SECRET` satt i CI-env. +- `npm audit --audit-level=high` rapporterar **0 sårbarheter**. + +### Quality-gates (npm scripts + CI) + +Nya scripts i `backend/package.json`: + +| Script | Kommando | +|---|---| +| `prisma:validate` | `prisma validate --schema prisma/schema.prisma` | +| `typecheck` | `tsc --noEmit` | +| `audit:high` | `npm audit --audit-level=high` | +| `quality:ci` | Kedja: validate → generate → typecheck → test → build → audit | + +CI-workflow (`.gitea/workflows/test.yml`) uppdaterad: +- Alla Prisma-steg använder nu `npm run prisma:validate`. +- Audit-steg använder `npm run audit:high`. +- Nytt **typecheck-steg** tillagt i både PR-snabbjobb och push-fulljobb. +- `npm ci` används genomgående (var `npm install` i delar av flödet). + diff --git a/_archive/docs/SESSION_CHECKPOINT_2026-05-12.md b/_archive/docs/SESSION_CHECKPOINT_2026-05-12.md new file mode 100644 index 00000000..e1a4a2c2 --- /dev/null +++ b/_archive/docs/SESSION_CHECKPOINT_2026-05-12.md @@ -0,0 +1,134 @@ +# Session Checkpoint (2026-05-12) + +> Föregående checkpoint: [SESSION_CHECKPOINT_2026-05-11.md](SESSION_CHECKPOINT_2026-05-11.md) + +## Status + +- Alla ändringar är lokalt implementerade och verifierade (tester gröna, inga type-fel, 0 npm-sårbarheter). +- Ej committat/pushat. + +## Klart i denna session + +### 1. Alias-scopehantering (admin kan höja privat → globalt) + +**Backend (`receipt-alias`):** +- `UpdateReceiptAliasDto` utökat med `isGlobal?: boolean` (`@IsBoolean()`). +- `receipt-alias.service.ts`: `update()` hanterar scope-byte med: + - Admin-only-regel: vanlig användare → `ForbiddenException`. + - Global → privat utan owner → `BadRequestException`. + - Beräknar `nextIsGlobal` + `nextOwnerId` korrekt och sparar. +- Konfliktcheck baseras på nästa scope, inte gammalt. + +**Admin-UI (`flutter/lib/features/admin/presentation/admin_aliases_panel.dart`):** +- Edit-dialog har scope-switch. +- Switch är **låst (disabled)** om aliaset redan är globalt — endast privat → global är möjligt. +- Subtitel förklarar läget dynamiskt. +- Bekräftelse-chip visas i listan i 6 sekunder efter genomförd scope-ändring. +- `_scopeChangedAliasId` / `_scopeChangedToGlobal` state-fält med Timer + dispose-cleanup. + +**Admin repository (`flutter/lib/features/admin/data/admin_repository.dart`):** +- `updateReceiptAlias` tar emot `bool? isGlobal` och inkluderar det i PATCH-body. + +**Tester (16/16 passerar):** +- `receipt-alias.service.spec.ts`: admin kan höja privat → global; användare blockeras; global → privat utan owner ger `BadRequestException`. +- `receipt-alias.security.spec.ts`: controller delegerar DTO med `isGlobal` korrekt. + +### 2. Kategori-chip fallback + +- Den gemensamma chip-buildern returnerar nu `SizedBox.shrink()` vid tom kategoriväg — "okänd"-chip visas inte längre i admin- eller importpaneler. + +### 3. Beroendehärdning + +**recipe-app backend:** +- Uppgraderat till **NestJS 11** (`@nestjs/common/core/platform-express/testing` 11.1.19, `@nestjs/jwt` 11.0.2, `@nestjs/passport` 11.0.5). +- `multer` uppgraderat till **2.1.1** (åtgärdar high-severity CVE i transitivt beroende). +- `@types/express` → **5.0.5**, `@nestjs/cli` → **11.0.21**, `@nestjs/schematics` → **11.1.0**. +- `jwt.strategy.ts`: fail-fast check för `JWT_SECRET` + typed `secretOrKey`. +- `JWT_SECRET: ci-test-secret` satt i CI-env i `.gitea/workflows/test.yml`. +- `npm audit --audit-level=high` = **0 sårbarheter**. + +**microservice-importer backend:** +- Samma uppgradering till Nest 11 + multer 2.1.1 + `@types/express` 5. +- `npm audit --audit-level=high` = **0 sårbarheter**. + +### 4. Quality-gate scripts + +**recipe-app/backend/package.json** – nya scripts: + +| Script | Syfte | +|---|---| +| `prisma:validate` | `prisma validate --schema prisma/schema.prisma` | +| `typecheck` | `tsc --noEmit` | +| `audit:high` | `npm audit --audit-level=high` | +| `quality:ci` | Kedja: validate → generate → typecheck → test → build → audit | + +**recipe-app/.gitea/workflows/test.yml** – uppdateringar: +- Prisma-steg kör `npm run prisma:validate`. +- Audit-steg kör `npm run audit:high`. +- Nytt **Typecheck backend**-steg i PR-snabbjobb och push-fulljobb. + +**microservice-importer/backend/package.json** – nya scripts: + +| Script | Syfte | +|---|---| +| `typecheck` | `tsc --noEmit` | +| `audit:high` | `npm audit --audit-level=high` | +| `quality:ci` | Kedja: typecheck → build → audit | + +**microservice-importer/.github/workflows/test.yml** – uppdateringar: +- `npm install` → `npm ci`. +- Prisma/test-steg ersatta med: typecheck → build → audit. +- `continue-on-error` borttagen från build. + +## Ändrade filer (recipe-app) + +- `backend/src/receipt-alias/dto/update-receipt-alias.dto.ts` +- `backend/src/receipt-alias/receipt-alias.service.ts` +- `backend/src/receipt-alias/receipt-alias.service.spec.ts` +- `backend/src/receipt-alias/receipt-alias.security.spec.ts` +- `backend/src/auth/jwt.strategy.ts` +- `backend/package.json` +- `backend/package-lock.json` +- `.gitea/workflows/test.yml` +- `flutter/lib/features/admin/data/admin_repository.dart` +- `flutter/lib/features/admin/presentation/admin_aliases_panel.dart` +- `TEKNISK_BESKRIVNING.md` +- `NEXT_STEPS.md` +- `_archive/docs/SESSION_CHECKPOINT_2026-05-12.md` (denna fil) + +## Ändrade filer (microservice-importer) + +- `backend/package.json` +- `.github/workflows/test.yml` +- `TEKNISK_BESKRIVNING.md` +- `next_steps_MSImporter.md` + +## Snabb återstart nästa gång + +```bash +# Verifiera status +cd recipe-app/backend +npm run quality:ci + +cd ../../microservice-importer/backend +npm run quality:ci +``` + +Flutter-analys: +```bash +cd recipe-app/flutter +flutter analyze lib/features/admin/presentation/admin_aliases_panel.dart +``` + +Alias-tester: +```bash +cd recipe-app/backend +npm test -- src/receipt-alias/receipt-alias.service.spec.ts src/receipt-alias/receipt-alias.security.spec.ts --runInBand +``` + +## Nästa rekommenderade steg + +1. Commit och push av samtliga lokala ändringar. +2. Deploy till produktionsmiljö och verifiera alias-flöde med riktiga kvitton. +3. Manuell verifiering: admin kan höja privat → globalt via UI; vanlig användare kan inte. +4. Widgettester för alias-panelens switch (privat → global, disabled-state om globalt).