Commit Graph

413 Commits

Author SHA1 Message Date
8f017cb879 fix: Deploy-Skript darf Daten nicht mehr automatisch loeschen, Fehlermeldungen haerten
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Erste drei Punkte aus dem TODO-Block L (Sicherheitsdurchgang vom 12.09.):

- scripts/update-app.sh: kein automatischer "prisma db push --accept-data-loss"-
  Fallback mehr, wenn "migrate deploy" fehlschlaegt. Das lief am 11.09. beim
  Boot-Lauf tatsaechlich unbeaufsichtigt durch. Ein fehlgeschlagenes Migrate
  bricht das Deployment jetzt sauber ab, exakt wie ein fehlgeschlagener Build.
- 14 API-Routen gaben error.message direkt an den Client zurueck (Kalender-
  Connect/-Sync, Task-Import/-Sync, Someday-Listen, Datenimport). Neuer Helper
  src/lib/api-error.ts (safeErrorMessage): generische Meldung in Produktion,
  echte Meldung nur noch lokal. Logging unveraendert in console.error.
- src/lib/email.ts: tls.rejectUnauthorized: false entfernt -- stand seit dem
  allerersten Commit unbegruendet drin, produktiver SMTP-Host (Kasserver) hat
  ein gueltiges Zertifikat.

Verifiziert: Typecheck, Lint, 79 Unit-Tests, Produktions-Build alle gruen.

v1.123.2

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 15:36:00 +02:00
e62294a204 fix: Standalone-Output-Wurzel fest verankern -- Smoke-Test scheiterte nach next@15
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Der erste Deploy nach dem next@15-Upgrade (v1.123.0) brach am Smoke-Test ab:
Next.js hatte den Standalone-Output um einen Ordner tiefer verschachtelt als
scripts/update-app.sh erwartet, weil es per Lockfile-Suche nach oben eine
verwaiste, leere package-lock.json in /root auf dem Produktionshost fand und
/root faelschlich fuer die Projektwurzel hielt.

outputFileTracingRoot: __dirname in next.config.js verankert die Wurzel jetzt
explizit. Die laufende App war nie betroffen -- der Smoke-Test hat den Build
wie vorgesehen abgefangen, bevor umgeschaltet wurde.

Verifiziert lokal mit denselben Env-Variablen wie scripts/update-app.sh
(NEXT_DIST_DIR=.next-build): .next-build/standalone/server.js liegt jetzt an
der erwarteten Stelle. Typecheck, Lint, 79 Unit-Tests weiterhin gruen.

v1.123.1

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 14:56:37 +02:00
114131f9e4 fix: next/next-auth/nodemailer/postcss auf gepatchte Versionen heben
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Letzter offener Punkt aus dem Sicherheitsdurchgang vor dem Beta-Test: npm audit
meldete 24 Schwachstellen, davon mehrere kritisch in next und next-auth.

- next 14.2.35 -> 15.5.24 (patcht alles, was next@16 sonst erfordert haette --
  ein Major-Sprung statt zwei; next 15 unterstuetzt weiterhin React 18)
- next-auth 4.24.13 -> 4.24.15, @auth/core per overrides auf 0.41.3 erzwungen
  (next-auth pinnt es sonst exakt auf die verwundbare 0.34.3, als ungenutzten
  optionalen Peer)
- nodemailer 7 -> 10 per overrides (next-auth haelt einen ungenutzten optionalen
  Peer auf 7.x)
- postcss auf 8.5.28, auch next's eigene interne Kopie per overrides
- ungenutztes @auth/prisma-adapter entfernt (Projekt nutzt @next-auth/prisma-adapter)

npm audit: 24 -> 0.

Zwei echte Codeaenderungen dafuer noetig:
- Next.js 15: { params } in Routen-Handlern ist jetzt ein Promise. Einzige
  betroffene Route: cross-sync/rules/[id].
- nodemailer.Transporter gibt es seit @types/nodemailer 8 nicht mehr als
  Namespace-Property, nur noch als benannter Type-Export. Einzige Stelle:
  src/lib/email.ts.

Ausserdem google-auth-library als direkte Abhaengigkeit deklariert (vorher nur
ueber googleapis transitiv gehofft) und per overrides auf eine Version gepinnt --
der frische package-lock.json aus den obigen Fixes hob sie sonst nicht mehr
passend, wodurch zwei inkompatible Kopien nebeneinander existierten und der
Typecheck brach.

Verifiziert: Typecheck, Lint, 79 Unit-Tests, Produktions-Build alle gruen.
Login-Seite, Sicherheitsheader und Auth-Middleware manuell im gebauten
Standalone-Server geprueft. Kein Playwright-E2E-Lauf (braucht echte DB/OAuth).

v1.123.0

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 14:41:52 +02:00
3742ae52c6 fix: Login-Rate-Limit, Sicherheitsheader und Deploy-Skript-PATH nachziehen
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Sicherheitsdurchgang vor dem geplanten Beta-Test mit Security-Scannern:

