Commit Graph
182 Commits
Author SHA1 Message Date
Nick Szaunig a0f7573af5 fix(backend): block SSRF via webhook subscription URLs
WebhooksService.create() rejected obviously private, loopback, or
link-local URLs (incl. cloud metadata 169.254.169.254 and the
decimal/octal/hex IPv4 shorthand encodings the WHATWG URL parser
normalizes) so an admin-configured webhook can no longer be used to
proxy requests into internal infrastructure. Registration-time only,
no DNS resolution (DNS-rebinding is out of scope for this check).
2026-08-23 07:05:53 +02:00
Nick Szaunig 2458927d38 fix(backend): DELETE /webhooks/:id returns 204 No Content
Matches REST convention and the frontend api-client's existing 204
fast-path, avoiding a JSON-parse crash on an empty response body.
2026-08-23 06:58:13 +02:00
Nick Szaunig 59fdc816a0 feat(backend): Webhooks mit HMAC-signierter Auslieferung (Modul 28)
WebhooksModule (WebhookSubscription: URL, Events, Secret, aktiv) mit
Event-Dispatcher, angehaengt an 10 Ereignisse in 8 bestehenden Services
(colony.created, inspection.created, queen.created, queen.replaced,
harvest.created, batch.created, batch.updated, product.stock_changed,
task.created, task.completed). Auslieferung ist best-effort und blockiert
die ausloesende Anfrage nicht bei Fehlern.
2026-08-23 06:56:56 +02:00
Nick Szaunig e8177432b0 feat(backend): Statistik- und Reporting-Endpunkte (Modul 27)
Aggregations-Endpunkte fuer Voelker, Koeniginnen, Bienenstaende, Varroa,
Honig und Fuetterung nach Lastenheft Abschnitt 4.26.
2026-08-23 06:33:50 +02:00
Nick Szaunig 50268fa591 feat(backend): Koeniginnenbewertung (Modul 31)
QueenEvaluation-Modell (Volksstaerke, Sanftmut, Wabensitz, Schwarm-
trieb, Brutbild, Honigertrag je Skala 1-5) als Sub-Ressource der
Queens-API: GET/POST /queens/:id/evaluations. Vorgezogen vor Modul
27 (Statistik), da dessen Koeniginnen-Auswertungen auf diesen Daten
aufbauen.
2026-08-22 22:55:36 +02:00
Nick Szaunig 75f0d4fd51 fix(backend): IDOR in POST /notifications/:id/read (Modul 26)
markRead() pruefte bisher nicht, ob die Benachrichtigung dem
anfragenden Nutzer gehoert - jeder authentifizierte Nutzer konnte
fremde Benachrichtigungen als gelesen markieren. Jetzt: 403 bei
fremder Benachrichtigung, weiterhin erlaubt fuer eigene und
Broadcast-Benachrichtigungen (userId = null). E2E-Regressionstest
ergaenzt.
2026-08-22 22:50:00 +02:00
Nick Szaunig a57cde1f9a feat(backend): Benachrichtigungssystem (Modul 26)
NotificationsModule: Notification-Modell mit Prioritaeten INFO/
HINWEIS/WARNUNG/KRITISCH, GET /notifications (eigene + Broadcast),
POST /notifications/:id/read. record() als interne API fuer
kuenftige Automatisierungsregeln (Modul 30) vorgesehen.
2026-08-22 22:43:38 +02:00
Nick Szaunig fef1177a2c feat(backend): Kalender (Modul 25)
CalendarModule mit GET /calendar?from=&to=&apiaryId= aggregiert
Durchsichten, Aufgaben, Behandlungen, Fuetterungen, Ernten und
Koeniginnen-Zuweisungen zu einem einheitlichen Ereignisfeed. Rein
lesende Aggregation, kein neues Datenmodell.
2026-08-22 22:34:47 +02:00
Nick Szaunig 3f20133d02 feat(backend): Inventar (Modul 24)
EquipmentModule (GET/POST /equipment, GET/PATCH /equipment/:id) fuer
Ausruestungsgegenstaende (Inventarnummer, Bezeichnung, Hersteller,
Kaufdatum, Zustand, Standort, Wartungsdatum). Neues Prisma-Modell
Equipment (Migration equipment).
2026-08-22 22:26:16 +02:00
Nick Szaunig e82cae257b feat(backend): Abfuellungen und Produkte (Modul 23)
ProductsModule (GET/POST /products, GET/PATCH /products/:id) und
BottlingModule (GET/POST /bottling-batches) mit transaktionaler
Reduzierung der HoneyBatch-Restmenge beim Abfuellen; Ablehnung bei
Abfuellmenge > verfuegbarer Menge. Neue Prisma-Modelle Product und
BottlingBatch (Migration bottling_products).
2026-08-22 11:08:09 +02:00
Nick Szaunig dd88b6a92c feat(backend): QR-Code-System (Modul 22)
QrModule mit GET /qr/:entityType/:id.svg fuer colonies (Deep-Link
direkt zu /inspections/new), apiaries, queens, honey-batches und
storage-containers. Nutzt pdfkit-Nachbar qrcode zur SVG-Erzeugung.
2026-08-22 10:51:42 +02:00
Nick Szaunig c281d04b16 feat(backend): Datenexport-Modul (Modul 21)
ExportModule mit GET /export/colonies.csv, /export/honey-batches.csv,
/export/:entity.json (apiaries/colonies/queens/honey-batches/tasks)
und /export/:report.pdf (honey-batch-traceability via pdfkit).
Ausserdem fehlendes "typecheck"-Skript in package.json ergaenzt
(von CLAUDE.md dokumentiert, war aber nicht vorhanden).
2026-08-22 10:05:46 +02:00
Nick Szaunig 8a6769dbfd feat(backend): Audit-Log-Abfrage (Modul 19)
AuditModule um GET /audit-log?entityType=&entityId= erweitert
(nur Administrator). Zusaetzlich Jest-E2E-Parallelitaet begrenzt
(maxWorkers: 4), um wiederkehrende Verbindungsengpaesse gegen
Postgres unter vielen parallelen Testsuiten zu vermeiden.
2026-08-22 06:00:52 +02:00
Nick Szaunig 146b56d683 feat(backend): Suche und Filter (Modul 14)
SearchModule mit GET /search?q= über Bienenstände, Völker,
Königinnen, Aufgaben und Honigchargen. Kombinierbare Filter
(Status, Standort, Bienenstand) in den bestehenden List-Endpunkten.
2026-08-22 05:29:47 +02:00
Nick Szaunig 09407d4378 feat(backend): Dashboard-Modul (Modul 13)
DashboardModule mit Kennzahlen-Übersicht sowie Alerts fuer
überfällige Aufgaben, auffällige Völker und Lagerartikel unter
Mindestbestand.
2026-08-22 05:15:25 +02:00
Nick Szaunig 15b6ea4edb feat(backend): Lagerverwaltung-Modul (Modul 12)
StorageModule mit Lagerbehaeltern, Lagerartikeln und
Bestandsbewegungen (Zugang/Abgang/Umlagerung/Korrektur), die den
Artikelbestand automatisch fortschreiben.
2026-08-22 05:03:48 +02:00
Nick Szaunig cf625552d1 feat(backend): Honigchargen-Modul (Modul 11)
HoneyBatchesModule inkl. Honigmessungen und
Rückverfolgbarkeits-Endpunkt, der eine Charge über die Schleuderung
und Ernte bis zu den Ursprungsvölkern zurückverfolgt.
2026-08-22 00:37:09 +02:00
Nick Szaunig 340397b34d feat(backend): Ernten- und Schleuderungs-Module (Modul 10)
HarvestsModule und ExtractionsModule als Fundament der
Rückverfolgbarkeitskette: eine Ernte kann mehrere Völker umfassen,
eine Schleuderung mehrere Ernten zusammenführen.
2026-08-22 00:25:36 +02:00
Nick Szaunig cc0aaf0a31 feat(backend): Fütterungen-Modul (Modul 9)
FeedingsModule mit Erfassung, Colony-Historie und
Mengensummen-Endpunkt je Einheit.
2026-08-22 00:14:41 +02:00
Nick Szaunig 61e0bbe794 feat(backend): Behandlungen-Modul (Modul 8)
TreatmentsModule mit Erfassung und Colony-Historie-Endpunkt fuer
Tierarzneimittel-Behandlungen.
2026-08-22 00:04:50 +02:00
Nick Szaunig f363bffed1 feat(backend): Varroamessungen-Modul (Modul 7)
VarroaModule mit Erfassung und Colony-Historie-Endpunkt fuer
Varroamessungen.
2026-08-21 23:56:06 +02:00
Nick Szaunig 7bba168bd6 feat(backend): Aufgaben-Modul (Modul 6)
TasksModule mit CRUD, Status-/Prioritätsfilter und
Erledigen-Endpunkt für polymorph verknüpfte Aufgaben.
2026-08-21 23:43:47 +02:00
Nick Szaunig 9b59e4bb35 feat(backend): Durchsichten-Modul (Modul 5)
InspectionsModule mit CRUD, Colony-Historie-Endpunkt und
Folgeaufgaben-Erstellung aus einer Durchsicht heraus.
2026-08-21 18:43:08 +02:00
Nick Szaunig b18d61640d feat(backend): Koeniginnen-Modul (Modul 4)
QueensModule: CRUD + assign-colony + history, entsprechend Lastenheft
§4.5 (Koeniginnenverwaltung). assign-colony schliesst die offene
QueenColonyHistory der bisherigen Koenigin am Zielvolk (falls vorhanden)
sowie eine evtl. noch offene History dieser Koenigin an einem anderen
Volk, bevor Colony.currentQueenId gesetzt und ein neuer History-Eintrag
angelegt wird - damit bleibt jeder Koeniginnenwechsel nachvollziehbar,
wie gefordert. Rollen wie bei Apiaries/Colonies: Lesen offen, Schreiben
auf ADMIN/BEEKEEPER beschraenkt.

