Xircuit Blog

Produkt-Updates, Entwickler-Logs und Neuigkeiten aus der Entwicklung von Xircuit.

Eine Plattform, sieben Branchen: Mandantenfähigkeit von Anfang an cover image

Eine Plattform, sieben Branchen: Mandantenfähigkeit von Anfang an


Eine Plattform, sieben Branchen: Mandantenfähigkeit von Anfang an

Empfangsbereich eines modernen Studios Foto: Daria Nepriakhina · StockSnap (CC0 1.0), via Openverse

Als wir mit Xircuit anfingen, stand eine Versuchung im Raum, die fast jedes Softwareprojekt kennt: für den ersten Kunden bauen und alles andere später sehen. Ein Fitnessstudio hat ganz konkrete Wünsche, und es wäre bequem gewesen, genau diese Wünsche in Tabellen und Menüs zu gießen. Nur hätte uns das in eine Ecke manövriert, aus der man später schwer wieder herauskommt. Eine Physiotherapiepraxis, ein Verein, ein Spa — sie alle brauchen im Kern dasselbe, sprechen aber eine andere Sprache und arbeiten nach anderen Regeln.

Deshalb haben wir von der ersten Zeile an nicht ein Studio gebaut, sondern eine mandantenfähige Plattform, die viele Studios, Praxen und Vereine nebeneinander trägt. Diese Woche beschreibe ich, wie diese Mandantenfähigkeit aufgebaut ist — und warum die drei unscheinbaren Bausteine Organisation, Rolle und Mitgliedschaft das ganze Gewicht des Systems tragen.

Eine Plattform, sieben Sprachen

Jede Organisation in Xircuit gehört zu genau einer von sieben Branchen. Wir nennen sie intern Tiers, und sie sind mehr als ein Etikett: Ein Tier entscheidet, wie die Oberfläche mit den Menschen spricht, die zu einer Organisation gehören. Dasselbe Datenmodell, dieselbe Mitgliederliste, dieselbe Detailseite — aber im Fitnessstudio steht dort „Mitglied", in der Praxis „Patient" und im Coaching-Kontext „Klient".

Das klingt nach Kosmetik, ist aber eine bewusste Architekturentscheidung. Wir hätten für jede Branche eine eigene Anwendung bauen können, mit eigenem Wortschatz und eigener Datenhaltung. Das Ergebnis wären sieben Codebasen gewesen, die langsam auseinanderdriften, und jede Fehlerbehebung hätte man siebenmal machen müssen. Stattdessen gibt es genau ein Modell einer Person, die einer Organisation angehört, und der Tier bestimmt nur, welche Begriffe und welche Voreinstellungen darübergelegt werden. Die Sprache ist eine Schicht an der Oberfläche, nicht ein Bruch im Fundament.

Diese Trennung zwischen „was ist es wirklich" und „wie nennen wir es hier" zieht sich durch das gesamte Produkt. Ein Termin bleibt ein Termin, egal ob er im Salon ein Styling-Slot ist oder in der Praxis eine Behandlung. Der Kern ist geteilt, die Fassade ist branchenspezifisch.

Rollen gehören zur Organisation, nicht zum Nutzer

Die zweite tragende Entscheidung betrifft die Rollen. Wer in Xircuit etwas tun darf, ergibt sich nicht aus einer globalen Eigenschaft der Person, sondern aus ihrer Rolle innerhalb einer bestimmten Organisation. Ein GymManager, ein Trainer, ein PracticeAdmin, ein einfaches Member — all das sind keine Etiketten, die einem Nutzerkonto pauschal anhaften, sondern Rollen, die an die Kombination aus Person und Organisation gebunden sind.

Der Unterschied wird an einem Beispiel greifbar. Dieselbe Person kann in einem Studio Trainer sein und in einem anderen schlicht Mitglied. Sie kann in ihrer eigenen Praxis PracticeAdmin sein und im Verein nebenan nur ein normales Mitglied. Es ist immer dieselbe Identität — die stabile Anmeldung aus Auth0, über die ich letzte Woche geschrieben habe —, aber die Rechte hängen am Kontext. Beim Wechsel der aktiven Organisation wechselt also nicht die Person, sondern das Bündel dessen, was sie hier tun darf.

Hätten wir Rollen global vergeben, wäre dieses Nebeneinander unmöglich gewesen, ohne für jede Konstellation ein neues Konto anzulegen. Menschen hätten dann mehrere Logins jonglieren müssen, nur weil sie in mehreren Rollen unterwegs sind. Indem die Rolle an der Mitgliedschaft hängt und nicht am Nutzer, bleibt die Identität eine und dieselbe, und die Berechtigungen bleiben sauber pro Organisation getrennt.

Eine vielfältige Gruppe von Menschen Foto: Startup Stock Photos · StockSnap (CC0 1.0), via Openverse