- Login (authorize() in src/lib/auth.ts) hatte als einziger Auth-Endpunkt kein
  Rate-Limit, obwohl signup/reset-password/verify-email/resend-verification es
  bereits nutzen. Jetzt max. 8 Versuche pro E-Mail in 15 Minuten.
- Fehlende Standardheader ergaenzt (X-Content-Type-Options, X-Frame-Options,
  Referrer-Policy, Permissions-Policy), X-Powered-By abgeschaltet. Bewusst
  ohne CSP -- braucht eine eigene, getestete Whitelist fuer OAuth/Fonts/CDN.
- npm audit fix (ohne --force): 24 -> 10 gemeldete Schwachstellen, keine
  Breaking Changes. Die verbleibenden 10 haengen an next@14 und next-auth@4
  (siehe CHANGELOG "Known issues") und brauchen ein eigenes Major-Upgrade.

Ausserdem zwei Betriebsfixes, die beim heutigen Deploy live auffielen:

- scripts/update-app.sh setzt jetzt selbst PATH=/usr/local/bin:$PATH. Ohne
  Login-Shell fand es pm2 nicht und brach nach erfolgreichem Build beim
  Neustart ab -- die Instanz blieb dabei auf dem alten Stand, kein Datenverlust,
  aber ein unnoetiger manueller Eingriff.
- tsconfig.json nimmt .next-build/types/**/*.ts mit auf; Next.js traegt das
  beim Bauen mit NEXT_DIST_DIR=.next-build sonst als nie eingecheckte
  Abweichung auf dem Produktionshost ein.

v1.122.0

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 10:30:12 +02:00
bc41ef340d docs: Changelog für v1.121.0-v1.121.2 nachtragen
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
v1.121.3

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 09:34:32 +02:00
85667b68c1 refactor: Spaltenaufteilung ueberlappender Termine aus WeeklyView herausloesen
Erster kleiner Schnitt aus Phase A des CodeScene-Auftrags: die Ueberlappungs-
Berechnung war ein rein funktionaler, aber verschachtelter Block mitten in der
Komponente. Sie liegt jetzt als layoutDaySegments/computeEventOverlapLayout in
src/lib/weekly/event-layout.ts und ist mit node:test abgedeckt (einzelner
Termin, Ueberschneidung, direkte Abfolge, drei gleichzeitige Termine,
Reihenfolgeunabhaengigkeit).

Kein sichtbares Verhalten geaendert; der Algorithmus ist unveraendert
uebernommen. WeeklyView.tsx: 9683 -> 9642 Zeilen.

v1.121.2

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 09:30:29 +02:00
00010059a2 fix: Apple-Sync-Route absichern und Passwort-Logging entfernen
Zwei Befunde aus dem Sicherheitsdurchgang zum CodeScene-Auftrag:

- /api/calendar/apple/sync war ohne Anmeldung erreichbar und hat beliebige
  Apple-Zugangsdaten aus dem Request gegen Apple CalDAV geschickt. Damit liess
  sich die Instanz als Relay zum Durchprobieren fremder Zugangsdaten nutzen.
  Die Route verlangt jetzt dieselbe Session-Pruefung wie /connect.
- AuthForm.tsx hat E-Mail und Passwort im Klartext in die Browser-Konsole
  geschrieben. Die Debug-Ausgaben sind entfernt.

Keine Aenderung an Payloads oder Antwortformaten.

v1.121.1

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 09:27:35 +02:00
d52e780967 feat: Termine ueber Mitternacht am Tageswechsel teilen
Ein Termin von 22:00 bis 02:00 wurde bisher als ein ueberlanger Block in den
Starttag gezeichnet und hat die Tagesspalte verlaengert. Jetzt wird er an der
Tagesgrenze geteilt: 22:00-24:00 am Starttag, 00:00-02:00 am Folgetag -- so,
wie es Kalender-Apps zeigen.

Die Regel liegt als reine Funktion splitEventByDay in src/lib/weekly/date-utils.ts
und ist mit node:test abgedeckt (Teilung, Mehrtagestermine, Ende exakt um
Mitternacht, Ganztagstermine, ungueltige Zeiten). Die Wochenansicht arbeitet in
Raster und Liste nur noch mit diesen Tagesabschnitten; Klick, Drag und Resize
greifen weiterhin auf den ungeteilten Termin zu, damit Payloads unveraendert
bleiben. Die Slot-Sperre (protectEventTimes) erfasst dadurch auch die
Nachtstunden des Folgetags.

v1.121.0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 09:25:12 +02:00
dcbcb77dba fix: Build-Erkennung an den gebauten Commit koppeln, Smoke-Server sauber beenden
Some checks failed
Playwright Tests / test (push) Has been cancelled
Test and SonarQube / quality (push) Has been cancelled
Zwei Fehler im neuen Deploy-Weg, beide bei einem Testlauf gefunden.

