CodamAIDocs
Themafertig

Warum beide Arten fachlich gleich sein müssen

Gleicher Code, gleiche Regeln, gleiche Ablehnungen. Was „fachlich gleich“ konkret heißt, wo der Unterschied trotzdem sichtbar wird und wo nicht.

Ausprägungen
dieselbe Frage, zwei Wegegleich: Regeln, Antworten, Ablehnungenverschieden: Laufzeit, Ausfall, Startprüfungen

Worum es geht

CIAS läuft entweder im selben Prozess wie CDMS oder als eigener Dienst. Diese Entscheidung ist eine Entscheidung über Betrieb: über Prozesse, Netzwerk und Ausfälle. Sie darf keine Entscheidung darüber sein, wer was darf.

Der Grund ist einfach: Sonst gäbe es zwei Systeme mit einem Namen. Ein Kunde, der im einen bedient wird und im anderen abgelehnt, wäre kein Betriebsunterschied, sondern ein Sicherheitsvorfall — und man würde ihn erst bemerken, wenn jemand umzieht.

Wie das technisch erreicht wird

Zwischen CDMS und CIAS steht kein direkter Aufruf, sondern ein Port. Ein Port ist eine Schnittstelle: eine Frage als Methodensignatur, ohne jede Aussage darüber, wer sie wie beantwortet. Die Antwort liefert ein Adapter, und davon gibt es genau zwei — einen für jede Bauform.

flowchart TB
    G["Aufrufer in cias-authentication<br/>TenantGate / AttributeLookup<br/><i>Regeln, Zwischenspeicher, Ablehnung</i>"]
    G --> P{{"Port<br/>TenantLookupPort"}}
    P -->|eingebettet| LA["LocalTenantLookupAdapter<br/>(cias-tenancy)"]
    P -->|getrennt| RA["RemoteTenantLookupAdapter<br/>(cias-tenancy-client)"]
    RA -->|HTTP| CTL["TenantLookupController<br/>im CIAS-Dienst"]
    LA --> UC["TenantManagementUseCase.standing"]
    CTL --> UC
    UC --> DB[("Mandanten von CIAS")]

Lies das Bild von unten: Beide Wege enden bei derselben Methode. Der lokale Adapter ruft sie direkt auf. Der entfernte Adapter schickt HTTP an einen Endpunkt im CIAS-Dienst, und dieser Endpunkt ruft genau dieselbe Methode auf. Die Regel, ob ein Mandant bedient wird, existiert also nur ein einziges Mal.

Genauso liegt es oben: Der Aufrufer ist in beiden Bauformen dieselbe Klasse. Der Zwischenspeicher des Mandanten-Tors, die Frist von 30 Sekunden, die Ablehnung im Zweifel — das alles gehört dem Aufrufer, nicht dem Adapter. Die Adapter selbst dürfen weder zwischenspeichern noch wiederholen noch eine Antwort schönen.

Die drei Fragen über die Grenze

Es sind nur drei Fragen, die zwischen CDMS und CIAS wandern. Jede hat einen Port und zwei Adapter:

FrageWer fragtEingebettetGetrennt
Darf Mandant X gerade bedient werden?Mandanten-Tor, bei jeder AnfrageMethodenaufruf in cias-tenancyGET /cias/lookup/tenants/{key}
Welche Attributwerte hat diese Person in diesem Mandanten?Filterkette, bei jeder Anfrage mit MandantMethodenaufruf in cias-userGET /cias/lookup/users/{id}/attributes
Welche Rollen und Attribute meldet dieses Modul an?CIAS, beim Start und auf AnstoßAufruf einer Bean im selben ProzessGET /cias/fetch beim Modul

Bei den ersten beiden fragt CDMS bei CIAS. Bei der dritten ist es umgekehrt: Da fragt CIAS bei CDMS. Mehr dazu unter Module melden Rollen und Attribute an.

Wie verhindert wird, dass die beiden auseinanderlaufen

Zwei Adapter, geschrieben zu verschiedenen Zeiten, laufen von selbst auseinander. Dagegen gibt es zu jedem Port eine gemeinsame Vertragssuite: eine Sammlung von Tests, die nicht einen Adapter prüft, sondern den Port. Jeder Adapter meldet sich bei derselben Suite an und muss sie bestehen.

Was diese Suiten festhalten, ist immer dieselbe Art von Unterscheidung — und sie ist der eigentliche Grund, warum es sie gibt:

Die Unterscheidung, die kein Adapter verwischen darf
  1. 1
    CIAS
    bedient — der Mandant existiert und darf arbeiten
    Die Anfrage läuft weiter.
  2. 2
    CIAS
    existiert, aber nicht bedient — gesperrt, geschlossen oder außerhalb seines Zeitfensters
    Abgelehnt. Im Log steht, dass jemand bewusst gesperrt wurde.
  3. 3
    CIAS
    kennt keiner — auf diesen Schlüssel läuft kein Mandant
    Ebenfalls abgelehnt, aber aus einem anderen Grund. Für einen Betreiber ist das ein ganz anderer nächster Schritt.
  4. 4
    CIAS
    konnte nicht gefragt werden — Zeitüberschreitung, abgelehnte Verbindung, unlesbare Antwort
    Ergebnis: Das ist kein „nein“. Ein Adapter, der daraus ein „nein“ machte, meldete jede Störung als bewusste Sperre. Er wirft stattdessen, und der Aufrufer entscheidet — aus seinem Zwischenspeicher oder mit einer Ablehnung.

