My-Weekly-ToDo-List/TODO.md
mARTin-B78 b4e45aca9c
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
security: weitere Dateien mit Zugangsdaten aus dem Git nehmen
Das Audit hatte nur src/ nach Passwoertern durchsucht -- zu eng. Betroffen
sind vier getrackte Dateien, nicht eine:

- INFRASTRUCTURE_REQUIREMENTS.md fuehrt das DB-Passwort unverschleiert als
  "**Password**: ..." auf, dazu SMTP und NEXTAUTH_SECRET
- deployment-notes.md enthaelt DATABASE_URL und NEXTAUTH_SECRET
- tests/debug/db-connection-test.spec.ts eine Connection-URL samt echter IP
- .env.production.save, der urspruengliche Fund

Die ersten beiden und .env.production.save sind aus dem Index genommen
(lokal bleiben sie), im Testskript ist das Passwort ersetzt. .gitignore
greift jetzt auf .env* statt auf feste Namen -- genau daran war
.env.production.save vorbeigerutscht.

Im Git liegen zwei verschiedene DB-Passwoerter: eines aus dem alten
Docker-Compose-Setup (@db:5432, vermutlich tot), eines aus dem
Supabase-Zugang. Ob letzteres noch aktiv ist, klaert der Pruefbefehl
in TODO.md Block F.

v1.117.2

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 23:32:38 +02:00

11 KiB

To-do — Repository-Audit vom 2026-09-06

Abarbeitungsliste aus dem Repository-Audit. Reihenfolge ist bewusst gewählt: schnelle Sicherheitsgewinne zuerst, das große Refactoring zuletzt.

Abhaken mit [x]. Die Nummern in Klammern entsprechen den Punkten aus dem Audit.


Block A — Schnell erledigt, sofortiger Gewinn

A1. Tote Mock-Login-Route entfernen (Audit 3)

  • src/app/api/auth/login/route.ts löschen
  • Prüfen, dass niemand sie aufruft (grep -rn "api/auth/login" src/)
  • Commit + Version bumpen