1. Das Skript uebersprang den Build, wenn vorher von Hand git pull lief.
   Die Entscheidung haengte an HEAD vs. origin/main -- nach einem manuellen
   Pull sind beide gleich, also "Nothing to do", obwohl der vorhandene Build
   aus einem aelteren Commit stammte. Genau das ist beim Deploy von v1.120.0
   passiert: gepullt wurde, gebaut nicht, ausgeliefert blieb 1.119.4.
   Massgeblich ist jetzt .next/BUILD_COMMIT.

   Mein Rat, vor dem Skript git pull auszufuehren, hat den Fall ueberhaupt
   erst ausgeloest -- das Skript pullt selbst.

2. Der Smoke-Test-Server ueberlebte das Beenden. ( ... ) & startet eine
   Subshell, $! ist deren PID; node lief als Waise weiter und hielt Port
   3999 belegt. Jeder weitere Deploy waere daran gescheitert. exec ersetzt
   die Subshell, kill greift, kill -9 fasst nach, der ERR-Trap raeumt
   ebenfalls auf, und vorab wird geprueft ob der Port frei ist.

Beide Szenarien getestet: alter Build wird erkannt und neu gebaut,
gleicher Stand wird uebersprungen, Port bleibt frei.

v1.120.1

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 22:41:26 +02:00
162c56d0d3 feat: fehlgeschlagener Build reisst die laufende App nicht mehr mit
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
next build lief direkt auf .next -- also auf dem Verzeichnis, aus dem die
laufende Instanz bedient wird. Brach der Build ab, fand PM2 server.js nicht
mehr (MODULE_NOT_FOUND) und geriet in eine Neustartschleife mit ueber 790
Versuchen. Am 07.09. war die Seite dadurch rund eine Stunde unbrauchbar.

Neuer Ablauf:
1. Build nach .next-build, .next bleibt unangetastet
2. statische Dateien und .env in den neuen Baum
3. Smoke-Test: der neue Build wird auf Port 3999 gestartet und muss auf
   /auth/login antworten -- ein Build kann durchlaufen und trotzdem nicht
   starten
4. erst danach umschalten, alter Stand bleibt als .next-previous liegen
5. PM2 neu starten

Scheitert etwas davon, raeumt der ERR-Trap .next-build weg und die laufende
App bleibt unveraendert. Die Meldung "die laufende App bleibt unberuehrt"
stimmt damit endlich -- vorher war sie schlicht falsch.

Geprueft wurde vorher, dass der umbenannte Build ueberhaupt startet: der
standalone-Ausgabebaum traegt den distDir-Namen intern, server.js findet
seine Dateien aber relativ zu sich selbst. Testweise gestartet, Login-Seite
und JS-Dateien lieferten 200.

Beide Faelle durchgespielt: Abbruch liess .next samt Markierung unberuehrt
und raeumte .next-build weg; Erfolg schaltete um, legte .next-previous an
und bestand den Smoke-Test.

v1.120.0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 22:33:04 +02:00
bea9723a6f fix: Heap-Limit fuer den Build auf 4 GB -- 2 GB waren zu knapp
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Der Wert 2048 aus v1.119.3 stammte aus der Zeit, als der Container 3 GB
hatte. Er war zu niedrig gewaehlt: Der Build starb punktgenau bei 2045 MB,
also an meiner eigenen Grenze. Gemessener Bedarf sind rund 2,6 GB, deshalb
jetzt 4096. Der Container hat inzwischen 6 GB und damit genug Luft.

v1.119.4

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 21:36:50 +02:00
0628ec58ba fix: Build-Speicher auf dem Container -- NODE_OPTIONS statt Rateschluss
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Der Deploy starb mit "Ineffective mark-compacts near heap limit". Nodes
Standard-Heap richtet sich nach dem Arbeitsspeicher und liegt auf dem
Container bei rund 1,5 GB -- zu wenig fuer next build. update-app.sh setzt
jetzt --max-old-space-size=2048.

Ich hatte zuerst ESLint im Build verdaechtigt (mein ignoreDuringBuilds:
false aus v1.117.4) und die Aenderung zurueckgenommen. Eine Messung
widerlegte das: Spitzenspeicher mit ESLint 2.590 MB, ohne 2.595 MB -- kein
Unterschied. Die Ruecknahme ist damit hinfaellig, ESLint bleibt im Build.

Der Build braucht rund 2,6 GB. Bei 3 GB Container-RAM bleibt das knapp;
NODE_OPTIONS ist die Sofortmassnahme, mehr RAM fuer LXC 202 die eigentliche
Loesung. Steht als Block J in TODO.md, zusammen mit der Alternative, den
Build auf den Spark zu verlagern.

