Commit Graph
167 Commits
Author SHA1 Message Date
Nick SzaunigandClaude Sonnet 5 ae53f7889e feat: RBAC Phase 3 - LegacyRole-Enum, RolesGuard und @Roles vollstaendig entfernt
Letzte Phase des RBAC-Umbaus: die transitionale Rollen-Infrastruktur,
die seit Phase 1 parallel zum neuen Role/Permission-System mitlief,
ist jetzt komplett weg.

- Prisma-Migration: User.legacyRole-Spalte und LegacyRole-Enum
  gedroppt (nichts liest die Spalte mehr, seit Phase 2 jeder Controller
  auf @RequirePermission laeuft).
- roles.guard.ts, roles.guard.spec.ts, roles.decorator.ts geloescht;
  RolesGuard aus den APP_GUARD-Providern entfernt.
- AuthenticatedUser/JWT-Payload verlieren das role-Feld (permissions
  werden ohnehin frisch pro Request aus der DB aufgeloest, nicht aus
  dem Claim).
- Users-API: CreateUserDto/UpdateUserDto akzeptieren jetzt roleId
  (eine echte Role.id) statt der alten role-Enum-Werte; UsersService
  validiert, dass die Rolle existiert und aktiv ist, bevor sie
  zugewiesen wird.
- Alle 34 e2e-Fixtures und der Seed-Script folgen dem neuen Schema.

Verifiziert: tsc, lint, build, unit (220/220), volle e2e-Suite
159/159 gruen - keine uebersprungenen Tests.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 09:01:13 +02:00
Nick SzaunigandClaude Sonnet 5 0284077d3b feat: RBAC Phase 2e - Verwaltung auf @RequirePermission umgestellt, Coverage-Test aktiviert
Users, Webhooks, Automation, Import, AuditLog: die klassenweiten
@Roles(Role.ADMIN)-Blankets (die gefaehrlichsten der Migration, da sie
JEDE Route der Klasse abdecken) durch pro-Route @RequirePermission
ersetzt. Effektiver Zugriff unveraendert: ADMIN besitzt weiterhin alle
betroffenen Permission-Keys, jede andere Rolle bleibt ausgeschlossen.

Damit ist kein @Roles(...) mehr in der Codebase in Benutzung - alle
23 Controller laufen jetzt vollstaendig ueber @RequirePermission.
test/authorization-coverage.e2e-spec.ts (bisher it.skip mit TODO fuer
"nach Phase 2") ist jetzt scharf geschaltet und bestaetigt: 0 Routen
ohne Rechte-Pruefung, 0 ungueltige Permission-Keys.

Verifiziert: tsc, lint, build, unit (222/222), volle e2e-Suite
159/159 gruen - keine uebersprungenen Tests mehr.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 07:13:04 +02:00
Nick SzaunigandClaude Sonnet 5 8832081973 feat: RBAC Phase 2d - Auswertung & Ausgabe auf @RequirePermission umgestellt
Dashboard, Search, Calendar, Statistics, Qr, Export, Documents:
@Roles(...) durch @RequirePermission(...) ersetzt bzw. neu eingefuehrt
(alle diese Controller hatten zuvor gar keine Rollenpruefung -
jeder eingeloggte Nutzer konnte lesen). Documents behaelt STAFF-Zugriff
auf Upload und Loeschen.

Verifiziert: tsc, lint, volle e2e-Suite 158/159 gruen (1 getrackter Skip).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 07:09:20 +02:00
Nick SzaunigandClaude Sonnet 5 c510304813 feat: RBAC Phase 2c - Ernte & Lager auf @RequirePermission umgestellt
Harvests, Extractions, HoneyBatches, Storage, Products, Bottling,
Equipment: @Roles(...) durch @RequirePermission(...) ersetzt,
ungeschuetzte GET-Routen mit :read-Rechten geschlossen. HoneyBatches
behaelt die feine Unterscheidung relocate (auch STAFF) vs.
create/measurements (nur BEEKEEPER+); Storage bekommt konsequent
keine STAFF-Schreibrechte (deckt sich mit dem bisherigen @Roles-Stand).

Verifiziert: tsc, lint, volle e2e-Suite 158/159 gruen (1 getrackter Skip).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 07:05:32 +02:00
Nick SzaunigandClaude Sonnet 5 cdbdaedb8f feat: RBAC Phase 2b - Betrieb auf @RequirePermission umgestellt
Varroa, SwarmControl, Treatments, Feedings (+ jeweilige
Colony-Sub-Controller): @Roles(...) durch @RequirePermission(...)
ersetzt, ungeschuetzte GET-Routen mit :read-Rechten geschlossen.

Verifiziert: tsc, lint, e2e (varroa/swarm-control/treatments/feedings
einzeln gruen; volle Suite 158/159 gruen, 1 getrackter Skip).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 07:02:15 +02:00
Nick SzaunigandClaude Sonnet 5 f4b174ec56 feat: RBAC Phase 2a - Bienenvolk-Kern auf @RequirePermission umgestellt
Apiaries, Colonies, Queens, Inspections (+ ColonyInspections),
Tasks, TaskTemplates: @Roles(...) durch @RequirePermission(...) ersetzt.
Schliesst dabei die bisher ungeschuetzten GET-Routen (jeder eingeloggte
Nutzer konnte lesen, unabhaengig von seiner Rolle) mit :read-Rechten.
TaskTemplatesController verliert seinen klassenweiten @Roles-Blanket
zugunsten pro-Route-Rechten (gleiche effektive Berechtigung: nur
ADMIN/BEEKEEPER, jetzt ueber task-templates:* statt Rollen-Liste).