Dieselbe Sorgfalt gilt an der dritten Frage: „meldet nichts an“ und „konnte nicht gefragt werden“ dürfen nicht verwechselt werden. Der Rollenabgleich zieht zurück, was ein Modul nicht mehr anmeldet — ein Adapter, der einen Ausfall als leere Anmeldung durchreichte, nähme einem Dienst seine Rollen weg, nur weil er gerade neu startet.

Wo der Unterschied trotzdem sichtbar wird

„Fachlich gleich“ heißt nicht „in jeder Hinsicht gleich“. Es heißt: Was entschieden wird, ist gleich. Nicht gleich ist, was ein Ausfall bedeutet und wie lange etwas dauert.

Gleich und nicht gleich
Gleich
die Fachlichkeit
  • welcher Mandant bedient wird und welcher nicht
  • welche Rollen und Attributwerte in einer Anfrage gelten
  • welche Anfragen abgelehnt werden, mit welchem Fehlerschlüssel
  • was eine Rollenvergabe darf und was die Obergrenze verbietet
  • welche Rollen der Abgleich anlegt, umbenennt oder als veraltet markiert
Nicht gleich
der Betrieb
  • Laufzeit: ein Methodenaufruf gegen einen HTTP-Aufruf über das Netz
  • Ausfall: nur getrennt kann CIAS allein ausfallen
  • Zugangsdaten: nur getrennt braucht CDMS ein eigenes Dienstkonto
  • Startprüfungen: der eigenständige Dienst prüft zusätzlich, ob Entwicklungseinstellungen übrig sind
  • Datenbanken: eine gemeinsame gegen zwei getrennte

Drei Punkte davon lohnen ein genaueres Hinsehen.

Der Ausfall. Eingebettet gibt es kein „halb“: Entweder läuft der Prozess oder nicht. Getrennt kann CIAS stehen, während CDMS weiterläuft. Dann entscheidet der Zwischenspeicher des Mandanten-Tors, und er entscheidet nach einer Regel, die absichtlich unsymmetrisch ist: Ein Ausfall darf niemanden aussperren, der schon gearbeitet hat, und niemanden hereinlassen, der es nicht hat. Wer im Zwischenspeicher steht, arbeitet mit der letzten bekannten Antwort weiter — Ablehnung eingeschlossen. Wer nicht darin steht, wird abgelehnt. Einzelheiten unter Wenn CIAS nicht erreichbar ist.

Die Verzögerung einer Sperre. Das Mandanten-Tor merkt sich seine Antwort für kurze Zeit, standardmäßig 30 Sekunden. Sperrst du einen Mandanten, wirkt das deshalb nach spätestens dieser Frist — in beiden Bauformen. Eingebettet ist das leicht zu unterschätzen, weil man denkt, im selben Prozess müsse es sofort gelten. Die Frist gehört aber dem Aufrufer, und den gibt es in beiden Bauformen.

Die Startprüfungen. Beide Betriebsarten prüfen beim Start, ob Entwicklungseinstellungen stehen geblieben sind, und starten dann nicht, solange codamai.safety.mode nicht warn ist. Einen Unterschied gibt es nur beim Schema: Das eigenständige CIAS verlangt zusätzlich ddl-auto: validate, eingebettet gehört das Schema der Anwendung — siehe Im Zweifel ablehnen.

Wo er nicht sichtbar wird

Für den Client, der die API aufruft, ist die Bauform unsichtbar. Es gibt keinen Header, kein Feld in der Antwort und keinen Fehlerschlüssel, aus dem man sie ablesen könnte. Eine abgelehnte Anfrage sieht in beiden Bauformen gleich aus, und das ist Absicht: Ablehnungen sollen nichts über den inneren Aufbau verraten. Siehe Ablehnungen, die nichts verraten.

Auch die Rollen und Rechte sind unsichtbar verschoben. Was eine Rolle auf den Daten erlaubt, steht im Modell und wird von CDMS durchgesetzt — dort kommt CIAS in keiner Bauform vor.

Fallen

Weiter

Quellen im Code und in der Wissensdatenbank
  • CIAS/cias-kernel – TenantLookupPort, TenantStanding (leer ≠ nicht bedient), TenantBoundAttributePort
  • CIAS/cias-tenancy – LocalTenantLookupAdapter (delegiert an TenantManagementUseCase.standing), TenantLookupController (ruft dieselbe Methode)
  • CIAS/cias-tenancy-client – RemoteTenantLookupAdapter, RemoteTenantBoundAttributeAdapter (jeder Fehler wird geworfen, 401/403 ist kein „nein“)
  • CIAS/cias-user – LocalTenantBoundAttributeAdapter, AttributeLookupController (setzt auf denselben Adapter auf)
  • CIAS/cias-authentication – TenantGate (Aufrufer und Zwischenspeicher, identisch in beiden Bauformen), AttributeLookup, TokenParser, JwtSessionFilter
  • CIAS/cias-authorization – ModuleDeclarationPort, LocalModuleDeclarationAdapter, RemoteModuleDeclarationAdapter (GET /cias/fetch)
  • CIAS/cias-test-support – TenantLookupContract, TenantBoundAttributeContract; CIAS/cias-authorization – ModuleDeclarationContract
  • CIAS/cias-spring-boot-starter – CiasSafetyCheck (codamai.safety.mode)
  • CIAS/cias-runtime – CiasLocalProfileNotice
  • CIAS/cias-kernel/docs/adr – ADR-022; CIAS/cias-authentication/docs/adr – ADR-021, ADR-042; CIAS/cias-authorization/docs/adr – ADR-025
Suchen