Ecclesiam
Ein falscher Zeitplan ist schlimmer als gar keiner.
309
Anforderungen
1034
Randfall-Klauseln
94
Domänen-Invarianten
95%
Abdeckung, 2534 Tests
Warum es existiert
Ich wollte einen einzigen Ort, der beantwortet, wann die Messe ist. Und die Anbetung, die Beichte, die Exerzitien, was die Pfarrei diese Woche anbietet — für jede katholische Pfarrei, von wo auch immer man gerade steht. Diese Antwort gibt es heute schon, verteilt auf das Telefon des Pfarrbüros, einen Aushang an der Kirchentür und eine Facebook-Seite, die seit 2019 niemand angefasst hat, was praktisch heißt: es gibt sie nicht.
Drumherum liegen drei Dinge. Ein Pfarrer erreicht die Menschen, die seiner Pfarrei folgen. Eine Pfarrei hält ihre eigenen Informationen aktuell. Und für sie zu spenden ist ein Kopieren und Einfügen, kein Anruf, zu dem man sich erst überwinden muss. Worum es der Plattform wirklich geht, ist Nähe: die Gläubigen, die Priester und die Pfarreien auf eine einzige Fläche zu bringen, die allen offensteht.
Das Problem
Jemand möchte wissen, wann die Messe beginnt. Heute heißt das: im Pfarrbüro anrufen, einen Aushang an der Kirchentür lesen oder eine Facebook-Seite finden, die zuletzt 2019 aktualisiert wurde. Der Zeitplan existiert — er steht nur nirgends, wo man ihn nachschlagen könnte.
Das Schwierige war nie, einen Zeitplan zu veröffentlichen. Es ist, den richtigen zu veröffentlichen: den Sonntag, an dem sie ausfiel, den auf 10 Uhr verlegten Termin, den Feiertag mit einem zusätzlichen Gottesdienst. Diese eine Anforderung hat den Großteil der Architektur bestimmt.
Architektur
Vier Repositories, drei Vertrauensbereiche, ein Django-Backend, dem jede Regel gehört.
Die öffentliche API braucht keine Anmeldedaten und ist rein lesend. Das Pfarr-Dashboard authentifiziert sich mit einem Supabase-JWT und ist rechtebasiert eingeschränkt. Die Superadmin-Konsole liegt hinter Passwort, TOTP und Tailscale, mit einer Caddy-IP-Allowlist, die in der Middleware vor der DRF-Authentifizierung läuft — ein durchgesickertes Token ist außerhalb des Netzes damit wirkungslos, und ein gültiges Dashboard-Superuser-JWT hat dort keinerlei Rechte.
Die Pfarrei ist der Mandant, aber es gibt weder eine Mandantenspalte noch ein Schema pro Mandant. Die Isolation ermittelt die Menge der Pfarreien, die eine Person verwaltet, und filtert jede Abfrage dagegen. Die handelnde Pfarrei kommt immer aus der URL, nie aus dem Payload.
Entscheidungen, die eine Erklärung verdienen
- 01
Messtermine werden berechnet, nie gespeichert. Eine einzige Expansions-Engine bedient die öffentliche API, den Dashboard-Kalender, den iCal-Feed und die App — eine Änderung kann also nicht an einer Stelle korrekt und an einer anderen veraltet sein.
- 02
Zugriffe außerhalb des Bereichs liefern 404, nicht 403. Wer Identifikatoren durchprobiert, erfährt nichts darüber, welche Pfarreien in einer anderen Diözese existieren.
- 03
Jede Regel wird dreifach durchgesetzt: Serializer, model.clean() und ein CheckConstraint in der Datenbank. Eine Regel, die nur im Serializer lebt, ist keine Invariante, sondern Formularvalidierung.
- 04
Das Dokumentations-Repository ist zugleich ein MCP-Server, und sein Prüfer bricht ab, sobald ein Link, ein Bezeichner, ein Dateiverweis, eine Zeilennummer oder ein Constraint-Name nicht mehr auflösbar ist. Dokumentation, die still veralten kann, ist schlimmer als keine.
- 05
Check-in und Event-Zusagen waren ausgeliefert und wurden nach einer Datenschutzprüfung bewusst wieder entfernt. Geblieben ist eine Migration, die die Tabellen löscht. Ein Wiederaufbau wäre eine Produkt- und Compliance-Entscheidung, keine technische.
Stack
Stand
Live und weiterhin in aktiver Entwicklung. Backend, Dashboard und die öffentliche Website sind in Produktion und werden weiter ausgebaut — was hier beschrieben ist, ist der aktuelle Stand, kein Endzustand. Die Superadmin-Konsole läuft in einem privaten Netz. Die mobile App hat eine fertige Release-Signierung, wurde aber nie in einen Store gebracht, und der Pilot umfasst bewusst eine einzige Pfarrei — es gibt keine Nutzungszahlen zu nennen.