21 KiB
Code-Review und Umsetzungsvorschlag
Historischer Ausgangsbefund. Der aktuelle Umsetzungs- und Prüfstand steht in IMPLEMENTATION.md.
Stand: 01.10.2026. Repository: https://git.jfritzsche.de/jf/taskmanager.git
Geprüfter Commit: c2e00ff13a90041c43bdbdbebff51362f557ac40.
Umfang und Ergebnis
Geprüft wurden Datenmodell, sämtliche API-Handler, Authentifizierung, Rechteprüfungen, Uploads, zentrale UI-Abläufe, Datenabruf und Docker-Konfiguration. Die Anwendung basiert auf Next.js App Router, React, NextAuth mit Credentials/JWT, Prisma und PostgreSQL. Positiv sind serverseitige API-Prüfungen, Passwort-Hashing mit bcrypt, überwiegend explizite Benutzerprojektionen ohne Passwort und Zod-Validierung. Die vorhandene Rollenlogik ist bereits eine einfache Form von RBAC, aber fest im Code verdrahtet, ohne Gruppen und mit inkonsistenten Objektregeln.
Das Ergebnis ist ein Review mit Umsetzungsvorschlag; Anwendungscode und Datenbank wurden nicht umgebaut. Keine Prüfung einer produktiven Instanz und keine Exploit-Ausführung. Externe Reverse-Proxy-Regeln, produktive Secrets und tatsächlicher Deployment-Stand sind unbekannt.
Priorisierte Sicherheitsbefunde
S1 – Kritisch: verwundbare Framework-Version im Lockfile
package-lock.json fixiert Next.js 16.0.1 und React 19.2.0. Die Anwendung verwendet den App Router. Next.js dokumentiert für diese Versionslinie die kritische RSC-Lücke mit möglicher Remote-Code-Ausführung (CVE-2025-66478 / upstream CVE-2025-55182). Das ist unabhängig von den eigenen Rollenprüfungen zu behandeln.
Maßnahme: Next/React und zusammengehörige Pakete auf einen zum Umsetzungszeitpunkt unterstützten, gepatchten Stand heben, Lockfile reproduzierbar neu erstellen und Regressionstests ausführen. Nicht allein den historischen ersten Fix 16.0.7 als heute ausreichend betrachten. Falls genau dieser Stand öffentlich betrieben wurde: nach Patch Deployment und Secrets auf mögliche Kompromittierung prüfen und Secrets rotieren.
Quelle: https://nextjs.org/blog/CVE-2025-66478
S2 – Hoch: Vorgesetzte können Adminrechte erlangen
Belege: src/app/api/users/[id]/route.ts:28, :80, :84; src/app/api/users/route.ts:69, :111; src/lib/validations/user.ts:18.
canManageUsers erlaubt VORGESETZTER und ADMIN. Danach werden sämtliche Rollen einschließlich ADMIN akzeptiert. Ein Vorgesetzter kann sein eigenes Benutzerobjekt mit role: ADMIN ändern und sich neu anmelden oder einen neuen Admin anlegen. Zusätzlich darf er das Passwort bestehender Admins ändern. Eine Einschränkung der Rollenauswahl im Frontend würde dies nicht beheben.
Maßnahme: Profilpflege, Passwort-Reset und Rechtevergabe als getrennte Permissions behandeln. Geschützte Administratoren dürfen nur durch ausdrücklich autorisierte Administratoren geändert werden. Auch Gruppenmitgliedschaften und Rollen-Permission-Zuordnungen als mögliche Eskalationswege absichern. Letzten aktiven Administrator vor Entfernung/Deaktivierung schützen, auch bei konkurrierenden Requests.
S3 – Hoch: Rechteentzug und Benutzerlöschung entwerten Sitzungen nicht
Beleg: src/lib/auth.ts:86–100. Rollen werden beim Login in das JWT kopiert und anschließend ungeprüft wiederverwendet. Die API lädt den aktuellen Benutzerstatus nicht nach.
Nach Herabstufung oder Löschung kann ein bestehendes Token weiterhin die alten Rechte liefern. Passwortänderungen widerrufen ebenfalls keine bestehenden Tokens. Einzelne Schreibaktionen können anschließend an Fremdschlüsseln scheitern; das ist kein verlässlicher Zugriffsschutz.
Maßnahme: zentraler serverseitiger Principal-Resolver, der Existenz, Aktivstatus und aktuelle Berechtigungen prüft. Bei JWT-Nutzung serverseitig geprüfte Session-Version oder widerrufbare Session-ID vorsehen. Rechte- und Gruppenänderungen müssen sofort wirksam werden. Ein Permissions-Array in einem langlebigen JWT allein löst das Problem nicht.
S4 – Hoch: Uploads haben keinen geschützten Downloadweg
Belege: src/app/api/tasks/[id]/files/route.ts:159–180, src/components/tasks/file-section.tsx:74, src/middleware.ts.
Dateien landen unter public/uploads; die Oberfläche verlinkt direkt auf /uploads/.... Diese Pfade liegen außerhalb des Middleware-Matchers. Soweit Dateien vom Deployment statisch ausgeliefert werden, umgeht der Direktlink alle Aufgabenrechte. Ob zur Laufzeit neu hinzugefügte Dateien sofort statisch erreichbar sind, hängt vom Next.js-/Deployment-Verhalten ab und wurde nicht live geprüft. Die Speicherarchitektur ist in beiden Fällen ungeeignet für vertrauliche Anhänge.
Maßnahme: privater Speicher außerhalb von public, zufälliger Storage-Key und Download-Route mit aktueller Session, files.read und Objektprüfung. Vorhandene Dateien migrieren und alte öffentliche Auslieferung unterbinden. Downloads mit geeigneten Content-Type-, Content-Disposition- und nosniff-Headern senden.
S5 – Hoch bei unveränderter Verwendung: bekannte Startzugänge und Secrets
Belege: prisma/seed.ts:14–30, start.sh:24–36, docker-compose.yml:12–37.
Seed erstellt einen Administrator mit bekanntem Passwort. Containerstart führt Seed wiederholt aus. Seed loggt den kompletten User einschließlich Passwort-Hash; Startskript loggt das Standardpasswort. Compose enthält festes Datenbankpasswort und bekanntes NextAuth-Secret. Ein gelöschter Seed-Admin kann beim nächsten erfolgreichen Seed erneut entstehen.
Maßnahme: einmaliger Bootstrap mit separat bereitgestelltem Zufallsgeheimnis, erzwungener Passwortänderung und ohne Geheimnisse im Log. Produktion muss bei fehlenden/unsicheren Secrets abbrechen. Kein automatisches Benutzer-Seeding bei jedem Start. Produktive Konfiguration ist nicht eingesehen worden.
S6 – Mittel bis hoch: Upload-Validierung und Ressourcenverbrauch
Beleg: src/app/api/tasks/[id]/files/route.ts:125–171.
Die Prüfung vertraut dem vom Client gelieferten MIME-Type. Der ursprüngliche Dateiname inklusive Endung wird weiterverwendet. Dadurch können andere Inhalte unter einem erlaubten MIME-Type hochgeladen werden; aktive Inhalte unter einer HTML-Endung könnten bei entsprechender statischer Auslieferung im Anwendungsursprung ausgeführt werden. Die 10-MB-Prüfung erfolgt erst nach dem Parsen des gesamten Multipart-Bodys. Quoten und Upload-Ratenbegrenzung fehlen im Repository.
Maßnahme: Inhaltssignatur/Containerformat prüfen, Endung selbst aus validiertem Typ ableiten, UUID-Speichernamen verwenden, Gesamtrequest vor bzw. während des Einlesens begrenzen, Benutzer-/Teamquoten und Rate-Limits einführen. Schadsoftwareprüfung je nach Einsatzumgebung ergänzen. Download immer über den geschützten Weg aus S4.
S7 – Mittel: fehlende Login-Begrenzung und uneinheitliche Objektregeln
src/lib/auth.ts enthält keine Anmelde-Ratenbegrenzung. src/lib/validations/user.ts akzeptiert neue Passwörter ab sechs Zeichen. Externe Schutzmaßnahmen sind unbekannt. Empfehlung: Rate-Limit nach Konto und IP, normalisierte E-Mail-Adressen, längere Passwörter mit expliziter Byte-Grenze bei bcrypt, sichere Reset-/Einladungsabläufe und MFA oder SSO.
Bearbeiter dürfen erledigte Aufgaben im Detail nicht lesen, über die Kommentar- und Datei-Listen aber weiterhin zugehörige Daten abrufen. canChangeStatus prüft nur die Zuweisung und erlaubt so das Wiederöffnen einer erledigten Aufgabe über die API; canAddComment erlaubt weiter Kommentare. Belege: src/app/api/tasks/[id]/route.ts, src/app/api/tasks/[id]/comments/route.ts, src/app/api/tasks/[id]/files/route.ts, src/lib/permissions.ts. Empfehlung: gemeinsame Objekt- und Statusregeln für alle Unterressourcen; Archiv-Lesezugriff und Wiederöffnen bewusst modellieren.
Funktionsfehler und technische Qualität
| Priorität | Befund | Umsetzung |
|---|---|---|
| Hoch | Normales npm ci --ignore-scripts scheitert: preact@10.11.3 fehlt im Lockfile. Docker verwendet ebenfalls npm ci. |
Abhängigkeiten/Peer-Abhängigkeiten konsistent auflösen; saubere Installation in CI erzwingen. |
| Hoch | Mehrere Handler nutzen validation.error.errors, installiert ist Zod 4. |
Einheitlich .issues verwenden und Fehlerantworten testen. |
| Hoch | Datei-DELETE nutzt synchrone params, während Next 16 asynchrone Route-Parameter verlangt. |
params als Promise typisieren und vor Zugriff awaiten. |
| Mittel | Pfleger darf Aufgaben erstellen, aber useUsers() ruft die nur für Benutzerverwalter erlaubte API auf; assigneeId ist Pflicht. |
Eigenen, minimalen und nach Geltungsbereich gefilterten Assignee-Endpunkt mit tasks.assign schaffen. |
| Mittel | Middleware prüft /users, echte Seite liegt unter /dashboard/users. |
Server-Prüfung der echten Seite; API-Prüfungen behalten. Aktuell kein dadurch belegter API-Datenzugriff. |
| Mittel | Aufgabenlöschung kaskadiert nur DB-Dateieinträge, nicht die Dateien auf Disk. Upload kann vor fehlgeschlagenem DB-Insert eine Datei hinterlassen. | Wiederholbaren Cleanup-Job/Outbox, Fehlerkompensation und Abgleich verwaister Dateien vorsehen. |
| Mittel | Benutzerlöschung scheitert bei verknüpften erstellten Aufgaben/Kommentaren an RESTRICT-Fremdschlüsseln. | Deaktivierung statt Standard-Hard-Delete; Historie erhalten und Löschkonzept separat definieren. |
| Mittel | Dashboard zählt „Alle Aufgaben“ aus standardmäßig nur offenen Aufgaben; „Neueste“ verwendet nach Fälligkeit sortierte Liste. | Eigene autorisierte Statistikabfrage und korrekte Sortierung/Bezeichnung. |
| Mittel | Ungültige Statusfilter/kaputtes JSON/Fremdschlüsselfehler werden teilweise zu 500. beauftragtAm: null wird beim PATCH zu undefined und löscht das Datum nicht. |
Query- und Body-Schemas, explizite null-Semantik sowie konsistente 400/404/409-Fehler. |
| Mittel | next lint ist in Next 16 entfernt; keine Test-Suite oder CI-Konfiguration gefunden. |
ESLint Flat Config, separates Typecheck-Skript, API-Integrationstests und Build-Pipeline. |
| Mittel | Docker übernimmt alle node_modules einschließlich Entwicklungswerkzeugen; Prisma-Konfiguration benötigt DATABASE_URL bereits beim Laden. | Migration als eigenen Deployment-Schritt, schlankes Runtime-Image, Build ohne produktive Secrets verifizieren. Upload-Verzeichnis gehört im Image nicht explizit nextjs. |
| Niedrig | Mehrere any-Typen, doppelte Upload-Validierung, Auth-Adapter per as any; Schema hat keine vollständigen Adapter-Modelle. |
DTOs für JSON-Daten, eine Upload-Policy, Auth-Konfiguration bewusst auf Credentials/JWT zuschneiden oder Adapter-Schema vollständig implementieren. |
Next-16-Kompatibilität: https://nextjs.org/docs/app/guides/upgrading/version-16
Optimierungsmöglichkeiten
- Aufgabenlisten paginieren und serverseitig suchen/filtern. Aktuell werden alle Aufgaben inklusive sämtlicher Kommentare, Autoren und Dateien geladen (
src/app/api/tasks/route.ts:51). Listen benötigen Zusammenfassungen und Zähler; Details separat nachladen. - Kalender nur für den sichtbaren Zeitraum laden. Derzeit werden alle Aufgaben geladen und für jeden Tag erneut gefiltert. Einmalige Gruppierung nach Datum und eine leichte Kalenderprojektion verwenden.
- Zehnsekunden-Polling in
src/hooks/use-tasks.tsreduzieren. Bei 100 aktiven Clients entstehen allein für eine Listenabfrage ungefähr 600 Requests pro Minute. Zunächst gezielte Cache-Invalidierung und längere Intervalle, bei echtem Bedarf SSE mit Autorisierung und Wiederverbindung. - Query-Keys für Listen und Details trennen; doppelte Invalidierung entfernen. Formulare nicht bei jedem Hintergrund-Refetch zurücksetzen, während der Nutzer Änderungen eingibt (
task-modal.tsx, Reset-Effekt). - Indizes anhand realer Abfragen/EXPLAIN planen, z.B. Zuweisung + Fälligkeit und Team + Fälligkeit. Der zusätzliche normale E-Mail-Index neben dem Unique-Index ist voraussichtlich redundant. Nicht ohne Messung weitere Indizes anlegen.
- Parallele Änderungen durch Versionsnummer/optimistische Sperre absichern. Ein veraltetes Formular sollte 409 mit Neuladeoption erhalten statt fremde Änderungen zu überschreiben.
- Explizites Datumsmodell: Ist „bis wann“ ein Kalendertag oder Zeitpunkt? Bei Tagesfristen date-only und definierte Zeitzone verwenden; aktuelle
isPast-Prüfung kann Aufgaben am Fälligkeitstag bereits als überfällig markieren.
Zielbild: Benutzer, Gruppen, Rollen und Permissions
Empfehlung: Gruppen bilden organisatorische Teams, Rollen bündeln Fähigkeiten. Ein Benutzer kann mehreren Gruppen angehören. Rechte ergeben sich aus expliziten Rollenzuweisungen mit Geltungsbereich. Gruppenname und Rollenname haben keine Sonderwirkung im Code.
User --< UserGroup >-- Group
Group --< GroupRoleBinding >-- Role --< RolePermission >-- Permission
User --< UserRoleBinding >-- Role (optional, für gezielte Ausnahmen)
Task --> owningGroupId
Task --> assigneeId
Vorgeschlagene Tabellen:
| Modell | Zentrale Felder/Regeln |
|---|---|
| User | id, emailNormalized (unique), name, passwordHash, active, sessionVersion |
| Group | id, key (unique), name, active |
| UserGroup | userId + groupId als zusammengesetzter Schlüssel |
| Role | id, key (unique), name, systemProtected |
| Permission | id, key (unique); ausführbare Aktionen als versionierter Katalog |
| RolePermission | roleId + permissionId als zusammengesetzter Schlüssel |
| GroupRoleBinding | groupId, roleId, scope: ASSIGNED / GROUP / GLOBAL |
| UserRoleBinding | userId, roleId, scope; bei GROUP explizite targetGroupId |
| Task | zusätzliche owningGroupId, version; vorhandene assigneeId bleibt |
| AuditEvent | actorId, action, targetType/id, Zeitpunkt, strukturierte Änderungen ohne Secrets |
GROUP bedeutet bei GroupRoleBinding die bindende Gruppe; bei UserRoleBinding die explizite Zielgruppe. Kombinationen per Datenbank-Constraint validieren und doppelte Bindings ausschließen. Individuelle Rollenzuweisungen zunächst sparsam einsetzen, direkte User-Permissions weglassen. Keine verschachtelten Gruppen oder Deny-Regeln in Version 1.
Permissions beispielsweise: tasks.read, tasks.create, tasks.update, tasks.assign, tasks.change_status, tasks.reopen, tasks.delete, comments.read, comments.create, files.read, files.upload, files.delete, users.read, users.create, users.update, users.deactivate, users.reset_password, groups.manage, groups.members.manage, roles.manage, roles.assign, audit.read.
Administrations-Permissions zunächst nur GLOBAL erlauben. Aufgaben-Permissions wirken im Scope ihrer Zuweisung. ASSIGNED bedeutet tatsächlich zugewiesen, nicht automatisch selbst erstellt. GROUP prüft owningGroupId; GLOBAL erlaubt alle Gruppen. Mehrere erlaubende Bindings vereinigen sich. Fehlende Permission bedeutet Ablehnung. Gruppenverwaltung darf nicht automatisch Rechtevergabe erlauben: Mitgliedschaft in einer privilegierten Gruppe ist selbst eine Rechtevergabe.
Beispiel: Jana ist in „Haustechnik“ mit Rolle „Bearbeiter“, Scope ASSIGNED. Sie kann ihre zugewiesenen Aufgaben lesen, kommentieren und deren Status ändern. Eine Teamleitung mit Scope GROUP sieht und bearbeitet Aufgaben der Haustechnik, erhält aber keine Benutzer- oder Adminrechte. Ein Koordinator kann Aufgaben anlegen und zuweisen, ohne Benutzerkonten verwalten zu dürfen.
Technische Durchsetzung
- Ein serverseitiges
authorize(principal, permission, resource)entscheidet anhand aktueller DB-Daten. Listen verwenden denselben Geltungsbereich als Prisma-Filter, einschließlich Zähler/Statistiken und Unterressourcen. - Jede API prüft Berechtigung und Objektzugehörigkeit. Das Frontend verwendet abgeleitete Fähigkeiten nur zum Anzeigen passender Aktionen. Middleware dient der Navigation und grundlegenden Anmeldung.
- Statusübergänge bleiben eigene Fachregeln: beispielsweise Löschen nur erledigter Aufgaben; Wiederöffnen benötigt eine eigene Permission. Lesen erledigter Aufgaben sollte standardmäßig möglich bleiben, soweit der Scope passt, und nicht durch Listenfilter verboten werden.
- Änderungen von Rollen, Mitgliedschaften, Aktivstatus und Passwörtern widerrufen relevante Sessions bzw. invalidieren Autorisierungs-Caches. Benutzer-/Rollen-Cache darf keinen unkontrollierten Rechtefortbestand erzeugen.
- Vergabe administrativer Rechte, Änderung geschützter Rollen und letzter Admin benötigen besondere, transaktionale Prüfungen und Audit-Protokollierung. Benutzerverwaltung allein berechtigt nie zum Vergeben beliebiger Rollen.
Migration ohne unbeabsichtigte Rechteausweitung
- Aktuelle Rechte als API-Testmatrix festhalten; bekannte Eskalationen vorher schließen.
- Tabellen und Permission-Katalog ergänzen, bestehendes Rollenfeld zunächst beibehalten.
- Bestehende Rollen explizit in Startrollen überführen. Dabei die unsichere Admin-Vergabe durch Vorgesetzte ausdrücklich nicht übernehmen. Berechtigte bestehende Admins kontrolliert zuordnen.
- Für Altaufgaben eine Bestandsgruppe anlegen. Fachliche Teamzuordnung anhand tatsächlicher Organisationsdaten durchführen, nicht aus Ersteller oder Rollenname erraten. Globalen Altzugriff nur dort vorübergehend erhalten, wo bewusst benötigt.
- Neue Entscheidung zunächst vergleichend protokollieren, Unterschiede prüfen. APIs, Downloads, Listen und UI gemeinsam umstellen; nach Umschaltung kein permissiver Fallback auf alte Rollen.
- Alte Sitzungen invalidieren und alte Rollenprüfung nach erfolgreicher Abnahme entfernen. Backup und Rollback vor destruktiver Schema-Bereinigung vorsehen.
Erweiterungsmöglichkeiten
| Reihenfolge | Erweiterung | Nutzen |
|---|---|---|
| 1 | Benutzer-/Gruppen-/Rollenverwaltung mit Anzeige effektiver Rechte | Nachvollziehbare Verwaltung einschließlich „Warum darf dieser Benutzer das?“ |
| 1 | Aktivitätenhistorie und Audit-Log | Änderungen an Aufgaben und Rechten nachvollziehen |
| 1 | Einladungen, Passwort-Reset, Kontodeaktivierung, optional OIDC/SSO + MFA | Vollständiger Benutzerlebenszyklus |
| 1 | Erinnerungen und Eskalationen bei Fälligkeit | Weniger liegenbleibende Aufgaben; Queue und Zustellstatus vorsehen |
| 2 | Teams, Standorte, Projekte und Team-Zuweisung | Aufgaben sinnvoll strukturieren; Teampool mit Übernahme durch Einzelperson |
| 2 | Prioritäten, Tags, gespeicherte Filter und Volltextsuche | Schneller Überblick bei wachsendem Bestand |
| 2 | Wiederkehrende Aufgaben und Vorlagen | Wiederkehrende Wartungs-/Prüfabläufe abbilden |
| 2 | Unteraufgaben, Checklisten und Abhängigkeiten | Größere Arbeiten planbar machen |
| 2 | Kanban und Stapelbearbeitung | Effektivere tägliche Arbeit |
| 2 | Archivierung, Wiederherstellung und konfigurierbare Aufbewahrung | Sicherere Alternative zum sofortigen Löschen |
| 3 | Berichte zu Durchlaufzeit, Rückstand und Auslastung | Transparenz für Teamleitungen; dieselben Datenrechte anwenden |
| 3 | CSV-/Excel-Import und Export, Kalenderabonnement | Datenaustausch mit Vorschau, Validierung und Zugriffsschutz |
| 3 | Webhooks und dokumentierte Integrations-API | Anbindung weiterer Systeme mit separaten, eingeschränkten Tokens |
| 3 | Mobile/PWA-Oberfläche | Einsatz vor Ort; Offline-Daten nur mit bewusstem Schutz- und Konfliktkonzept |
Empfohlene Umsetzungspakete
- Sicherheits- und Build-Basis: Framework/Abhängigkeiten aktualisieren, Lockfile/Typecheck/Lint/Build reparieren, Privilegieneskalation schließen, sichere Secrets/Bootstrap, Sitzungswiderruf und private Uploads.
- RBAC: Tabellen, zentrale Autorisierung, Team-Scope, Migrationsskript, Verwaltungsoberfläche und Sicherheits-Testmatrix. Zuerst dieses Fundament fertigstellen, bevor mehrere neue Fachmodule entstehen.
- Zuverlässigkeit und Performance: Pagination, leichte DTOs, Kalender-/Statistikendpunkte, Cleanup, Fehlerbehandlung, Konflikterkennung und weniger Polling.
- Fachliche Erweiterungen: zuerst Historie, Erinnerungen, Vorlagen und bessere Filter; anschließend nach tatsächlichem Bedarf.
Abnahmetests müssen insbesondere fremde Gruppen, entzogene Mitgliedschaften, gelöschte Benutzer mit altem Token, Selbstbeförderung, Passwort-Reset privilegierter Benutzer, Rechtevergabe über Gruppen, öffentliche Dateilinks, erledigte Aufgaben und konkurrierende Entfernung des letzten Admins abdecken. Positive Zugriffsfälle ebenfalls testen.
Prüfprotokoll
- Clone erfolgreich; Commit siehe oben.
- Normales
npm ci --ignore-scripts --no-audit --no-fund: fehlgeschlagen wegen inkonsistentem Lockfile (fehlendes preact 10.11.3). npm audit --json: 31 betroffene Pakete, davon 4 kritisch, 17 hoch, 6 mittel, 4 niedrig. Vollständige Rohdaten inaudit-review.json. Dies sind Paketmeldungen einschließlich transitiver und Entwicklungsabhängigkeiten, keine 31 nachgewiesenen Exploits. Insbesondere Auth.js-Meldungen müssen gegen den tatsächlich verwendeten Credentials-Flow geprüft werden.- Zusätzlicher Diagnoseversuch
npm ci --ignore-scripts --legacy-peer-deps --no-audit --no-fund: erfolgreich (597 Pakete). Das ist kein Ersatz für ein korrektes Lockfile; keine Lockfile-Reparatur vorgenommen. prisma generatemit lokaler Dummy-DATABASE_URL erfolgreich; verbindet sich dafür nicht mit einer produktiven Datenbank.npx --no-install tsc --noEmit --incremental false: fehlgeschlagen mit 14 Fehlern, Rohdaten intypecheck-review.txt. Bestätigt unter anderem vier Zod-Fehler, falsche Prisma-Seed-Konfiguration, zu eng inferierte Rollen-Arrays, fehlende Kalender-Typen, ungültigen next-themes-Typimport und einen nicht lokal importierten User-Typ.npm run lint: fehlgeschlagen, danext lintals ungültiges Projektverzeichnis behandelt wird.- Keine produktive DB, keine Migration/Seeds und keine Live-Sicherheitstests ausgeführt. Wegen der bestätigten Installations-/Typecheck-Blocker keinen vollständigen Produktionsbuild durchgeführt.