v1.119.3

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 19:06:41 +02:00
e8198190fd refactor: restliche fuenf Fremdkomponenten aus WeeklyView.tsx herausloesen
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
TaskInput, SomedayAddTask, TaskItem (ueber 900 Zeilen), ListVisualsPopover
und TabVisualsPopover liegen jetzt unter src/components/weekly/. Dazu die
Prioritaets-Abzeichen: GridTaskBlock importierte getPriorityBadge aus
WeeklyView.tsx und zog sich damit die gesamte Wochenansicht in seinen
Abhaengigkeitsgraphen.

WeeklyView.tsx: 11.148 -> 9.711 Zeilen, erstmals unter 10.000. Gegenueber
dem Stand vor dem Audit (11.906) sind das 2.195 Zeilen oder 18 Prozent.

Der Typecheck hat den Schnitt in mehreren 19-Sekunden-Runden gefuehrt und
dabei zwei Dinge gefunden, die sonst erst im Browser aufgeschlagen waeren:
ein doppeltes export-Schluesselwort und -- feiner -- dass DragEvent in
WeeklyView aus React stammt, in den neuen Dateien ohne Import aber das
globale DOM-DragEvent gewesen waere.

Verifiziert: Typecheck 0 Fehler, npm run build Exit 0, 63 Unit-Tests gruen.

v1.119.2

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 18:55:54 +02:00
7db4dfbf47 refactor: ProjectIcon, ProjectsSidebar und NotesSidebar in eigene Dateien
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Beim Vermessen der Struktur zeigte sich: In WeeklyView.tsx stecken acht
eigenstaendige Komponenten mit zusammen rund 1.870 Zeilen, die gar nichts
mit der Wochenansicht zu tun haben. Sie haben bereits eigene Props -- der
Schnitt braucht also kein Props-Design, nur die richtigen Importe.

Drei davon sind jetzt heraus, unter src/components/weekly/. Die Symbolliste
projectIconsGlobal ist zu ProjectIcon gewandert, wo sie als einzige
gebraucht wird.

11.556 -> 11.148 Zeilen.

Der scharfe Typecheck aus v1.118.1 hat sich hier zum ersten Mal richtig
ausgezahlt: Er nannte in 19 Sekunden praezise jeden fehlenden Import, in
mehreren schnellen Runden. Vor C1 haette der Build all das stumm
durchgewunken -- und die Fehler waeren erst im Browser aufgeschlagen.

Verifiziert: Typecheck 0 Fehler, npm run build Exit 0, 63 Unit-Tests gruen.

v1.119.1

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 14:26:08 +02:00
6fe4b69514 feat: Heute-Hervorhebung im Spaltenkopf, Termin-Symbole nach oben rechts
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Zwei UI-Wuensche aus der Wochenansicht (TODO.md Block I).

Der Spaltenkopf ist position: sticky und deckte mit --weekly-bg ab -- die
Hervorhebung des heutigen Tages begann daher erst unterhalb von Wochentag
und Datum. Jetzt faerbt sich der Kopf mit.

Die Symbole sitzen statt unten rechts oben rechts. Damit Titel und Uhrzeit
nicht darunter laufen, bekommen sie rechts Freiraum -- ueber
:has(.event-icons-row) nur dort, wo ueberhaupt Symbole erscheinen. Fuer
beide Darstellungen umgesetzt: Zeitraster und Liste.

Verifiziert: npm run build Exit 0. Das Ergebnis ist rein visuell und daher
nur im Browser wirklich pruefbar.

v1.119.0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 14:08:23 +02:00
53de4017e5 fix: @ts-nocheck aus allen drei Dateien entfernen
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Die Dateien schalteten die Typpruefung komplett ab und blieben deshalb auch
von ignoreBuildErrors: false unberuehrt -- eine Luecke im gerade erst
geschlossenen Netz.

- calendar-cache.ts brauchte die Ausnahme gar nicht: ohne sie null Fehler.
- microsoft-todo.ts hatte vier Faelle zirkulaerer Typinferenz
  (url -> data -> response -> url), aufgeloest durch explizite Annotationen.
- outlook-calendar.ts verbarg einen moeglichen Laufzeitfehler: Der Code
  streute response!-Assertions, eine Stelle war vergessen. Statt noch einer
  Assertion prueft er jetzt echt, ob nach drei Wiederholversuchen ueberhaupt
  eine Antwort vorliegt.

Ausserdem Block I in TODO.md: Hervorhebung des aktuellen Tages im
Spaltenkopf und die Symbole in Kalenderterminen nach oben rechts, beide mit
Fundstelle in globals.css.

Verifiziert: Typecheck 0 Fehler, npm run build Exit 0.

v1.118.2

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 13:59:57 +02:00
db99b486c7 fix: Build prueft wieder Typen -- 7 Fehler behoben, Notion-Anbindung war defekt
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
typescript.ignoreBuildErrors steht jetzt auf false. Ein erfolgreicher Build
ist damit wieder ein Beleg dafuer, dass der Code uebersetzbar ist.