Verifiziert: tsc, lint, e2e (apiaries/colonies/queens/inspections/
tasks/task-templates, 29/29 gruen).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 06:57:04 +02:00
Nick SzaunigandClaude Sonnet 5 139ea6fdd7 feat: RBAC Rollen & Rechte (Phase 1 - Datenmodell, Roles-Verwaltung, Guard-Infrastruktur)
Replaces the fixed 5-value Role enum with a database-driven Role/Permission
model: admins can create custom roles with a precise per-resource/action
permission set (83-key code-owned catalog), instead of being locked to
ADMIN/BEEKEEPER/STAFF/READONLY/API_CLIENT.

- New Role/Permission/RolePermission tables; legacy Role enum renamed to
  LegacyRole and kept as User.legacyRole so all existing @Roles() call
  sites keep working unchanged during the migration.
- New RolesController/RolesService (CRUD, permission-set editing,
  deactivate/reactivate) with lockout-prevention invariants: system roles
  (ADMIN) can't be edited or deactivated, and a role still assigned to
  users can't be deactivated.
- New PermissionResolverService (30s-cached, DB-fresh per user) and
  PermissionsGuard + @RequirePermission(), registered as an additional
  APP_GUARD alongside the legacy RolesGuard so both systems run
  side-by-side until controllers are migrated in Phase 2.
- PermissionCatalogSyncService seeds any new catalog entries into the DB
  on boot, so future features only touch the TS catalog.
- New GET /auth/me returns the caller's role and effective permissions.
- Migration hand-written (destructive column rename) with grants derived
  from a fresh grep of every existing @Roles() call site, verified
  against 5 controllers read in full for STAFF's exact write boundary.
- test/roles.e2e-spec.ts covers the new endpoints and invariants end to
  end; test/authorization-coverage.e2e-spec.ts added but skipped until
  Phase 2 gives every controller a @RequirePermission.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-26 06:52:24 +02:00
Nick Szaunig d31aa79f50 feat: card-grid boxes with Aktiv/Historie split on main list pages
Replace the list-row layout with a responsive box grid (EntityCard):
icon avatar, title, badge, and 1-2 key fields visible at a glance per
box, matching what the user asked for ("Kaestchen" over rows).

Add an Aktiv/Historie tab split (ActiveHistoryTabs) so deactivated or
terminal-status entries move out of the default view instead of mixing
in with active ones:
- Apiaries, Colonies, Queens: split on deactivatedAt (the field the app
  already uses everywhere for "Historie statt Loeschen").
- Task templates: split on the existing active boolean.
- Tasks: OPEN/IN_PROGRESS vs DONE/CANCELLED.
- Honey batches: everything vs SOLD/CONSUMED.
- Products: ACTIVE vs DISCONTINUED.
- Storage containers: everything vs OUT_OF_SERVICE.
Equipment and stock items have no lifecycle field in the schema, so
they keep the plain grid without a Historie tab.

Verified live: deactivating a Bienenstand moves it out of Aktiv into
Historie immediately, both counts update, reactivating moves it back.
2026-08-26 00:25:23 +02:00
Nick Szaunig c586bff18f feat: modernize main list pages from tables to card-based rows
New shared ListItemCard component: icon avatar, title/subtitle, trailing
badges/actions, chevron affordance when linked to a detail page. Applied
to the 9 primary data-list pages (Bienenstaende, Voelker, Koeniginnen,
Honigchargen, Aufgaben, Lager, Produkte, Inventar, Wiederkehrende
Aufgaben), replacing the plain HTML tables with the same rounded-card
list aesthetic already used elsewhere in the app (inspections,
treatments, varroa, etc.), for a consistent look across the whole
product. Admin/settings tables (Benutzer, Webhooks, Audit-Log, Import)
intentionally left as tables per user's scoping choice.
2026-08-25 23:49:31 +02:00
Nick Szaunig faefd47e4b feat: dashboard tiles link to their matching list page
Each stat tile now navigates to /apiaries, /colonies, /queens, /tasks,
/honey-batches or /storage on click instead of being inert.
2026-08-25 23:21:16 +02:00
Nick Szaunig 147417d7d4 fix: address code-review findings (startup validation, shutdown hooks, health check, deploy config)
Verified each finding against the real codebase first, since the review's
diff was polluted by a stale leftover agent-worktree copy under
.claude/worktrees/ (now removed) that made several already-fixed or
never-broken issues look current (CORS, missing typecheck script, PWA
icons, font CSS, Helmet/Swagger CSP - all confirmed fine live, not
touched).

Real fixes:
- main.ts: fail-fast on missing DATABASE_URL/JWT_ACCESS_SECRET at boot,
  call enableShutdownHooks() so PrismaService.onModuleDestroy() actually
  runs on SIGTERM during k8s rolling deploys, PORT fallback 3000 -> 3001
  to match every other place that documents the port.
- health.controller.ts: log the real underlying DB error instead of
  discarding it, add a 5s timeout to the readiness query so a hung DB
  fails the probe fast instead of blocking indefinitely.
- Frontend Dockerfile: declare ARG/ENV NEXT_PUBLIC_API_URL before the
  build step, since Next.js inlines NEXT_PUBLIC_* vars at build time and
  a runtime-only ConfigMap value never reaches the compiled bundle.
- Backend ingress.yaml: drop the no-op rewrite-target regex for a plain
  prefix path (identical behavior, less confusing).
