Files
Aether/kalender-plan.md
T
marcandClaude Opus 5 8f90a7fbd6 docs: Plan für einen Kalender in Aether
Radicale ist für einen einfachen Kalender zu umständlich, vor allem fehlt
die OIDC-Anbindung. Der Plan hält fest, warum das als Modul in Aether
besser aufgehoben ist: Ein CalDAV-Client kann ohnehin kein OIDC, er will
Benutzername und Passwort – und App-Passwörter für DAV gibt es hier schon.

Vor dem Schreiben nachgesehen statt geschätzt: emersion/go-webdav v0.7.0
beantwortet PROPFIND/REPORT selbst, caldav.Filter() filtert, und der
Zeitraumfilter löst Wiederholungen über go-ical und rrule-go auf. Damit
ist der Teil, vor dem ich gewarnt hatte, in der Bibliothek. Zu erfüllen
bleibt eine Schnittstelle mit neun Methoden – Speicherarbeit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 20:43:56 +02:00

4.9 KiB
Raw Blame History

Kalender in Aether – Plan

Stand 02.09.2026. Ausgangspunkt: Radicale ist für einen einfachen selbst gehosteten Kalender überraschend umständlich (Konfigurationsdateien, dünne Doku, keine OIDC-Anbindung).

Entscheidung: ein Modul in Aether, kein eigener Dienst

Der Grund ist genau das, was bei Radicale gefehlt hat.

Ein CalDAV-Client kann kein OIDC. DAVx5, Thunderbird und die Kalender-App melden sich mit Benutzername und Passwort an – ein Anmeldefenster im Browser gibt es dort nicht. Wer OIDC für CalDAV sucht, sucht etwas, das es so nicht gibt. Die richtige Antwort sind App-Passwörter, und die hat Aether schon: Das WebDAV unter /dav/ läuft bereits darüber.

Damit ist die Rechnung einfach:

Radicale o. ä. Modul in Aether
Anmeldung Oberfläche eigenes Konzept, kein OIDC PocketID, schon da
Anmeldung DAVx5 eigene Nutzerdatei App-Passwörter, schon da
Reverse Proxy, TLS zusätzlicher Eintrag schon da
Sicherung zweiter Datenbestand dieselbe Datenbank
Oberfläche im Grunde keine die, die wir bauen

Was die Bibliothek abnimmt

github.com/emersion/go-webdav (v0.7.0, Oktober 2025) bringt einen CalDAV-Handler mit. Nachgesehen, nicht angenommen:

  • Der Handler beantwortet PROPFIND, OPTIONS und REPORT selbst und liest calendar-query wie calendar-multiget.
  • caldav.Filter() wendet die Filter der Anfrage auf die Termine an.
  • Der Zeitraumfilter löst Wiederholungen auf: matchCompTimeRange ruft comp.RecurrenceSet(loc), und go-ical stützt sich dafür auf teambition/rrule-go. Genau der Teil, vor dem ich gewarnt hatte – „jeden zweiten Dienstag, über die Zeitumstellung hinweg" – steckt in der Bibliothek und nicht in unserem Code.

Zu erfüllen ist eine Schnittstelle mit neun Methoden plus dem Nutzer-Principal:

CalendarHomeSetPath · CreateCalendar · ListCalendars · GetCalendar
GetCalendarObject · ListCalendarObjects · QueryCalendarObjects
PutCalendarObject · DeleteCalendarObject

Das ist Speicherarbeit, keine Protokollarbeit. Die Einschätzung „zwei Wochen bis DAVx5 läuft, danach ein halbes Jahr Kleinkram" gilt für einen Server von Grund auf – hier nicht.

Datenmodell

Zwei Tabellen, mehr braucht es nicht:

  • calendars – Besitzer, Name, Farbe, Zeitzone, ctag (ändert sich bei jeder Änderung, daran erkennt der Client, dass es etwas Neues gibt).
  • calendar_objects – Kalender, UID, das .ics roh und unverändert, etag, dazu abgeleitet dtstart/dtend und ein Kennzeichen, ob eine Wiederholung dranhängt.

Die wichtigste Regel: das .ics byte-genau speichern, wie der Client es geschickt hat. Nicht zerlegen und neu zusammensetzen – sonst gehen Eigenschaften verloren, die wir nicht kennen (Anhänge, Teilnehmerstatus, Herstellerfelder), und beim nächsten Abgleich fehlt etwas, das vorher da war. Die abgeleiteten Spalten sind nur zum Vorsortieren da.

Phasen

Inhalt Aufwand
1 CalDAV lesend und schreibend, ein Kalender, Anmeldung über App-Passwörter, Auffindpfade (/.well-known/caldav, current-user-principal, calendar-home-set). Ziel: DAVx5 gleicht ab. 1–2 Abende
2 Mehrere Kalender, Farbe, Umbenennen, Löschen. Export als .ics, Import einer bestehenden Datei. 1 Abend
3 Weboberfläche in Aether: Monat, Woche, Liste; Termin anlegen, ändern, löschen. Der Teil, der Spaß macht – und dessen Fehler man sieht. 2–3 Abende
4 sync-collection statt Vollabgleich, Aufgaben (VTODO), Kalender in der HoneyOS-Leiste. offen
5 Kontakte (CardDAV). Dieselbe Maschinerie, dieselbe Bibliothek – und einfacher, weil es dort keine Wiederholungen gibt. später entscheiden

Was es ausdrücklich nicht wird

Keine Einladungen an andere Leute (iMIP/Scheduling), keine Frei/Belegt-Abfragen über Häuser hinweg, kein Teilen zwischen Nutzern. Das ist der Teil, an dem Groupware-Server groß und kompliziert werden. Ein Kalender für dich, auf allen deinen Geräten – das ist das Ziel.

Die Notausfahrt

Ein Kalender, der lautlos einen Termin verschluckt, ist schlimmer als einer, der ausfällt. Deshalb:

  • Export als .ics je Kalender ist Teil von Phase 2, nicht später. Solange du deine Termine jederzeit herausbekommst, ist keine Entscheidung endgültig.
  • Auf Wunsch zusätzlich als Verzeichnis mit einer Datei je Termin – das ist der Aufbau, den Radicale liest. Umziehen wäre dann ein Kopiervorgang.
  • Tests mit echten Anfragen, die DAVx5 stellt (mitgeschnitten, nicht erfunden), und eine Prüfliste in TESTING.md fürs Telefon.

Offene Fragen

  1. Wie viele Kalender – einer, oder getrennt nach Privat/Arbeit/Geburtstage?
  2. Aufgaben mit dazu (VTODO), oder reine Termine?
  3. Der Kalender in der HoneyOS-Leiste: nur der nächste Termin, oder eine eigene Kachel?
  4. Kontakte: ernsthaft geplant oder erst mal offenlassen? Es ändert nichts an Phase 1–3, nur an der Benennung der Pakete.