Die Ursache der 30-Minuten-Laufzeit war nicht die Groesse von WeeklyView.tsx,
wie ich vermutet hatte, sondern das include-Muster **/* in tsconfig.json. Auf
src/**/* eingegrenzt laeuft der volle Typecheck in 19 Sekunden.

Die sieben gefundenen Fehler:

- notion-calendar.ts rief notion.databases.query() auf. Die Methode gibt es
  in @notionhq/client v5 nicht mehr -- die Notion-Anbindung war zur Laufzeit
  schlicht kaputt und niemandem aufgefallen. Migriert auf dataSources.query(),
  aber mangels Notion-Zugang ungetestet. Gespeicherte Verbindungen enthalten
  alte database_ids und muessen neu eingerichtet werden.
- WeeklyView.tsx importierte isAllDayEvent noch aus format statt date-utils
  -- mein eigener Fehler aus v1.118.0, der ohne scharfen Typecheck
  durchgerutscht war.
- Export-Helfer lagen in einer route.ts, wo Next.js nur Route-Handler
  erlaubt; SettingsSidebar importierte sie von dort und zog einen
  Server-Handler in den Client-Graphen. Jetzt in src/lib/export-fields.ts.
- push-notifications.ts: BufferSource-Cast fuer applicationServerKey.
- web-push hat keine Typen; lokale Deklaration statt neuer Abhaengigkeit.

Verifiziert: npm run build Exit 0 mit scharfem Typecheck, 63 Unit-Tests gruen.

v1.118.1

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 09:45:03 +02:00
5c5f2a284e feat: 63 Unit-Tests fuer die ausgelagerten Funktionen
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Nodes eingebauter Test-Runner mit --experimental-strip-types: keine neue
Abhaengigkeit, keine Browser, keine Datenbank, Laufzeit rund 170 ms.
npm test fuehrt sie aus, npm run test:e2e startet weiterhin Playwright.

Die Tests haben sofort zwei echte Fehler gefunden, die ich beim Auslagern
in v1.117.7 selbst eingebaut hatte:

- isAllDayEvent rief parseCalendarDate ohne Import auf
- resolveViewDays nutzte clampViewDays ohne Import

Beides haette zur Laufzeit einen ReferenceError gegeben. Der Build meldete
nichts, weil typescript.ignoreBuildErrors noch aktiv ist -- genau der Fall,
gegen den C1 laeuft. isAllDayEvent liegt jetzt in date-utils.ts, wo es
thematisch hingehoert; clampViewDays und MAX_VIEW_DAYS in
device-settings.ts, DaysSelector re-exportiert sie.

Geprueft werden ISO-Kalenderwochen gegen bekannte Kalenderdaten, die
Wochenstart-Berechnung inklusive Sonntag-Sonderfall, das Zeitraster, die
12/24-Stunden-Anzeige und der Round-Trip formatDateToISO <-> parseCalendarDate
-- die Bruecke zwischen Datenbank und Anzeige, aus der Ein-Tag-Verschiebungen
entstehen.

Mit npm run build verifiziert (Exit 0).

v1.118.0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 09:19:41 +02:00
cd59c02995 refactor: Geraeteeinstellungen und Formatierungs-Helfer auslagern
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Dritter Schnitt an WeeklyView.tsx (D1):
- src/lib/weekly/device-settings.ts: Cookie-Helfer plus die vier
  Schluessellisten, die bewusst nur im Cookie und nicht in der Datenbank
  gehalten werden
- src/lib/weekly/format.ts: stripHtml, invertColor, isAllDayEvent,
  getSomedaySlotCount

11.655 -> 11.556 Zeilen. Mit npm run build verifiziert (Exit 0).

Damit sind die reinen Funktionen ohne Komponenten-State heraus, insgesamt
11.906 -> 11.556 (rund 3 %). Der Rest ist die Komponente selbst: JSX und
Handler auf gemeinsamem State. Jeder weitere Schnitt braucht echtes
Props-Design statt Verschieben.

v1.117.7

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 09:11:31 +02:00
c303e1cf2b refactor: Datums- und Zeitraster-Helfer nach src/lib/weekly/date-utils.ts
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Zweiter Schnitt an WeeklyView.tsx (D1). 13 reine Funktionen ohne
Komponenten-State: getStartOfWeek, getDayName, getTimeSlots, formatHour,
getWeekNumber, formatCustomHeader und weitere.

11.830 -> 11.655 Zeilen. Mit npm run build verifiziert (Exit 0).

Nebenbefund: getWeekNumber existiert im Projekt dreimal -- hier, in
WeekPrintModal.tsx und in api/user/export-week-view/route.ts. Das Ersetzen
der Duplikate steht in TODO.md; vorher gehoeren die drei Implementierungen
auf Gleichheit geprueft.

v1.117.6

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 09:09:26 +02:00
97cb306853 refactor: Datentypen der Wochenansicht in src/lib/weekly/types.ts
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Erster Schritt der Aufteilung von WeeklyView.tsx (D1). Die sieben gemeinsamen
Typen lagen in der Komponentendatei; SettingsSidebar und GridTaskBlock
importierten sie von dort und zogen sich damit die gesamte
11.900-Zeilen-Komponente in ihren Abhaengigkeitsgraphen.