5 Unit-Tests + 2 e2e-Tests, Lint, Typecheck und Build gruen.
2026-08-21 18:26:55 +02:00
Nick Szaunig a71b31df38 fix(backend): Status-Guard fuer Move/Split/Merge auf inaktiven Voelkern
Beim Live-Test im Browser gefunden: move/split/merge liessen sich auch
auf einem bereits DISSOLVED/MERGED-Volk aufrufen und wuerden dort
klaglos durchlaufen - ein Datenintegritaetsproblem, kein reines
UI-Detail. assertActive() wirft jetzt ConflictException (409), wenn
das betroffene Volk (bzw. bei merge: Ziel- und alle zu vereinigenden
Voelker) nicht ACTIVE ist.

Neuer Unit-Test + neuer e2e-Test (dissolve, danach move -> 409).
2026-08-21 18:20:48 +02:00
Nick Szaunig d3f321f1b5 feat(backend): Voelker-Modul (Modul 3)
ColoniesModule: CRUD + Move/Split/Merge/Dissolve/History, entsprechend
Lastenheft §4.4 (Lebenszyklus eines Volkes):
- move: Standortwechsel, protokolliert in ColonyApiaryHistory.
- split: erzeugt Ableger als neues Volk, Abstammung ueber
  ColonyLineage(SPLIT, von Mutter- zu Ablegervolk).