2026-08-25 23:07:29 +02:00
Nick Szaunig 3f7c4ed404 feat: Jahresbericht-PDF pro Volk/Stand
Neue PDF-Reports im Export-Modul: colony-annual-report (Durchsichten,
Behandlungen, Varroakontrollen, Schwarmkontrolle, Ernten eines Volkes fuer
ein Jahr) und apiary-annual-report (Voelker-Uebersicht + Ernten eines
Stands fuer ein Jahr). Jahr ist optional, faellt auf das aktuelle Jahr
zurueck.

Frontend: "Jahresbericht"-Button auf Volk- und Stand-Detailseite, laedt
das PDF ueber den bestehenden Blob-Download-Mechanismus herunter.
2026-08-25 11:51:41 +02:00
Nick Szaunig f1298eff08 fix: harden auth against brute force, add auth audit logging, fix cookie/TLS gaps
Security review findings (HIGH-1/2/3, MEDIUM):

- Rate limiting via @nestjs/throttler: global 100 req/min default, stricter
  10 req/min on login and refresh. Also closes the MEDIUM finding (public
  batch-lookup enumeration) since it now sits behind the global limit too.
  Trust the K8s ingress's single proxy hop so throttling keys off the real
  client IP, not the ingress pod's IP.
- Auth events (login success/failure, logout, token refresh) are now
  audit-logged via new AuditAction values, closing the gap where the
  project's own audit-log principle never actually covered the Auth module.
- Refresh-token cookie now defaults to Secure=true (opt out only via
  COOKIE_SECURE=false for local HTTP dev), instead of keying off NODE_ENV
  which was never set in the K8s deploy templates. Added a TLS block +
  cert-manager annotation to both the backend and frontend ingress
  templates, which previously had no HTTPS termination configured at all.
2026-08-25 10:49:25 +02:00
Nick Szaunig 1a7331b6b2 feat: Schwarmkontrolle-Protokoll
Neues SwarmControlCheck-Modul: strukturierte Weiselzellenkontrollen pro
Volk mit Zahl/Verdeckelungsstatus der Zellen, Schwarmstimmung, ergriffener
Maßnahme und optionalem naechsten Kontrolltermin.

Frontend: neue Karte auf der Volk-Detailseite, Erfassungsformular unter
/swarm-control/new sowie Quick-Add-Eintrag.
2026-08-25 09:12:50 +02:00
Nick Szaunig 4609a0f9ec feat: Wiederkehrende Aufgaben-Vorlagen (recurring task templates)
Neue TaskTemplate-Entität mit YEARLY/MONTHLY/INTERVAL_DAYS-Wiederholung.
Fällige Aufgaben werden lazy bei GET /tasks erzeugt (Compare-and-Swap auf
nextDueDate), damit mehrere API-Replicas im Kubernetes-Cluster dieselbe
Vorlage nicht doppelt feuern - ohne zusätzliche Cron-Abhängigkeit.