WeeklyView.tsx re-exportiert die Typen weiterhin, bestehende Importe bleiben
also unveraendert -- kein Anfassen der beiden Importeure noetig.

11.906 -> 11.830 Zeilen. Mit npm run build verifiziert: Exit 0, 36 Seiten
generiert, /tasks unveraendert bei 265 kB.

v1.117.5

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 09:05:31 +02:00
4a9b276d3c fix: Build meldet wieder ESLint-Fehler
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
eslint.ignoreDuringBuilds stand auf true, der Build verschluckte also jede
Lint-Meldung. Im gesamten Projekt gab es genau zwei echte Errors -- beide
"let json" statt "const json" in SettingsSidebar.tsx. Behoben, Schalter aus,
next lint endet mit Exit 0.

Die 695 Warnungen (470 no-explicit-any, 209 ungenutzte Variablen, 11
unvollstaendige Hook-Abhaengigkeiten) blockieren den Build nicht. Die
Hook-Warnungen sind davon die interessantesten, weil daraus echte Bugs
entstehen -- stehen als eigener Punkt in TODO.md.

Naechster Schritt ist typescript.ignoreBuildErrors; der volle tsc-Lauf
dauert wegen WeeklyView.tsx ueber 15 Minuten und laeuft noch.

v1.117.4

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 08:57:20 +02:00
391134f36d security: Zugangsdaten aus dem Arbeitsverzeichnis entfernen
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
.env.production.save und .env.local geloescht (per shred ueberschrieben) --
beide waren identische Kopien derselben Zugangsdaten. In deployment-notes.md
und INFRASTRUCTURE_REQUIREMENTS.md sind die Klartext-Werte durch Platzhalter
ersetzt, die Dateien bleiben als Dokumentation lesbar.

Ausserhalb der Git-Historie liegt damit kein Zugangsdatum mehr im Projekt.
Das alte NEXTAUTH_SECRET und SMTP_PASSWORD sind laut Nutzer rotiert und
ausser Betrieb; offen bleibt allein der Status des Datenbank-Passworts
(Pruefbefehl in TODO.md Block F).

v1.117.3

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 23:47:53 +02:00
b4e45aca9c security: weitere Dateien mit Zugangsdaten aus dem Git nehmen
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
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
f1eeca6ab6 docs: Schritt 2 der Secret-Rotation auf selbst gehostetes Supabase korrigiert
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Die Anleitung beschrieb Supabase Cloud mit Dashboard-Knopf. Tatsaechlich laeuft
Supabase per Docker auf einem eigenen LXC (scripts/supabase-setup.sh), ohne
Cloud-Dashboard. Der Weg geht ueber POSTGRES_PASSWORD in supabase/docker/.env
plus ALTER USER, mit pg_dumpall als Rueckfahrkarte -- das Passwort steckt an
mehreren Stellen, ein halber Wechsel legt die Datenbank lahm.

Ergaenzt um die Ports und eine ehrliche Einordnung: Die Datenbank hoert auf
einer privaten LAN-Adresse, dieser Schritt hat von den dreien die niedrigste
Prioritaet.

v1.117.1

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 23:15:14 +02:00
230a4034e8 feat: rate limiting, token hashing, remove mock login route
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Erste Abarbeitung des Repository-Audits (siehe TODO.md).

Sicherheit:
- Rate-Limiting für alle vier Auth-Endpunkte. Sie waren unbegrenzt aufrufbar,
  also beliebig viele Mails über den eigenen SMTP-Zugang und beliebig viele
  Rateversuche auf Verifizierungscodes.
- Passwort-Reset-Token nur noch als SHA-256-Hash in der Datenbank. Bisher
  Klartext: Lesezugriff auf die DB genuegte zur Kontouebernahme.