- merge: vereinigtes Volk bleibt historisch erhalten (status MERGED,
  deactivatedAt gesetzt statt geloescht), ColonyLineage(MERGE) je
  vereinigtem Volk zum Zielvolk.
- dissolve: Volk wird deaktiviert (status DISSOLVED), Dokumentation
  bleibt erhalten.
- history: aggregiert Standort-Historie, Koeniginnen-Historie und
  Abstammungslinien (als Quelle und als Ergebnis).

Move/Split/Merge laufen transaktional (prisma.$transaction). Rollen wie
bei Apiaries: Lesen offen, Schreiben auf ADMIN/BEEKEEPER beschraenkt.

9 Unit-Tests + 6 e2e-Tests (inkl. vollstaendigem Move->Split->Merge->
Dissolve-Flow und Rollenpruefung), Lint, Typecheck und Build gruen.
2026-08-21 09:06:51 +02:00
Nick Szaunig 5c92c810e1 feat(backend): Bienenstaende-Modul (Modul 2)
ApiariesModule: CRUD + Deactivate. Lesen fuer alle authentifizierten
Rollen offen, Schreiben (Anlegen/Aendern/Deaktivieren) auf ADMIN und
BEEKEEPER beschraenkt (Lastenheft §3.2: Imker verwaltet Bienenstaende).
Audit-Log-Eintraege bei Create/Update/Deactivate ueber AuditLogService.

