L1 aus dem TODO-Block Sicherheitsdurchgang: Apple-/Synology-Kalenderpasswoerter lagen
im Klartext in CalendarConnection.accessToken ("email:passwort"). Bei einem
Datenbank-Leak waeren das nicht nur App-Daten, sondern die echten Zugangsdaten der
Nutzer bei Apple bzw. auf ihrem NAS.
- src/lib/credential-crypto.ts: AES-256-GCM, Schluessel aus CREDENTIAL_ENCRYPTION_KEY.
enc1:-Praefix unterscheidet neu verschluesselte Werte von Alt-Klartext -- Klartext
bleibt beim Entschluesseln unveraendert lesbar statt zu brechen.
- src/lib/prisma.ts: Prisma-Client-Extension ver-/entschluesselt accessToken/refreshToken
transparent fuer alle rund ein Dutzend Aufrufstellen (Google/Outlook/Notion-Tokens
laufen mit, sind ebenso sensibel). Kein Aenderungsbedarf an den Aufrufstellen selbst.
- src/lib/auth.ts: PrismaAdapter braucht einen expliziten Typ-Cast fuer den erweiterten
Client (kein $on/$use mehr in dessen TS-Form, zur Laufzeit unveraendert).
Bestehende Zeilen brauchen keine Migration: Alt-Klartext bleibt lesbar und wird beim
naechsten Schreiben (Token-Refresh, Neuverbinden) automatisch verschluesselt.
ACHTUNG -- NICHT DEPLOYEN, bevor CREDENTIAL_ENCRYPTION_KEY in der Produktions-.env
steht: ohne den Schluessel wirft jeder Kalender-Request eine Exception. Konnte nicht
selbst gesetzt werden (Remote-Schreibzugriff per SSH von der Sandbox verweigert).
Verifiziert: Typecheck, Lint, 85 Unit-Tests (6 neu), Produktions-Build -- alle gruen,
mit einem Test-Schluessel gebaut.
v1.124.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>
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>
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>