Autorisierung an einer einzigen Stelle

Wenn Rechte kontextabhängig sind, wird die Frage „darf dieser Mensch das gerade" schnell verzwickt. Genau deshalb haben wir die Autorisierung nicht über den Code verstreut, sondern zentral gebündelt. Jede Prüfung läuft durch dieselbe Stelle, statt in jedem Endpunkt eine eigene, leicht abweichende Variante derselben Logik zu haben. Das ist weniger Bequemlichkeit als Sicherheitsprinzip: Verstreute Berechtigungsprüfungen sind der Ort, an dem Lücken entstehen, weil eine Kopie irgendwann vergessen wird, wenn sich eine Regel ändert.

Ein Detail, auf das ich besonders achte, ist das Protokollieren der Verweigerungen. Wir haben einen kleinen AuthLog-Deny-Helper, durch den jede abgelehnte Anfrage läuft und nachvollziehbar festgehalten wird — welche Regel gegriffen hat und in welchem Kontext. Eine stille Verweigerung ist im Betrieb ein Albtraum: Jemand kommt nicht an etwas heran, das er eigentlich sehen dürfte, und niemand kann rekonstruieren, warum. Indem wir das „Nein" konsequent an einer Stelle aussprechen und aufzeichnen, wird aus einem diffusen „das funktioniert nicht" eine konkrete, diagnostizierbare Zeile.

Wichtig bleibt dabei die Regel aus der Vorwoche: Protokolliert wird der Fluss, nicht der Inhalt. Der Deny-Helper hält fest, dass und warum eine Prüfung fehlschlug, aber keine personenbezogenen Daten. Es geht darum, den Weg nachvollziehbar zu machen, ohne die Menschen offenzulegen, die diesen Weg gegangen sind.

Mitgliederverwaltung als gemeinsame Basis

All das läuft auf einen Punkt hinaus, der leicht zu übersehen ist, weil er so grundlegend ist: Die Mitgliederverwaltung ist die gemeinsame Basis, auf der später alles andere aufsetzt. Termine, Gesundheitsdaten, Abrechnung, Zutritt — kein einziges dieser Themen steht für sich. Sie alle brauchen die Antwort auf dieselbe Frage: Welche Person gehört zu welcher Organisation, in welcher Rolle?

Ein Termin ist die Verabredung zwischen einem Mitglied und einer Organisation. Eine Gesundheitsmessung gehört einem Mitglied und ist nur für bestimmte Rollen derselben Organisation sichtbar. Eine Rechnung geht an ein Mitglied; ein Zutritt an der Tür prüft, ob dieses Mitglied gerade berechtigt ist. Wenn die Mitgliedschaft als Fundament nicht stimmt, kippt darüber alles andere. Deshalb haben wir viel Sorgfalt in diese Ebene gesteckt, bevor wir auch nur einen der darauf aufbauenden Bereiche in Angriff genommen haben.

Man merkt das Fundament erst, wenn es fehlt. Solange es trägt, wirkt es unsichtbar — und genau das ist das Ziel.

Realistische Daten über alle sieben Tiers

Eine mandantenfähige Plattform hat ein hässliches Testproblem: Wenn man nur mit einem leeren Studio entwickelt, sieht man die anderen sechs Branchen nie in echt. Bugs, die nur in der Physiopraxis oder nur im Verein auftreten, entdeckt man dann erst, wenn ein echter Kunde darüberstolpert. Das wollten wir vermeiden.

Deshalb bauen unsere Seed-Daten realistische Beispielorganisationen über alle sieben Tiers hinweg auf. Beim Hochfahren des Systems entstehen ein Fitnessstudio, eine Praxis, ein Verein, ein Spa, ein Salon und die übrigen Branchen mit plausiblen Mitgliedern, Rollen und Verknüpfungen — keine Platzhalter wie „Test Test", sondern Datensätze, die einer echten Organisation ähneln. So lässt sich jede Oberfläche gegen echte Daten prüfen, und man sieht sofort, ob die branchenspezifische Sprache greift, ob die Rollen richtig auflösen und ob die Autorisierung an der zentralen Stelle das erwartete Ergebnis liefert.

Der Nebeneffekt ist ein besseres Entwicklungsgefühl. Wer eine neue Funktion baut, klickt nicht durch ein steriles Demo-Konto, sondern durch sieben glaubwürdige Welten nebeneinander. Was in einer Branche seltsam aussieht, fällt dann früh auf — lange bevor es jemanden im Betrieb trifft.

Was kommt als Nächstes?

Nächste Woche: ein Logging- und Audit-Standard, der Fehler diagnostizierbar macht, ohne je personenbezogene Daten zu protokollieren.


Kommentare

Noch keine Kommentare. Teilen Sie als Erste(r) Ihre Gedanken!

Kommentar hinterlassen