Frontend: Verwaltungsseite unter /settings/task-templates zum Anlegen,
Auflisten und Deaktivieren von Vorlagen.
2026-08-25 05:36:55 +02:00
Nick Szaunig e458a7cf07 feat: Königinnen-Abstammungsbaum (Mutterlinie)
Neue Funktion jenseits der Lastenheft-Checkliste, explizit im Text als
spätere Erweiterung angedacht (§4.4: "ApiCore SOLL später
Abstammungsbäume darstellen können"). Königin.motherQueenId ist eine
neue optionale Selbstreferenz (additive Migration), zusätzlich zu den
bestehenden freien Textfeldern motherLine/fatherLine – letztere
bleiben für Fälle, in denen die Mutter nicht selbst in ApiCore erfasst
ist. Die Vaterlinie bleibt bewusst Freitext, da eine Königin mit vielen
Drohnen aus unterschiedlichen Völkern begattet wird und es keine
einzelne "Vater-Königin" gibt, die referenzierbar wäre.

Backend: GET /queens/:id/lineage baut die mütterliche Ahnenkette
(rekursiv über motherQueenId, Tiefe 8) sowie den Töchterbaum
(rekursiv über die neue daughterQueens-Relation) in einer Antwort;
create/update lehnen eine nicht existierende oder auf sich selbst
zeigende motherQueenId ab.

Frontend: neue "Abstammungsbaum"-Karte auf der Königin-Detailseite
zeigt die mütterliche Linie als Liste sowie die Töchter als
eingerückten Baum, beide mit Links zu den jeweiligen Königinnen.
Anlage- und Bearbeiten-Formular bekommen ein "Mutter"-Auswahlfeld
(Bearbeiten schließt die Königin selbst aus der Liste aus).

Live in Chrome verifiziert: dreistufige Kette (Großmutter → Mutter →
Tochter) korrekt in beide Richtungen dargestellt; dabei einen echten
Anzeigefehler gefunden und behoben – das Mutter-Auswahlfeld zeigte
nach dem Speichern die rohe Datenbank-ID statt des Königin-Codes an
(derselbe SelectValue-ohne-children-Fehler wie zuvor bei der
Import-Entitätsauswahl).
2026-08-25 05:13:45 +02:00
Nick Szaunig 68f459001a feat: Bearbeiten für alle Log-Einträge (Aufgaben, Durchsichten, Behandlungen, Fütterungen, Varroa-Messungen, Ernten, Schleuderungen, Abfüllungen)
Bisher liessen sich diese acht Objekttypen nur anlegen, nie nachträglich
korrigieren – Aufgaben hatten zwar schon einen PATCH-Endpunkt, aber
keine Bearbeiten-UI, die übrigen sieben hatten weder Backend- noch
Frontend-Unterstützung. Jetzt bekommt jeder Typ einen PATCH :id
Endpunkt (UpdateXDto per PartialType(PickType(...)) nach demselben
Muster wie UpdateColonyDto/UpdateApiaryDto, mit Audit-Log-Eintrag
inkl. Vorher-/Nachher-Stand) sowie eine Bearbeiten-UI:

- Aufgaben: Dialog auf der Aufgabenliste
- Durchsichten/Behandlungen/Fütterungen/Varroa-Messungen: Dialog pro
  Listeneintrag auf der Volk-Detailseite
- Ernten: Dialog auf der eigenen Ernte-Detailseite
- Schleuderungen: Dialog direkt in der Rückverfolgbarkeits-Karte der
  Honigcharge (keine eigene Detailseite nötig); Erntezeilen dort
  verlinken jetzt zur Ernte-Detailseite statt sie zu duplizieren
- Abfüllungen: Dialog auf der Abfüllungs-Detailseite, bewusst nur
  Datum/MHD/Losnummer editierbar – Glasgröße/-anzahl bleiben
  unveränderlich, weil sie bereits unumkehrbar die Honigcharge-Menge
  reduziert haben

Relationsstiftende Fremdschlüssel (colonyId, apiaryId/colonyIds,
harvestIds, honeyBatchId) bleiben überall bewusst nicht editierbar,
konsistent mit dem bestehenden apiaryId-Ausschluss bei UpdateColonyDto.
2026-08-25 04:28:37 +02:00
Nick Szaunig 63ab0e842d docs: NFC-Tags in TASKS.md abgehakt 2026-08-25 01:50:26 +02:00
Nick Szaunig 53b781aa04 feat: NFC-Tags beschreiben mit demselben Deep-Link wie der QR-Code
Neuer Endpunkt GET /api/v1/qr/:entityType/:id/link liefert den vom
QR-Dienst bereits genutzten Deep-Link als reine URL statt als SVG,
damit die Web-NFC-API (client-seitig, Chrome/Android) ihn per
NDEFReader.write() auf einen physischen NFC-Tag schreiben kann.
QrService.resolveUrl() ist aus generateSvg() herausgezogen, damit
beide Endpunkte exakt denselben Link erzeugen.

Der bestehende QrCodeDialog bekommt dadurch für alle sechs
QR-fähigen Entitäten (Völker, Bienenstände, Königinnen, Honigchargen,
Lagerbehälter, Abfüllungen) automatisch einen "Auf NFC-Tag
schreiben"-Button, der nur erscheint, wenn window.NDEFReader
tatsächlich existiert – kein Fallback für andere Browser oder iOS,
wie in der Lastenheft vorgesehen.
2026-08-25 01:50:14 +02:00
Nick Szaunig f346859121 docs: Herkunftsseiten + QR-Code in TASKS.md abgehakt 2026-08-25 01:36:08 +02:00
Nick Szaunig d56550c0e5 feat: öffentliche Herkunftsseiten für Honigchargen + Kunden-QR-Code
Neuer unauthentifizierter Endpunkt GET /api/v1/public/batches/:lot
(Abschnitt 27 der Lastenheft) liefert kontrolliert freigegebene
Rückverfolgbarkeitsdaten einer Abfüllcharge – Produkt, Erntemonat,
Bienenstand-Namen, Schleuderdatum, Wassergehalt – ohne interne IDs,
Adressen oder Koordinaten preiszugeben. Die neue Seite /herkunft/{lot}
liegt außerhalb der (app)-Route-Group und damit ohne Login/Sidebar,
gedacht als Ziel eines QR-Codes auf dem Honigglas. Der bestehende
QR-Dienst kennt jetzt den Entity-Typ "bottling-batches" und verlinkt
intern auf diese neue öffentliche Seite; ein entsprechender
QR-Code-Button samt Klartext-Link steht ab sofort auf der
Abfüllungs-Detailseite bereit.
2026-08-25 01:35:47 +02:00
Nick Szaunig 711536f299 docs: Offline-PWA in TASKS.md abgehakt 2026-08-25 01:14:28 +02:00
Nick Szaunig eb66c4bd53 feat: offline-fähige PWA mit IndexedDB-Sync für Durchsichten
Service Worker (public/sw.js) cached die App-Shell für Seiten-GETs
(network-first, cache-fallback). Durchsichten, die offline gespeichert
werden, landen in einer IndexedDB-Warteschlange (idb) statt zu
scheitern und werden automatisch synchronisiert, sobald wieder
Netzwerk verfügbar ist (Mount + online-Event), mit manuellem Retry
über ein Badge im App-Header. Ein modulweiter In-Flight-Lock in
sync.ts verhindert doppelte Synchronisierung bei gleichzeitigen
Aufrufen (gefunden über React-StrictMode-Doppel-Mount, das ohne den
Lock dieselbe Durchsicht zweimal anlegte).
2026-08-25 01:14:18 +02:00
Nick Szaunig 20239885b4 docs: Kartenansicht in TASKS.md als fertig markiert
Siehe vorherigen Commit fuer Implementierung und Live-Verifikation.
2026-08-25 00:40:39 +02:00
Nick Szaunig aa3a777381 feat(frontend): Kartenansicht für Bienenstände (Später-Liste)
Neue Seite /apiaries/map zeigt alle Bienenstände mit hinterlegten
Koordinaten auf einer Leaflet-Karte (OpenStreetMap-Kacheln), mit
Marker-Popup, das zum jeweiligen Bienenstand verlinkt. Karte wird
per next/dynamic mit ssr:false geladen, da Leaflet auf window/document
zugreift.

Breiten-/Längengrad waren zwar seit dem MVP im Backend-DTO vorhanden,
aber über kein Formular erreichbar – ohne diese Lücke wäre die Karte
dauerhaft leer geblieben. Daher Breitengrad-/Längengrad-Felder auf der
Bienenstand-Anlegen- und Bearbeiten-Seite ergänzt.

Marker-Icons werden aus public/leaflet/ bedient statt aus
node_modules-Bild-Imports, da Turbopack Bilder aus node_modules nicht
als StaticImageData auflöst (führte zu "iconUrl not set"-Laufzeitfehler,
live im Browser gefunden und behoben) – der von Leaflet empfohlene
Workaround für Bundler-Icon-Probleme.

Live verifiziert: Koordinaten speichern, Karte zeigt Marker an
korrekter Position, Popup verlinkt korrekt, Empty State bei fehlenden
Koordinaten, mobile Breite ohne Overflow. Zero Konsolenfehler.
2026-08-25 00:38:08 +02:00
Nick Szaunig 4b9f5c7f47 docs: v1.x-Kette end-to-end live verifiziert, v1.x vollständig abgehakt
Kompletten Ablauf live im Browser durchgeklickt: E2E-Kette-Stand ->
E2E-V-001 -> E2E-Q-001 (zugewiesen) -> Durchsicht -> Behandlung
(Ameisensäure) -> Ernte -> Schleuderung -> Honigcharge E2E-HC-001 ->
Lagerbehälter LB-01 (Umlagerung) -> Abfüllung E2E-LOT-001 -> Produkt
"Sommerhonig 500g". Jeder Schritt mit korrekt verknüpften Daten und
ohne Konsolenfehler bestätigt.

Damit ist die gesamte v1.x-Liste aus TASKS.md abgeschlossen.
2026-08-24 23:31:03 +02:00
Nick Szaunig c50c674e94 docs: Modul 33 (Import) und Build-Grün-Checks in TASKS.md abgehakt
Backend und Frontend beide fertig, getestet und live verifiziert
(siehe die beiden vorherigen Commits). Gesamter Backend- und
Frontend-Build war während der gesamten v1.x-Arbeit durchgehend grün.

Offen bleibt nur noch die abschließende End-to-End-Verifikation der
erweiterten Kernkette (Stand -> Volk -> ... -> Produkt) als
zusammenhängender manueller Durchlauf.
2026-08-24 23:07:42 +02:00
Nick Szaunig dfea017f75 feat(frontend): CSV-Import-Seite mit Ergebnisbericht (Modul 33)
Neue Seite /settings/import (nur Administrator, Sidebar-Link unter
Verwaltung): Datentyp wählen (Bienenstände/Völker/Königinnen), CSV-Datei
hochladen, danach Ergebnisbericht mit Zusammenfassung (erstellt/
übersprungen/Fehler) und Zeile-für-Zeile-Tabelle inkl. Statusbadge und
Fehlermeldung.

Live gegen das Backend verifiziert: Upload einer CSV mit einer gültigen
und einer ungültigen Zeile erzeugt korrekt 1 erstellt / 1 Fehler mit
Validierungsmeldung, der neu angelegte Bienenstand erscheint danach in
der regulären Bienenstände-Liste. Zero Konsolenfehler.
2026-08-24 23:07:07 +02:00
Nick Szaunig 4f2f31c05f feat(backend): CSV-Import für Stammdaten (Modul 33)
Neues ImportModule mit einem abhängigkeitsfreien CSV-Parser
(src/import/csv.ts, RFC4180-artig: Quoting, escapte Anführungszeichen,
CRLF/LF) passend zum bereits im ExportModule verwendeten
Schreibformat, sodass exportierte CSVs unverändert wieder importierbar
sind.

Endpunkt: POST /import/:entity (multipart, nur Administrator) für
apiaries, colonies, queens. Jede Zeile wird über die exakt gleichen
class-validator-DTOs geprüft, die auch die regulären POST-Endpunkte
nutzen (CreateApiaryDto/CreateColonyDto/CreateQueenDto) – keine
duplizierte Validierungslogik.

Ergebnisbericht pro Zeile (erstellt/übersprungen/Fehler + Meldung):
- Colonies/Queens: Zeilen mit bereits existierendem Code werden
  übersprungen statt einen Fehler zu werfen (idempotenter Re-Import)
- Colonies lösen den Bienenstand über eine "apiaryName"-Spalte auf
  (case-insensitive), da eine CSV keine internen IDs kennen kann;
  unbekannter Name → Fehlerzeile statt Abbruch des gesamten Imports

Unit-Tests für den CSV-Parser (Quoting, escapte Anführungszeichen,
CRLF, leere Zeilen) und den ImportService (alle drei Entitäten,
Validierungsfehler, Duplikat-Skip, unbekannter Bienenstand). E2E-Tests
über echten multipart-Upload (Rollenprüfung, Dateiendungsprüfung, alle
drei Entitäten, Re-Import-Idempotenz).
2026-08-24 23:00:46 +02:00
Nick Szaunig e051ad956b docs: Modul 30 (Automatisierungen) in TASKS.md als fertig markiert
Backend und Frontend beide fertig, getestet und live verifiziert
(siehe die beiden vorherigen Commits).
2026-08-24 22:47:58 +02:00
Nick Szaunig 5d32026092 feat(frontend): Automatisierungen-Verwaltung + erreichbare Trigger (Modul 30)
Neue Seite /settings/automation-rules (nur Administrator, Sidebar-Link
unter Verwaltung): zeigt alle drei fest hinterlegten Regeln mit
Beschreibung, Aktiv/Inaktiv-Umschalter, editierbarem Aufgabentext und
– nur bei Varroa-Schwellenwert – editierbarem Schwellenwert.

Zusätzlich zwei Lücken im Durchsicht-Formular geschlossen, ohne die
wären zwei der drei Trigger über die Oberfläche nie auslösbar gewesen:
- "Stifte vorhanden"-Checkbox ergänzt (eggsPresent wurde vom Formular
  bisher gar nicht gesendet, obwohl Backend und Typ es unterstützen)
- "Futtervorrat ausreichend"-Checkbox durch ein Select mit
  ausreichend/niedrig/kritisch ersetzt (bisher nur binär, "kritisch"
  war nicht erreichbar)

Live gegen das Backend verifiziert: Speichern einer Durchsicht mit
Königin nicht gesehen + keine Stifte erzeugt automatisch die erwartete
Aufgabe (sichtbar unter /tasks) und eine Benachrichtigung, zero
Konsolenfehler. Aktiv/Inaktiv-Umschalter auf der Automatisierungen-Seite
live getestet.
2026-08-24 17:34:29 +02:00
Nick Szaunig 3f47a6ae8d feat(backend): Automatisierungen mit drei fest hinterlegten Triggern (Modul 30)
Neues AutomationModule mit AutomationRule-Modell (ein Row je Trigger-Typ,
per Unique Constraint erzwungen). Drei fest im Code hinterlegte Trigger,
die Admins nur aktivieren/deaktivieren bzw. deren Konfiguration/Aufgaben-
text anpassen können:

- QUEENLESS_NO_EGGS: Königin nicht gesehen UND keine Stifte vorhanden
  (bei Durchsicht) → Kontrollaufgabe
- VARROA_THRESHOLD: Varroa-Schwellenwert überschritten (konfigurierbar,
  Standard 10 Milben/Tag) → Behandlungsprüfung
- FEED_STATUS_CRITICAL: Futterstatus "kritisch" (bei Durchsicht) →
  Fütterungsaufgabe

Jeder ausgelöste Trigger erzeugt eine Task UND eine Notification sowie
einen Audit-Log-Eintrag; Tasks lösen zusätzlich das bestehende
task.created-Webhook aus. InspectionsService und VarroaService rufen
die Auswertung direkt nach dem jeweiligen Erstellen auf.

Neue Endpunkte (nur Administrator): GET/PATCH /automation-rules.

Unit-Tests für AutomationService (alle drei Trigger, Deaktivierung,
Update mit Audit-Log) sowie E2E-Tests (Rollen-Check, alle drei Trigger
end-to-end über echte Inspection-/Varroa-Endpunkte, Deaktivierung
verhindert weitere Trigger). E2E-Suite zweimal hintereinander grün
verifiziert (Idempotenz der globalen Regel-Zeilen sichergestellt).
Migration auf Dev- und Test-Datenbank angewendet.
2026-08-24 17:25:42 +02:00
Nick Szaunig 42a2be31b4 docs: Modul 32 (Lagerbehälter-Umlagerung) in TASKS.md als fertig markiert
Backend und Frontend beide fertig, getestet und live verifiziert
(siehe die beiden vorherigen Commits).
2026-08-24 17:07:11 +02:00
Nick Szaunig 15f5ab57ae feat(frontend): Lagerbehälter-Sektion und Umlagerungshistorie (Modul 32)
Neue HoneyBatchStorageCard-Komponente auf der Honigcharge-Detailseite:
zeigt den aktuell zugeordneten Lagerbehälter, einen "Umlagern"-Dialog
(Ziel-Lagerbehälter wählen, optionale Notiz) und die vollständige
Umlagerungshistorie (von/nach, Zeitpunkt, Notiz) im etablierten
EmptyState-Stil.

HoneyBatch-Typ um storageContainer erweitert, neue
HoneyBatchRelocation/RelocateHoneyBatchInput-Typen und passende
API-Funktionen ergänzt. Live gegen das Backend verifiziert: Umlagerung
zwischen zwei echten Lagerbehältern aktualisiert die Anzeige und die
Historie korrekt, zero Konsolenfehler.
2026-08-24 17:06:54 +02:00
Nick Szaunig 59a320ae36 feat(backend): Lagerbehälter-Umlagerung für Honigchargen (Modul 32)
Neues HoneyBatchRelocation-Modell dokumentiert jede Umlagerung einer
Honigcharge zwischen Lagerbehältern (von/nach, Zeitpunkt, Benutzer,
Notiz). HoneyBatchesService.relocate() aktualisiert
HoneyBatch.storageContainerId transaktional zusammen mit dem
Historieneintrag; wirft NotFoundException bei unbekanntem Zielbehälter.

Neue Endpunkte: POST /honey-batches/:id/relocate,
GET /honey-batches/:id/relocations. honeyBatchInclude liefert jetzt
zusätzlich den aktuell zugeordneten storageContainer mit.

Unit- und E2E-Tests ergänzt (Mehrfachumlagerung, Historienreihenfolge,
404 bei unbekanntem Behälter). Migration auf Dev- und Test-Datenbank
angewendet.
2026-08-24 16:55:15 +02:00
Nick Szaunig fa13543578 docs: Modul 29 (Dokumente und Bilder) in TASKS.md als fertig markiert
Backend war bereits fertig, Frontend-Upload-Widget wurde soeben ergänzt
und live verifiziert (siehe vorheriger Commit). Anmerkung ergänzt, dass
Durchsicht keine eigene Detailseite hat und daher aktuell nicht
angebunden ist.
2026-08-24 16:43:36 +02:00
Nick Szaunig a21563cc76 feat(frontend): Dokumente-Upload-Widget (Modul 29 Frontend)
Backend war bereits fertig, das Frontend fehlte bislang. Neue
gemeinsame DocumentUploadCard-Komponente (Liste hochgeladener Dateien,
Upload per Dateiauswahl, Download, Löschen mit Bestätigungsdialog da
unumkehrbar) plus dazugehöriges src/lib/documents/ API-Modul.

apiFetch erzwingt bislang immer Content-Type: application/json, was
multipart-Uploads verhindert hätte – daher neue apiFetchFormData-
Hilfsfunktion in api-client.ts ergänzt (kein manuell gesetzter
Content-Type, damit der Browser die multipart-Boundary selbst setzt).

Eingebunden auf allen Detailseiten, die laut TASKS.md Modul 29 vorsehen
und tatsächlich eine eigene Route haben: Bienenstand, Volk, Königin,
Honigcharge. Durchsicht hat keine eigene Detailseite (nur Einträge in
der Volk-Unterliste) und wird daher vorerst ausgelassen.

Live verifiziert: Upload, Download und Löschen (inkl. Bestätigungsdialog)
funktionieren End-to-End gegen das Backend, zero Konsolenfehler auf
allen vier Detailseiten.
2026-08-24 16:43:18 +02:00
Nick Szaunig 9a32c6c11d feat(frontend): Icon-Badges auf Abfüllungs- und Ernte-Detailkarten
Header von BottlingBatchDetailPage und HarvestDetailPage um Icon-Badge
(Package bzw. Boxes im Honig-Gradient) ergänzt, konsistent zum bereits
überarbeiteten Look aller anderen Detailseiten. Schließt die letzten
beiden verbliebenen Detailseiten ohne Icon-Badge ab.
2026-08-24 14:50:34 +02:00
Nick Szaunig c0922387fd feat(frontend): EmptyState statt Fließtext in verschachtelten Listen
Ersetzt den bisherigen reinen Fließtext ("Noch keine X dokumentiert.")
durch die gemeinsame EmptyState-Komponente (Icon, Titel, Beschreibung)
in allen verschachtelten Listen auf den Volk- und Königin-Detailseiten:
Fütterung, Behandlungen, Varroa, Durchsichten, Historie (Volk und
Königin), Bewertungen und Honigmessungen.

Rundet den bereits umgesetzten EmptyState-Look der Hauptlistenseiten
konsistent auf die Detailseiten-Unterkarten ab.
2026-08-24 00:27:04 +02:00
Nick Szaunig e889edd6c5 feat(frontend): PageHeader mit Icon auf allen 13 "Neu"-Formularseiten
Ersetzt die bisherige schlichte CardTitle-Überschrift durch die
gemeinsame PageHeader-Komponente (Icon-Badge im passenden Gradient,
Titel, kurze Beschreibung) auf allen Formularseiten zum Anlegen neuer
Datensätze (Bienenstände, Völker, Königinnen, Aufgaben, Produkte,
Inventar, Schleuderungen, Abfüllungen, Durchsichten, Varroamessungen,
Behandlungen, Fütterungen, Ernten).

Konsistent zum bereits überarbeiteten Look der Listen- und Detailseiten;
die Beschreibungszeile gibt zusätzlich beim Öffnen sofort Kontext, was
die Seite tut – hilfreich für Nutzer, die schnell zwischen vielen
Formularen wechseln.
2026-08-24 00:21:41 +02:00
Nick Szaunig ebfbd2ef6d feat(frontend): Leerer-Zustand-Komponente für alle Listenseiten
Neue gemeinsame EmptyState-Komponente (Icon in Kreis, Titel, Beschreibung,
gestrichelter Rahmen) und Einbindung auf allen 9 Listenseiten mit Tabellen
(Völker, Bienenstände, Königinnen, Aufgaben, Honigchargen, Benutzer,
Inventar, Produkte, Lager mit Behältern und Artikeln).

Bug behoben: Bei leerem Datensatz wurde bisher nur eine Tabelle mit
Kopfzeile und keinerlei Inhalt oder Erklärung angezeigt – wirkte wie ein
Ladefehler statt eines normalen "noch keine Daten"-Zustands. Besonders
für neurodivergente Nutzer wichtig, da Unklarheit über den Systemzustand
("ist das kaputt oder einfach leer?") unnötige kognitive Last erzeugt.
2026-08-23 21:03:59 +02:00
Nick Szaunig fc88c272ae feat(frontend): Icon-Badges auf Honigcharge- und Inventar-Detailkarten
Header von HoneyBatchDetailPage und EquipmentDetailPage um Icon-Badge
(Droplet im Honig-Gradient bzw. Wrench im Himmel-Gradient) ergänzt,
konsistent zum bereits überarbeiteten Look der übrigen Detailseiten.
2026-08-23 20:59:28 +02:00
Nick Szaunig 5be352c4a0 feat(frontend): Icon-Badges auf Detailseiten-Karten (Volk/Bienenstand/Königin)
Header von ColonyEditCard, ApiaryEditCard und QueenEditCard um Icon-Badge
im Honig-/Salbei-Gradient ergänzt, passend zum bereits überarbeiteten
Look der Listen- und Übersichtsseiten.

Zusätzlich Bug behoben: ColonyEditCard und QueenEditCard nutzten bislang
ein hartcodiertes ACTIVE-Ternary statt der gemeinsamen statusTone()-Hilfsfunktion,
wodurch z. B. WEAK/CONSPICUOUS/DISSOLVED-Völker und LOST/DECEASED-Königinnen
auf der eigenen Detailseite nur als neutrales "secondary"-Badge statt in
Warn-/Fehlerfarbe erschienen.
2026-08-23 20:57:01 +02:00
Nick Szaunig 6c764bf885 feat(frontend): PageHeader auf den restlichen Hauptseiten
Inventar, Produkte, Lager, Kalender, Suche und Audit-Log bekommen den
gleichen Gradient-Icon-Header wie die uebrigen Seiten. Lager-Seite hatte
zwei h1-artige Ueberschriften fuer zwei Abschnitte (Lagerbehaelter/
Lagerartikel) auf einer Seite; jetzt ein PageHeader fuer die Seite plus
gleich grosse Unterueberschriften fuer beide Abschnitte statt
uneinheitlicher Groessen.
2026-08-23 20:48:03 +02:00
Nick Szaunig 805effb60b feat(frontend): kontrastreichere Tabs
Aktiver Tab war kaum vom Tab-Leisten-Hintergrund zu unterscheiden
(fast gleicher Ton). Jetzt weisser Karten-Hintergrund mit Schatten
und Primaerfarben-Text fuer den aktiven Tab, groesserer Radius/Padding
passend zum Rest der Oberflaeche.
2026-08-23 20:33:09 +02:00
Nick Szaunig 60b59c120a feat(frontend): einheitliche Seiten-Header mit Icon-Badge
Neue PageHeader-Komponente (Gradient-Icon-Badge + Titel + Beschreibung
+ Aktionen) ersetzt die nackten <h1>-Zeilen auf den meistgenutzten
Seiten (Voelker, Bienenstaende, Koeniginnen, Aufgaben, Honigchargen,
Statistik, Webhooks, Benutzerverwaltung). Gradient variiert pro
Bereich (Honig/Salbei/Himmel), passend zum jeweiligen Sidebar-Icon.
2026-08-23 20:31:03 +02:00
Nick Szaunig 3af56c96fa feat(frontend): Gradient-Buttons, weichere Formulare und Dialoge
Primaerer Button-Stil nutzt jetzt den Honig-Gradient statt Volltonfarbe,
mit Schatten und Hover-Lift. Buttons/Inputs/Select/Textarea/Dialog auf
rounded-xl bzw. rounded-2xl vereinheitlicht, Formularfelder mit Karten-
hintergrund, dezentem Schatten und Hover-Rahmen statt nacktem Rand.
Dialog-Footer-Radius/Aussenabstand an das groessere Popup-Padding
angepasst, sonst waere die Ecke am Fusszeilen-Rand versetzt gewesen.
2026-08-23 20:23:54 +02:00
Nick Szaunig 6a97ebc594 feat(frontend): Karten-Rahmen und ruhigere Typografie fuer alle Tabellen
Die geteilte Table-Komponente (11 Listenseiten: Voelker, Bienenstaende,
Koeniginnen, Aufgaben, Honigchargen, Inventar, Produkte, Lager, Benutzer,
Audit-Log, Webhooks) bekommt jetzt denselben Karten-Rahmen/Schatten wie
der Rest der Oberflaeche statt nackt auf dem Hintergrund zu schweben,
plus getoente Kopfzeile, ruhigere Uppercase-Spaltentitel und mehr
Zeilenabstand.
2026-08-23 20:13:56 +02:00
Nick Szaunig 5cacc3c60d feat(frontend): moderneres visuelles Redesign (Farben, Tiefe, Dashboard-Hero)
Kartenhintergrund und Seitenhintergrund waren fast farbgleich, wodurch
alles flach wirkte trotz vorhandenem Schatten. Staerkerer Kontrast
(--background/--card/--muted/--border), neue Gradient- und
Schatten-Tokens (--gradient-honey/-sage/-sky, --shadow-soft/-elevated).

Card-Komponente: rounded-2xl, echter sichtbarer Schatten, optionaler
Hover-Lift (interactive-Prop). Sidebar: solide Gradient-Badge, kraeftiger
Active-Pill-Zustand statt blassem Tint. Header: sticky mit Blur-Schatten
statt hartem Rand. Dashboard: Gradient-Hero mit Begruessung und
Honeycomb-Muster, farbige Gradient-Icon-Badges pro KPI-Kachel,
Hinweise-Zeilen mit Icon statt rohem Enum-Badge (dabei toten
CONSPICUOUS_COLONY-Style-Key gefunden und auf COLONY_ATTENTION
korrigiert). Honeycomb-Hintergrund aus der Login-Seite in eine
gemeinsame Komponente extrahiert und dort mit dem gleichen
Gradient-Badge-Header konsistent gemacht.
2026-08-23 20:10:33 +02:00
Nick Szaunig 6ab028d1be feat(frontend): confirmation dialogs and undo for destructive-feeling actions
Volk aufloesen, Bienenstand deaktivieren, Benutzer deaktivieren und
Webhook loeschen liefen bisher ohne jede Rueckfrage direkt auf Klick.
Neue wiederverwendbare ConfirmDialog-Komponente erzwingt jetzt eine
bewusste Bestaetigung. Zusaetzlich zeigen Volk/Bienenstand/Benutzer
nach dem Aufloesen/Deaktivieren einen Reaktivieren-Button (nutzt die
neuen Backend-Endpunkte), da diese Aktionen nie ein echtes Loeschen
sind und ein versehentlicher Klick bisher nicht rueckgaengig zu
machen war.
2026-08-23 11:50:45 +02:00