Warum: Altcode aus der Anfangszeit. Vergleicht gegen ein hartcodiertes Fake-Passwort ($2b$10$examplehashedpassword), erzeugt ein bedeutungsloses mock-jwt-token-… und setzt es als Cookie. Weil die Middleware /api/auth/* bewusst durchlässt, ist die Route ohne Login von außen erreichbar und schreibt jede probierte E-Mail per console.log ins Log. Kein Login-Bypass (der Vergleich schlägt immer fehl), aber unnötige Angriffsfläche.

A2. npm test reparieren (Audit 6)

  • Entscheiden: Jest raus oder Jest einrichten
  • package.json: "test" auf das zeigen lassen, was wirklich existiert (Playwright)
  • "test:e2e" für Playwright ergänzen
  • Debug-Skripte in tests/ aussortieren (siehe unten)

Warum: "test": "jest" — aber es gibt keine Jest-Config und keinen einzigen Jest-Test. Die 15 Dateien in tests/ sind Playwright-Specs, und die Namen verraten den Charakter: login-debug.spec.ts, css-debug-test.spec.ts, login-simple-debug.spec.ts. Wegwerf-Skripte, keine Regressionstests. npm test läuft ins Leere.

Aufräumen: Die reinen Debug-Skripte löschen, die brauchbaren behalten und benennen.

A3. dev-Branch auflösen (Audit 5)

  • Die vier Maßnahmen aus f6c4a21 frisch auf main anwenden (siehe A1, B1, B2)
  • dev auf main zurücksetzen oder löschen
  • CLAUDE.md: Branch-Strategie an die gelebte Praxis anpassen

Warum: Commit f6c4a21 vom 04.07.2026 behebt bereits Rate-Limiting, Token-Hashing, die Mock-Route und die Secret-Datei — wurde aber nie gemerged. dev fehlen inzwischen 70 Commits von main, ein Merge würde alte Dateistände zurückholen. Deshalb: Commit als Vorlage nehmen, Änderungen neu anwenden, dev danach entsorgen.

CLAUDE.md beschreibt einen dev → main-Workflow, der faktisch nicht gelebt wird (alles läuft direkt auf main). Doku an die Realität anpassen ist ehrlicher.


Block B — Sicherheit

B1. Rate-Limiting auf den Auth-Endpunkten (Audit 4)

  • Sliding-Window-Limiter in src/lib/rate-limit.ts anlegen
  • Einbinden in signup
  • Einbinden in resend-verification
  • Einbinden in reset-password
  • Einbinden in verify-email
  • Limits dokumentieren (Vorschlag: 5 Versuche / 15 Minuten je IP)

Warum: Im gesamten src/ ist kein Limiter vorhanden. Signup, Passwort-Reset und Verification-Mails sind unbegrenzt aufrufbar — Einladung zum Missbrauch deines SMTP-Zugangs.

B2. Passwort-Reset-Token nur als SHA-256-Hash speichern (Audit 4)

  • Beim Erzeugen: Klartext per Mail, Hash in die DB
  • Beim Einlösen: eingehenden Token hashen, dann vergleichen
  • Migration für bestehende Tokens (einfachster Weg: alle invalidieren)

Warum: src/app/api/auth/reset-password/route.ts:28 legt passwordResetToken im Klartext ab. Wer Lesezugriff auf die Datenbank hat, kann fremde Konten übernehmen. Der Token selbst kommt aus crypto.randomUUID() — das ist in Ordnung, nur die Ablage nicht.

B3. Secrets aus dem Git entfernen und rotieren (Audit 2)

  • .env.production.save aus dem Git-Index entfernt (Datei bleibt lokal)
  • .gitignore auf .env* erweitert (Ausnahme .env.example)
  • NEXTAUTH_SECRET neu erzeugt — 44 Zeichen, geprüft
  • SMTP_PASSWORD neu gesetzt
  • deployment-notes.md und INFRASTRUCTURE_REQUIREMENTS.md aus dem Index entfernt
  • Passwort aus tests/debug/db-connection-test.spec.ts entfernt
  • Nach dem Wechsel neu eingeloggt
  • Entscheiden: Historie umschreiben oder belassen (Empfehlung: belassen)
  • Prüfen, ob eines der geleakten DB-Passwörter noch aktiv ist (siehe F1)

Warum: .env.production.save ist eingecheckt und enthält echte Werte — DATABASE_URL (70 Zeichen), NEXTAUTH_SECRET (20 Zeichen), SMTP_PASSWORD (20 Zeichen). .gitignore listet .env.production, die .save-Endung fällt durchs Raster. Drin seit Commit da8d019.

Entwarnung: Das GitHub-Repo ist privat — nicht öffentlich abgreifbar. Die Werte stehen aber in der kompletten Historie, in jedem Klon und auf Gitea.

Anleitung siehe docs/secret-rotation.md.


Block C — Build und Typsicherheit

C1. Build darf Fehler nicht mehr verschlucken (Audit 1)

  • Schritt 1: eslint.ignoreDuringBuilds in next.config.js auf false
  • Gemeldete ESLint-Fehler abarbeiten
  • Schritt 2: npm run type-check laufen lassen, Fehlerzahl notieren
  • Fehler abarbeiten — modulweise, nicht auf einmal
  • Schritt 3: typescript.ignoreBuildErrors auf false
  • any-Stellen reduzieren (aktuell 452) — fortlaufend, kein Blocker

Warum: next.config.js hat ignoreDuringBuilds: true und ignoreBuildErrors: true. tsconfig.json sagt zwar strict: true, das ist aber wirkungslos, weil der Build die Fehler gar nicht meldet. Ein Typfehler fällt nicht beim Bauen auf, sondern erst als kaputte Seite im Browser. Ein erfolgreicher Build ist derzeit kein Beweis, dass der Code korrekt ist.

Achtung Reihenfolge: Erst ESLint, dann TypeScript. Beides gleichzeitig abzuschalten blockiert jeden Deploy, bis alles behoben ist.


Block D — Struktur

D1. Dateien über 4000 Zeilen aufteilen (Audit 7)

Betroffen sind genau zwei Dateien:

Datei Zeilen
src/components/WeeklyView.tsx 11.906
src/components/SettingsSidebar.tsx 5.445

Voraussetzung: C1 muss laufen — ohne Typecheck ist ein Refactoring dieser Größe Blindflug. Ebenso hilfreich: A2, damit es überhaupt Tests gibt.

WeeklyView.tsx → Zielstruktur

  • src/components/weekly/ anlegen
  • Reine Helfer nach src/lib/weekly/ (Datum, Slots, Formatierung)
  • Drag & Drop in einen Hook useTaskDragDrop.ts
  • Someday-Listen in SomedayLists.tsx
  • All-Day-Leiste in AllDayBar.tsx
  • Zeitraster + Tagesspalten in TimeGrid.tsx / DayColumn.tsx
  • Einstellungs-Flyouts in QuickSettingsPanel.tsx
  • Daten-Laden in useWeeklyData.ts
  • WeeklyView.tsx bleibt als Orchestrator übrig

SettingsSidebar.tsx → Zielstruktur

  • src/components/settings/ anlegen
  • Ein Panel pro Themenbereich als eigene Datei
  • Gemeinsame Bausteine (Farbwähler, Schalterzeile) in settings/controls/

Vorgehen: In kleinen Schritten, jeder Schritt ein eigener Commit, nach jedem Schritt Typecheck. Kein "großer Wurf" — die Datei ist zu zentral.

Warum: WeeklyView.tsx ist ein Viertel des gesamten Quellcodes. Der Weekday-Bug von Anfang September saß genau dort und war nur deshalb schwer zu finden.


Block E — Dauerhafte Absicherung

E1. Regelmäßige automatische Prüfung (Audit 8)

  • SonarQube-Analyse gegen https://sq.martin-bierschenk.de einrichten
  • Regelmäßigen Lauf aufsetzen — nightly 03:00, todo-sonar.timer (systemd user unit)
  • npm audit in denselben Lauf aufnehmen (scripts/quality-check.sh)
  • todo-sonar.timer auf scripts/quality-check.sh umstellen statt nur todo-sonar-scan
  • Playwright-Tests in den nächtlichen Lauf aufnehmen (braucht laufende App — erst nach A2)
  • Quality Gate im SonarQube definieren
  • Ergebnis irgendwohin melden, wo es auffällt (bisher nur Konsolenausgabe)
  • Entscheiden: .github/workflows/sonarqube.yml löschen oder behalten

Stand: Die Analyse läuft bereits — nächtlich um 03:00 auf dem Spark, per systemd-Timer, Ergebnis auf https://sq.martin-bierschenk.de. Was fehlte, war npm audit (Sicherheitslücken in Abhängigkeiten findet SonarQube nicht) und ein Bündel-Skript. Beides ist jetzt da.

Zur Entscheidung: GitHub Actions wurde am 02.09. bewusst verworfen — das Repo ist privat, Actions-Minuten kosten, und der SonarQube-Server läuft ohnehin selbst gehostet. Trotzdem liegt seit dem 03.09. ein Workflow im Repo, der bei jedem Push auf main anspringt. Er ruft npm run type-check und npm run lint auf — beides schlägt derzeit fehl (siehe C1), der Workflow wäre also dauerhaft rot. Sein Projekt-Key war zudem falsch und hätte in ein zweites, leeres SonarQube-Projekt geschrieben; das ist korrigiert. Entweder löschen (passt zur Entscheidung vom 02.09.) oder bewusst behalten und C1 vorziehen.

Warum: Bisher fallen Regressionen erst in Produktion auf. In Kombination mit C1 (Build meldet Fehler) und A2 (Tests laufen) entsteht daraus ein echtes Netz.

E2. Abhängigkeiten auf Sicherheitslücken prüfen

  • npm audit auf dem Container ausführen
  • Kritische Funde beheben

Warum: Konnte im Audit nicht geprüft werden — node_modules ist auf dem CIFS-Share nicht installierbar (keine Symlinks). Zu bekannten Lücken in den Abhängigkeiten liegt daher keine Aussage vor. Muss nachgeholt werden.


Block F — Zurückgestellt

F1. Datenbank-Passwort rotieren (bewusst nach hinten geschoben)

  • Prüfen, ob eines der geleakten Passwörter noch aktiv ist
  • Falls ja: rotieren nach docs/secret-rotation.md, Schritt 2
  • Falls nein: nichts zu tun, Haken dran

Warum zurückgestellt: Von den drei Zugangsdaten ist dieses das am wenigsten dringende. Die Datenbank hört auf einer privaten LAN-Adresse, nicht am Internet. Wer das Passwort aus dem Git holen will, braucht Zugriff auf das private Repository — und ist damit ohnehin schon im Netz. NEXTAUTH_SECRET und SMTP_PASSWORD waren die kritischen, beide sind erledigt.

Und es ist riskant: Supabase läuft selbst gehostet per Docker. Dasselbe Passwort steckt in supabase/docker/.env und in Postgres. Ein halb durchgeführter Wechsel legt die Datenbank und damit die App lahm. Das gehört an einen ruhigen Abend, nicht nebenbei.

Zwei verschiedene Passwörter liegen im Git (Fingerabdrücke, keine Klartexte):

Fingerabdruck Wo Vermutung
59fb583eaae9 deployment-notes.md, INFRASTRUCTURE_REQUIREMENTS.md altes Docker-Compose-Setup (@db:5432), vermutlich tot
9dbb40b14c4d .env.production.save Supabase-Zugang, möglicherweise noch aktiv

Prüfen lässt sich das auf dem Container, ohne einen Wert auszugeben:

cd /root/My-Weekly-ToDo-List
grep '^DATABASE_URL=' .env | sed -E 's|.*://[^:]+:([^@]+)@.*|\1|' | tr -d '\n' | sha256sum | cut -c1-12

Ergibt der Befehl 9dbb40b14c4d, ist das geleakte Passwort noch in Benutzung — dann lohnt F1. Kommt etwas anderes heraus, wurde es längst getauscht und du kannst F1 abhaken.


Kleinkram (ohne Eile)

  • 114 console.log aus dem Produktionscode entfernen (die 275 console.error sind in Ordnung)
  • NEXTAUTH_SECRET auf 32 Byte verlängern (erledigt sich mit B3)
  • API-Routen: JSON-401 statt HTML-Redirect für nicht angemeldete Aufrufe
  • deploy.sh und docker-compose.yml löschen oder als veraltet markieren — sie beschreiben ein Portainer-Setup, das nicht mehr verwendet wird
  • Eigener Auth-Check in apple/sync und weather/geocode (aktuell nur durch die Middleware geschützt — zusätzliche Absicherung schadet nicht)