Zum Inhalt springen
labkompass

Logbuch#homeos#family#architektur#eigenbau#selfhosting

Die dritte Säule war Wiederholung: Family in HomeOS

Von Niclas Hennrich · veröffentlicht · geschehen am


BuildIn Arbeit

Selbst gebaut und in Betrieb genommen. Gehört zum Vorhaben HomeOS — Control Center mit drei Säulen.

neue Tabellen mit eigenem Präfix
20
neue Backend-Tests
186
neue Seiten im Frontend
9

Kurz zur Einordnung: HomeOS ist mein selbst gebautes Control Center fürs Homelab, aus dem Infrastruktur-NOC gewachsen, mit drei Säulen: Infrastruktur, Haus (Smart Home) und Family (Haushalt). Am Vortag war die Haus-Säule entstanden. Das hier ist die dritte.

Was ich wollte: Einen selbst gehosteten Familienplaner — Mitglieder, gemeinsamer Kalender, Aufgaben, Routinen, Einkaufsliste, Essensplan, Anwesenheit, Benachrichtigungen, ein „Heute"-Aggregat und ein Wanddisplay. Funktional wie die kommerziellen Familien-Apps, aber im eigenen Haus und mit dem echten Smart Home verbunden. Und ohne die bestehende Architektur zu beschädigen.

Was ich gebaut habe: Exakt nach dem Muster der Haus-Säule. Eigener Tabellen-Präfix (20 Tabellen, zwei rein additive Migrationen), eigener Service-Ordner, eigene API-Routen — und ein Grenztest in beide Richtungen: Family-Code darf keinen Haus-Code importieren und umgekehrt. Ein Umzug war nötig: Der Ereignis-Bus lebte bis dahin im Haus-Modul. Sobald zwei Domänen ihn brauchten, musste er in den neutralen Kern. Vorher wäre der Umzug Spekulation gewesen, danach eine Grenzverletzung. Querschnitt erkennt man am Importzwang.

Ein paar Entscheidungen, die ich festhalten will: Wiederholungen sind RRULE-Strings — das Vokabular aus dem Kalenderstandard iCalendar — und werden an genau einer Stelle expandiert; kein eigenes Wiederholungs-Vokabular. Termine werden nie materialisiert; wiederkehrende Aufgaben halten genau eine offene Instanz, Erledigen schreibt Historie und rückt die Fälligkeit. Externe Kalender kommen zuerst per ICS-Abo, weil Google, iCloud und Outlook alle ICS exportieren; OAuth-Connectoren wären externe Blocker gewesen. Der Sync-Zustand steht sichtbar am Kalender, und ein toter Feed löscht nichts. Anwesenheit ist bewusst manuell (zuhause, unterwegs, schläft, unbekannt); automatische Quellen lägen nahe und bleiben draußen — das ist eine Privacy-Entscheidung, keine technische Lücke. Das Punktesystem ist eine Einstellung und komplett abschaltbar.

Haus und Family reden miteinander, ohne sich zu kennen. Automationen reagieren generisch auf Ereignistypen mit dem Präfix family.; die Engine weiß nichts von einem Family-Modul. Zurück läuft es über einen Abonnenten am Bus, der eine Automations-Benachrichtigung in eine Family-Nachricht verwandelt. Diese Kette lief live: Eine Regel an einem Mock-Bewegungsmelder erzeugte den ersten echten Family-Hinweis.

Das Frontend: Neun Seiten, von „Heute" über den Kalender mit vier Ansichten bis zur mobile-first gedachten Einkaufsliste. Das Wanddisplay ist Vollbild ohne Navigation, mit Pixel-Shift gegen OLED-Einbrennen und Nacht-Dimmen. PWA nur mit Manifest und Icon, bewusst ohne Service Worker.

Was schiefging: Die Zeitzonenfalle vom Vortag — SQLite gibt naive Zeitstempel zurück, PostgreSQL nicht — traf erneut, diesmal bei Fälligkeiten; an der Übersetzungsstelle normalisiert. Zwei Enum-Namen waren im Repo schon belegt. Eine autogenerierte Migration erzeugte einen namenlosen Unique-Constraint, der den Downgrade gebrochen hätte; beim Review benannt. Und das Feld für die Erinnerungsminuten wäre ohne einen Minuten-Tick eine Attrappe gewesen — ein gespeichertes Feld ohne Wirkung ist ein stilles Versprechen. Der Tick läuft idempotent, mit einem Schlüssel je Vorkommen, und wurde sofort nachgezogen statt liegen gelassen.

Ergebnis: 186 neue Backend-Tests, alle zwölf Ansichten auf Desktop und Mobil per Screenshot real angesehen, drei Abläufe im Browser durchgeklickt. Offen bleiben Ausnahmen (EXDATE) im ICS-Sync, CalDAV als Connector und automatische Anwesenheitsquellen — dokumentiert, nichts davon versteckt. Ob die Familie das Ding wirklich benutzt, entscheidet sich in den nächsten Wochen, nicht in der Testsuite.

Was ich mitnehme: Eine Domänengrenze skaliert, wenn sie ein Muster ist. Die dritte Domäne kostete keinen Architekturstreit — Tabellen-Präfix, Service-Ordner, Grenztest, fertig. Die teure Entscheidung war die erste.