4 Unit-Tests + 4 e2e-Tests (inkl. Rollenpruefung READONLY vs. BEEKEEPER),
Lint, Typecheck und Build gruen.
2026-08-21 08:50:50 +02:00
Nick Szaunig 029484f9d5 feat(frontend): Login + Benutzerverwaltung (Modul 1)
/login: Formular gegen AuthProvider (Access-Token im Memory, Refresh
per httpOnly-Cookie), Fehlermeldung bei falschen Zugangsdaten.

(app)/layout.tsx: geschuetztes Layout, leitet ohne Session zu /login um,
Header mit Nutzer-E-Mail + Abmelden. settings/layout.tsx: zusaetzliches
Admin-Gate fuer /settings/users.

/settings/users: Liste, Anlegen-Dialog (shadcn/Base UI Dialog+Select),
Deaktivieren - alles ueber TanStack Query gegen die Users-API.

proxy.ts (Next 16 Nachfolger von middleware.ts): optimistische
Cookie-Praesenz-Pruefung fuer /login und /settings/*, echte
Autorisierung bleibt serverseitig (RolesGuard).

Backend-Fixes waehrend Browser-Verifikation gefunden und behoben:
- CORS fehlte komplett (app.enableCors, FRONTEND_ORIGIN) - jeder
  Cross-Origin-Request von :3000 nach :3001 wurde geblockt.
- React-StrictMode-Doppel-Effect liess zwei parallele Refresh-Aufrufe
  laufen; da Refresh-Tokens rotierend/einmalig sind, gewann einer und
  der andere bekam 401 -> Nutzer flog nach jedem Reload aus der Session.
  Fix: AbortController im Session-Restore-Effect.
- Manifest verwies auf nicht existente PNG-Icons (404); durch
  public/icon.svg ersetzt.

7 Vitest-Tests (Login-Formular, Users-Liste, JWT-Decode), Lint,
Typecheck und Build gruen. Kompletter Flow (Login, Reload-Persistenz,
Benutzer anlegen/deaktivieren, Abmelden, Redirect ohne Session) live
im Browser gegen den echten Server verifiziert.
2026-08-21 08:45:37 +02:00
Nick Szaunig 370102387f fix(backend): Refresh-Token als httpOnly-Cookie statt Response-Body
ARCHITECTURE.md §3 legt fest: Access-Token im Memory/Context, Refresh-Token
als httpOnly-Cookie. Vorherige Implementierung gab beide Tokens im JSON-Body
zurueck - vor dem Frontend-Aufbau (das genau gegen diesen Vertrag baut)
korrigiert.

/api/v1/auth/login und /refresh setzen jetzt ein httpOnly-Cookie
(Path /api/v1/auth, SameSite=Lax, secure in production) und liefern nur
noch { accessToken } im Body. /refresh und /logout lesen den Refresh-Token
aus dem Cookie statt aus dem Request-Body.

e2e-Tests und Live-Smoke-Test (curl mit Cookie-Jar) verifizieren
Login/Rotation/Logout-Invalidierung. 12 e2e- + 26 Unit-Tests, Lint,
Typecheck und Build gruen.
2026-08-21 08:27:58 +02:00
Nick Szaunig ae8f6d4435 feat(backend): Auth/Users/Audit-Modul (Modul 1)
AuthModule: Login/Refresh/Logout mit JWT-Access-Token + rotierendem,
gehashtem Refresh-Token (RefreshToken-Tabelle). JwtAuthGuard + RolesGuard
global via APP_GUARD registriert (gilt fuer jeden kuenftigen Endpunkt),
@Public()-Decorator als Ausnahme (Auth-Endpunkte, /health).

UsersModule: CRUD + Deactivate, nur ADMIN-Rolle, Passwoerter mit bcrypt
gehasht, nie im Response enthalten.

AuditModule: AuditLogService (Grundstruktur), wird von UsersService bei
create/update/deactivate injiziert und geschrieben.

Geteilte App-Konfiguration (Prefix/Versioning/Pipes/Helmet) aus main.ts
in src/app.config.ts extrahiert; e2e-Tests nutzten das vorher nicht und
bekamen dadurch 404 auf jede /api/v1/... Route - jetzt ueber
test/utils/create-test-app.ts geteilt, betrifft alle kuenftigen
e2e-Tests gleichermassen.

prisma/seed.ts legt einen Admin-User fuer lokale Entwicklung an.

26 Unit-Tests + 11 e2e-Tests (gegen echte Postgres-Testdatenbank) gruen,
Lint/Typecheck/Build gruen, Login/Refresh/Logout/Rollenpruefung manuell
gegen laufenden Server verifiziert.
2026-08-21 08:22:16 +02:00
Nick Szaunig eae3fea957 feat: Grundgeruest fertigstellen (Backend/Frontend/K8s)
Backend: Prisma-Client auf prisma-client-js + Driver-Adapter (@prisma/adapter-pg)
umgestellt (Prisma 7 verlangt Adapter, ESM-Client brach an Jest), erste Migration
erzeugt und angewendet, /api/v1 Versioning, Swagger unter /api/v1/docs, Helmet,
globale ValidationPipe, PrismaModule, HealthModule (/health, /health/ready mit
DB-Check), tsconfig.build.json Root-Dir-Fix (dist/main.js statt dist/src/main.js).

Frontend: Tailwind v4 + shadcn/ui initialisiert, TanStack Query Provider, PWA
Manifest (app/manifest.ts), Vitest + Testing Library Setup, next.config output
standalone.

deploy/k8s: Dockerfiles (Backend/Frontend, Multi-Stage) + Deployment/Service/
Ingress/ConfigMap/Secret-Vorlagen fuer beide Projekte.

Lokale Dev-/Test-Postgres-Instanz unter ApiCore-Backend/.devdb angelegt (eigene
Rolle, kein bestehendes Passwort noetig), .env/.env.test lokal befuellt.

Lint, Typecheck, Tests und Build sind fuer Backend und Frontend gruen; Server
wurde lokal gestartet und /health, /health/ready, /api/v1/docs manuell verifiziert.
2026-08-21 05:17:26 +02:00
Nick Szaunig c4a2d0648e chore: planning docs + backend/frontend scaffold + MVP Prisma schema
- CLAUDE.md, ARCHITECTURE.md, TASKS.md per Lastenheft-Vorgabe
- ApiCore-Backend: NestJS scaffold, Prisma 7 (DATABASE_URL via prisma.config.ts)
- ApiCore-Frontend: Next.js App Router scaffold (TS, Tailwind, ESLint)
- prisma/schema.prisma: alle MVP-Entitaeten aus Abschnitt 13/4.2-4.22/26,
  validiert und Client generiert

Grundgeruest (TASKS.md #0) noch nicht vollstaendig: shadcn/ui, TanStack Query,
PWA-Manifest, deploy/k8s/, Dockerfiles fehlen noch.
2026-08-21 04:48:16 +02:00