- Tote Mock-Login-Route entfernt. Sie verglich gegen ein hartcodiertes
  Fake-Passwort und war ueber die Middleware-Ausnahme fuer /api/auth/*
  ohne Anmeldung erreichbar.
- Passwort-Reset auf bcrypt-Kosten 12, wie beim Signup.

Reparaturen:
- npm test rief jest auf, obwohl es weder Jest-Config noch Jest-Tests gibt.
  Zeigt jetzt auf Playwright; jest/ts-jest/@types/jest entfernt.
- Falscher sonar.projectKey im Workflow.

Verifiziert per tsc gegen die geaenderten Bereiche: keine neuen Typfehler.

v1.117.0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 20:01:30 +02:00
155c9881bd fix: improve calendar event text contrast
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
Event titles were coloured with color-mix(... 78%, black), which stayed so
close to the event's own colour that it barely separated from the tinted
background. Mixing 30% of the colour into a dark slate keeps the calendar
colour recognisable while making the text properly legible.

v1.116.4

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 18:25:12 +02:00
24a8185587 feat: assign events to calendars
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
2026-09-05 12:34:46 +02:00
d3a990270b fix: remove only saved location suggestions
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
2026-09-05 08:32:49 +02:00
3ed7ec9825 fix: keep display settings per device 2026-09-05 08:00:38 +02:00
8c82db037a feat: add OpenStreetMap location autocomplete
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
2026-09-04 14:19:58 +02:00
c120a0ad7f chore: add SonarQube quality checks
Some checks are pending
Playwright Tests / test (push) Waiting to run
Test and SonarQube / quality (push) Waiting to run
2026-09-03 16:24:41 +02:00
d4ec6b0ef3 fix: key drag targets by date, not weekday, in views wider than a week
Some checks are pending
Playwright Tests / test (push) Waiting to run
The drop preview and the empty-slot input were keyed by date.getDay(), which
is only unique inside a 7-day window. At 21 days every column sharing the
hovered column's weekday lit up — the mirrored drop targets, one per Tuesday.

The invisible half was worse: handleDrop resolved its target with
visibleDays.find(d => d.getDay() === dayOfWeek), so dropping on the second or
third Tuesday scheduled the task on the first one. Both now use the column's
own date; handleDragOver/handleDrop take a Date instead of a weekday number.

Task rendering was already date-based, so only drag state was affected.

v1.115.3

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 13:54:50 +02:00
6f4fe219dc fix: make update-app.sh the single update path and run it at boot
Some checks are pending
Playwright Tests / test (push) Waiting to run
There were two near-identical update scripts and they drifted: the npm ci fix
from 1.114.1 only ever landed in update-app.sh, so the boot path kept running
npm install. my-weekly-todo-update.service now runs update-app.sh, and
boot-update.sh is a shim kept only so a not-yet-recopied unit still works.

To be usable at boot the script needed three things it did not have:

- Skip the rebuild when HEAD already matches origin/main and a standalone
  build exists, so a reboot is not a full rebuild every time (--force
  overrides).
- Do not restart PM2 when its daemon is not up yet. At boot this unit runs
  before pm2-root.service, and probing with `pm2 describe` would spawn a
  stray daemon that races the real service, so it checks the pid file.
- A flock single-instance lock, so a boot run and a manual run cannot install
  into the same tree at once.

It also picks up prisma migrate deploy / generate and the .env copy that only
the boot script had. The log moved to /var/log/my-weekly-todo-update.log.

v1.115.2

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 13:46:18 +02:00
9d4e40e4e3 fix: make the boot update actually fail loudly and survive long builds
Some checks are pending
Playwright Tests / test (push) Waiting to run
The "update on reboot" unit silently did nothing useful. boot-update.sh piped
every command into tee, so `set -e` only saw tee's exit status: a failed
npm install or build left a half-built tree and still logged "Boot update
finished". It also used npm install (rewrites package-lock.json, so the next
git pull aborts), had no GIT_TERMINAL_PROMPT=0, and was not wrapped in a
function even though git pull rewrites it mid-run.

The unit's TimeoutStartSec=300 was the other half: npm ci + prisma generate +
next build takes far longer than 5 minutes in the container, so systemd
SIGTERMed the oneshot mid-install and left a node_modules tree npm could no
longer remove (ENOTEMPTY on rmdir node_modules/date-fns/isEqual).

Also resyncs package-lock.json with package.json, missed in the 1.115.0 commit.

v1.115.1

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 13:27:11 +02:00
224fdba5c6 feat: custom day count for the week view
Some checks are pending
Playwright Tests / test (push) Waiting to run
Add a "Custom" option next to the 1/2/3/5/7 presets where any number of
days from 1 to 31 can be typed. The seven duplicated preset button rows
are replaced by a shared DaysSelector component with panel/header/menu
variants.

The day grid and all-day grid only had CSS for cols-1/2/3/5/7, so any
other count silently fell back to five columns; both now derive
grid-template-columns from the actual day count.

v1.115.0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 10:14:50 +02:00
2028ba80e0 fix: copy public/ and .next/static/ into standalone output on deploy
Some checks are pending
Playwright Tests / test (push) Waiting to run
next.config.js sets output: 'standalone', but Next.js does not copy public/
or .next/static/ into .next/standalone — that is a documented manual step.
Skipping it shipped new server code referencing new chunk hashes while the
old chunks stayed in the standalone tree, so those requests 404'd, React
never hydrated, and pages hung on "Loading session..." while the API kept
returning 200.

v1.114.2

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 13:13:42 +02:00
3338978163 chore: version-control the production deploy script
Moves the deploy script off the server and into the repo as
scripts/update-app.sh, with the two fixes made during the v1.114.0 deploy:

- set -euo pipefail, so a failed git pull aborts instead of rebuilding and
  restarting PM2 on unchanged code while printing "Update Complete"
- npm ci instead of npm install, which rewrote package-lock.json and left the
  tree dirty so the next git pull aborted

The body is wrapped in a main() function because the script lives inside the
checkout it updates, and git pull rewriting it mid-run would leave bash
reading from a stale file offset.

v1.114.1

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 19:03:08 +02:00
7e3e30ec83 feat: add SKIP button to Focus Mode
Focus Mode now shows a SKIP button that moves to the next task of the day
without completing the current one. Skipped task ids are tracked in
WeeklyView and filtered out of the focus queue, so completing a task still
picks the correct next one; the list is cleared when Focus Mode closes.
The timer resets on each new task, and the button is disabled when no other
task is left for today.

Also drops the standalone "Element Colors" and "Weekend Colors" sections from
Styling settings (those controls live in the CSS Variables panel since
1.113.1) and enlarges the CSS variable swatches.

v1.114.0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 17:37:17 +02:00
5510197cf4 fix: add element/weekend color controls to CSS Variables panel, color-first layout
Today Highlight, Past Days, Saturday and Sunday now also appear as their
own groups in the CSS Variables panel, bound to the same profile fields
as the existing Element/Weekend Colors controls so both stay in sync.
Every row now shows the color swatch before its label.

v1.113.1
2026-07-08 20:51:01 +02:00
02b2e40649 feat: add customizable CSS variables and custom CSS to Styling settings
Adds a "CSS Variables" panel to the Styling tab with a color picker and
description for every color token in globals.css (base, sidebar, design
token aliases, event colors, all-day chips), plus a "Custom CSS" textarea
that loads after the default stylesheet and can override any rule.

Overrides are stored per-user (customCssVars, customCss) and applied on
the root container's inline style, so they take precedence over themes
and per-field settings.

v1.113.0
2026-07-08 19:57:21 +02:00
4a18027068 fix: refresh calendar immediately after drag-move of event
Some checks failed
Playwright Tests / test (push) Has been cancelled
After dragging a calendar event to a new time or date, trigger
fetchCalendarEvents on both the old and new date context so the
move is reflected instantly without waiting for the next poll cycle.
Applies to both non-recurring and recurring drag confirms.

v1.112.2
2026-06-10 10:29:45 +02:00
4f140baa38 feat: move jump-to-date icon left of nav pill, picker opens below
- Calendar icon is now a standalone button to the left of the << < Today > >> cluster
- Uses its own ref (navDatePickerBtnRef) so SimpleDatePicker anchors and
  opens directly below the icon instead of at the center date display
- Removed separator inside nav pill (no longer needed)

v1.112.1
2026-05-29 12:14:34 +02:00
e7eb060643 feat: add location autocomplete and custom reminder times to event modal
- Location field shows dropdown suggestions from previously saved locations
  as the user types; selected/submitted locations are persisted to
  profile.viewSettings.savedLocations (max 20, most recent first)
- Reminder dropdown gains a "Custom…" option that opens an inline editor
  for entering X minutes / hours / days before the event; confirmed custom
  values are persisted to profile.viewSettings.customReminderMinutes
  (max 10) and appear in future reminder dropdowns

v1.112.0
2026-05-29 11:53:03 +02:00
530006060a feat: add jump-to-date button to hiding top toolbar left section
v1.111.6
2026-05-29 11:51:54 +02:00
07401d3dfa fix: restore Printer icon to collapsed desktop rail
Print button was accidentally dropped when the history flyout was
slimmed to undo/redo only. Restored next to Refresh in the rail.

v1.111.5
2026-05-11 15:52:04 +02:00
0e189e53b3 fix: vertically center icons, checkbox, and text in task rows
Changed alignItems from flex-start to center on outer div and span.
Removed manual top/left offsets on checkbox (no longer needed with
center alignment). Icon column uses justifyContent: center.

v1.111.4
2026-05-11 15:43:14 +02:00
4a5910779e fix: align checkboxes, right-align end icons, fix weather overlap
- borderLeft now always 4px (transparent when no project/kanban color)
  so all tasks have the same left padding (8px) and checkboxes align
- Rolling and provider icons moved from inline text flow to a right-
  aligned sibling span in the outer flex row (always at line end)
- paddingRight: 30px when weatherEnabled to prevent temperature overlay
  from overlapping task text

v1.111.3
2026-05-11 15:36:57 +02:00
10e7ba98f1 fix: always reserve icon column width for checkbox/text alignment
Icon column (14px fixed width) is now always rendered when priority or
project icon settings are enabled, even when a task has no icons.
Each icon slot is a 12×12px centered container so icons are the same
size and horizontally aligned. Increased gap to 2px for breathing room.

v1.111.2
2026-05-11 15:15:40 +02:00
cb17c91ca6 fix: replace Circle with project icon in task hover menu
The project assign button and dropdown list now show the project's
actual icon (or faFolder as fallback) instead of a plain circle,
matching the icon rendering used in the task row stacked column.

v1.111.1
2026-05-11 15:08:16 +02:00