1. Funktionale Anforderungen
(was die Middleware fachlich leisten soll)
Die Middleware von Los 1 bildet die zentrale Zugriffsebene der BayernCloud Tourismus. Sie ermöglicht eine performante, standardisierte und sichere Bereitstellung sämtlicher touristisch relevanter Daten, die aus Los 2 übernommen, durch Los 3 verwaltet und von Los 4 direkt konsumiert werden. Damit wird eine einheitliche, robuste und zukunftsfähige Grundlage geschaffen, auf der vielfältige Anwendungen und Services aufbauen können.
Architekturüberblick
Das Konzept speichert sämtliche von Los 2 gelieferten Daten in einer performanten Such- und Abfrageschicht auf Basis von Elasticsearch (bzw. Elasticsearch-kompatibel). Kernidee ist die vollständige Ablage der Daten im JSON-LD-Format (@graph, schema.org/ODTA-konform) als _source, während die für Suche und Filterung relevanten Felder gezielt materialisiert werden. Dadurch bleibt das Datenmodell flexibel gegenüber Schema-Änderungen und erlaubt gleichzeitig hochperformante Abfragen (Volltext, Geo, Zeit, Facetten). Die Middleware erfüllt die vom Auftraggeber geforderte Mindestleistung von 25 vollständigen Datensätzen pro Sekunde. Darüber hinaus ist die Architektur so dimensioniert, dass typische Webanfragen auch bei Spitzenlast innerhalb branchenüblicher Antwortzeiten (sub-Sekunden bis wenige hundert Millisekunden) beantwortet werden. Versionierte Indizes und Alias-Switching stellen einen Zero-Downtime-Betrieb auf Datenebene sicher, während spezielle Rollover-Strategien für Sensorikdaten die Verarbeitung hochfrequenter Datenströme ermöglichen.
Das folgende Architekturdiagramm skizziert den Systemaufbau der Middleware.
@startuml
!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Context.puml
left to right direction
' --- Konsumenten & Externe Systeme links ---
together {
System_Boundary(ext, "Externe Systeme") {
component "Los 2 - dataCycle\n(JSON-LD @graph Quelle)" as l2
}
System_Boundary(cons, "Konsumenten") {
Person_Ext(user, "Nutzer", "Widgets, DMS, Partner")
}
}
' --- Middleware rechts ---
System_Boundary(bct, "Los 1 - Middleware") {
left to right direction
together {
component "WAF / Ingress\nTLS, Rate-Limits, CORS, Edge-Cache" as ingress
component "API Gateway\nREST/GraphQL, JWT-Validierung, Routing" as api
}
together {
component "Search Orchestrator\nÜbersetzt API-Requests in Elasticsearch-Queries\n+ Policy-Check & In-Memory-Cache" as orchestrator
component "Serializer-Service (optional)\nJSON-LD @graph Ausgabe" as serializer
component "ETL / Intake\nFetch, Transform, Bulk-Indexing von Los 2" as etl
}
component "Elasticsearch (Cluster)\nDatenhaltung & Suche\n(Blue/Green, ISM)" as os
}
' --- Flows ---
user -[#orange]-> ingress: HTTPS
ingress -[#orange]-> api: Requestweiterleitung (validiert, ggf. gecacht)
api -[#orange]-> orchestrator : validierte Requests
orchestrator -[#orange]-> serializer : optional, JSON-LD @graph
serializer -[#orange]-> user : Response (Open Data)
orchestrator -[#orange]-> user : Response (wenn ohne Serializer)
orchestrator --> os : Search/Filter/Geo
os --> orchestrator : Search Results
l2 --> etl : JSON-LD Pull/Webhook
etl --> os : Bulk/Upsert (Blue/Green)
' Layout-Hack
cons -[hidden]-> bct
ext -[hidden]-> bct
etl -[hidden]-> os
@enduml
Hinweis: Der Begriff „Search Orchestrator“ bezeichnet die fachliche Kernkomponente innerhalb des API Service. Sie übernimmt insbesondere die Validierung von Anfragen, die Anwendung von Zugriffspolicies sowie die Übersetzung in Elasticsearch-kompatible Suchabfragen.
Die Architektur ist so gestaltet, dass kundenspezifische Erweiterungen (z. B. neue Endpunkte, zusätzliche Filter, spezielle Datenaufbereitungen) flexibel integriert werden können, ohne bestehende Schnittstellen zu beeinträchtigen. Neue Anforderungen des Auftraggebers können durch zusätzliche Microservices, Index-Erweiterungen oder API-Routen umgesetzt werden. Alle Erweiterungen bleiben kompatibel zur bestehenden API und werden dokumentiert.
API-Schnittstelle
Die Middleware stellt eine leistungsstarke RESTful API auf Basis des OpenAPI-Standards (Version 3.1) bereit. Sämtliche Endpunkte liefern Inhalte im JSON-LD-Format (@graph) und unterstützen neben klassischen Funktionen wie Filterung, Sortierung und Pagination auch spezifische Anforderungen wie Lizenz- und Supplier-Filter sowie Geo- und Zeitabfragen. Die vollständige Spezifikation der Schnittstelle ist im Anhang als maschinenlesbares Dokument (bct-middleware-openapi.yaml) enthalten und dient sowohl als verbindliche Dokumentation als auch als Grundlage für die automatische Generierung von Clients.
Technisch wird die API über ein API-Gateway (z. B. Kong oder ein vergleichbarer Anbieter) bereitgestellt, das hinter einer vorgelagerten Ingress- bzw. WAF-Schicht betrieben wird. Das Gateway bildet den einheitlichen Zugangspunkt für alle Konsumenten der BayernCloud Tourismus - darunter Widgets (Los 4), das DMS-Frontend (Los 3) sowie externe Partner. Als primärer Standard wird REST unterstützt; optional steht zusätzlich eine GraphQL-Schnittstelle zur Verfügung, die insbesondere Partnern mit komplexeren Abfragebedarfen eine flexible Integration ermöglicht.
Das Gateway übernimmt zugleich zentrale Sicherheits- und Steuerungsfunktionen. Dazu zählen die Validierung von JWT/OIDC-Tokens, die vom lokalen Identity Provider ausgestellt oder über externe Provider gebrokert werden, sowie die Durchsetzung übergreifender Policies. Hierzu gehören Maßnahmen wie Rate-Limits und Throttling, die Absicherung durch CORS- und Header-Management, aber auch die Lizenz- und Zugriffskontrolle, die auf den im Token enthaltenen Claims basiert.
Die Schnittstellendefinition erfolgt einerseits über die OpenAPI-Spezifikation sämtlicher REST-Endpunkte, andererseits über ein GraphQL-Schema, das für ausgewählte Szenarien - etwa die flexible Integration von Partnern - bereitgestellt wird. Ergänzt wird das Angebot durch ein zentrales Developer Portal, das API-Dokumentationen, Beispielanfragen sowie Möglichkeiten zum Token-Erhalt bündelt und so eine effiziente Nutzung der Middleware unterstützt.
Aus diesem Aufbau ergeben sich mehrere Vorteile: Durch den einheitlichen Zugangspunkt werden alle BCT-Daten konsistent ausgeliefert. Die Sicherheit wird durch zentrale Token-Validierung, Rate-Limits und WAF-Regeln gewährleistet. Gleichzeitig bleibt die Lösung flexibel, indem sie einerseits REST als Standard für klassische Integrationen anbietet, andererseits aber mit GraphQL auch spezialisierte Anwendungsfälle unterstützt. Schließlich sorgt die Kombination aus OpenAPI-Spezifikation, GraphQL-Schema und Developer Portal für Transparenz und eine umfassend dokumentierte Schnittstellenlandschaft.
Datenformate & Datenmodell
JSON-LD als Standard-Format
Die Middleware setzt durchgängig auf JSON-LD im @graph-Format als Standard für die Datenhaltung und -bereitstellung. Jedes JSON-LD-Objekt wird dabei als eigenständiges Dokument in den jeweiligen Index geschrieben. Das vollständige JSON-LD bleibt im _source-Attribut unverändert erhalten, sodass die gesamte Originalstruktur verfügbar bleibt. Für eine performante Abfrage werden jedoch zusätzlich ausgewählte Attribute materialisiert, zu diesen gehören:
- allgemeine Merkmale wie
type,licenseundcategory[], - suchrelevante Felder wie
nameunddescriptionmit sprachspezifischen Analyzern für Deutsch und Englisch, - geobasierte Strukturen wie
geo_pointundgeo_shape, - zeitbezogene Angaben wie
startDate,endDateoderopenNow, - mediale Referenzen wie
url,mimeundaltinmedia[] - systemische Felder wie
source_revundlastUpdated.
Medien & Streams: Medien werden ausschließlich als Referenzen/URLs im JSON-LD geführt; die Middleware speichert oder streamt keine Binärdaten. Das gilt auch für Livestreams (z. B. Webcams/Skipisten): Es wird jeweils nur die Ziel-URL ausgeliefert; Abruf, Transkodierung und Verfügbarkeit liegen außerhalb von Los 1.
Index-Aufteilung nach Domänen
Um die unterschiedlichen Datenarten klar zu trennen und zugleich performant verarbeiten zu können, werden für jede Domäne separate Indizes angelegt, die über stabile Aliasse adressiert werden. Bei notwendigen Schemaänderungen erfolgt ein Blue/Green-Rollout über versionierte Indizes (z. B. -v1, -v2), sodass eine unterbrechungsfreie Migration möglich bleibt.
Beispiele für Aliasse und ihre typischen Inhalte sind:
| Alias | Typische Inhalte (@type aus Los 2) | Besonderheiten |
|---|---|---|
| bct-events | Event, Festival, Exhibition | Zeitfelder, GeoPoint, Lizenz, Kategorien |
| bct-places | Place, LocalBusiness, Accommodation, POI | GeoPoint, Adresse, Öffnungszeiten |
| bct-tours | Tour, Route, Lift, Piste | GeoShape (Linie/Polygon), Länge, Schwierigkeit |
| bct-areas | TouristDestination, ProtectedArea | GeoShape (Polygon), Klassifizierung |
| bct-messages | Message, OccupancyNotice, Alert | Zeitfenster, Dringlichkeit, Supplier |
| bct-sensors | Sensordaten (Parkplätze, Personenzähler, Messpunkte) | Zeitreihen, hohes Volumen, Rollover-Strategie |
Die Middleware ist auf die in Los 2 bereitgestellten Inhaltstypen (Events, POIs, Unterkünfte, Sensorikdaten etc.) ausgelegt. Da die Liste der unterstützten Typen dynamisch wächst (z. B. Assets, Audio/Video, Organisationen), ist das Datenmodell beliebig erweiterbar. Neue @type-Definitionen lassen sich ohne Schema-Brüche indexieren und über Aliasse zugänglich machen.
Das folgende Diagramm veranschaulicht die beschriebene Index-Struktur und zeigt die logische Aufteilung der Domänen sowie die Anbindung über Aliasse:
@startuml
!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Context.puml
title Elasticsearch - Index-Topologie
package "Domänen-Indizes (Blue/Green via Alias)" {
[Alias bct-events] as A1
[bct-events-v1] as E1
[bct-events-v2] as E2
A1 -[hidden]-> E1
A1 -[hidden]-> E2
note right of A1
Alias -> zeigt auf aktive Version
Zero-Downtime Switch
end note
[Alias bct-places] as A2
[bct-places-v1] as P1
}
A1 --> E2 : aktiv
A2 --> P1 : aktiv
package "Sensorik (Zeitreihe - Rollover/ISM)" {
[Alias bct-sensors] as S0
[bct-sensors-000001] as S1
[bct-sensors-000002] as S2
S0 --> S2 : aktuell
S0 ..> S1 : historisch
note right of S0
Rollover: Größe/Zeit
ILM/ISM: Hot->Warm->Delete
end note
}
@enduml
Zero-Downtime durch Index-Versionierung
Alle Indizes werden versioniert (z. B. bct-events-v2), während der Zugriff ausschließlich über die stabilen Aliasse (bct-events, bct-places etc.) erfolgt. Bei Änderungen am Mapping oder am Schema wird zunächst ein neuer Index mit den gewünschten Anpassungen erstellt, anschließend das vollständige Reindizieren der JSON-LD-Daten vorgenommen und die Ergebnisse validiert sowie getestet. Erst wenn alle Prüfungen erfolgreich sind, wird per Alias-Switch auf den neuen Index umgeschaltet - ein Vorgang, der sofort produktiv wirksam wird und ohne Downtime abläuft. Der alte Index wird im Anschluss archiviert oder gelöscht.
Sensorik-Daten (Zeitreihen)
Für hochfrequente Sensordaten, die in kurzen Intervallen bereitgestellt werden und besonders speicherintensiv sind, kommt ein Rollover-Mechanismus zum Einsatz. Der Alias bct-sensors verweist auf fortlaufend nummerierte Rollover-Indizes (z. B. bct-sensors-000001). Typische Felder in diesen Indizes sind sensorId, kind, ts, value, geo, meta und jsonld. Gesteuert wird der Datenlebenszyklus durch Index State Management (ISM): In der Hot-Phase verbleiben Daten bis zu einer Größe von 30 GB oder maximal sieben Tage, in der Warm-Phase bis zu 180 Tage. Nach einer Gesamtdauer von sechs Monaten werden die Datensätze automatisch gelöscht.
Vorteile des Ansatzes
Der gewählte Ansatz bietet eine Reihe von Vorteilen. Durch die Materialisierung zentraler Attribute sind Such- und Filteranfragen hoch performant. Gleichzeitig bleibt durch die Speicherung des vollständigen JSON-LD im _source maximale Flexibilität für Schemaänderungen und zukünftige Erweiterungen erhalten. Die klare Trennung der Indizes nach Domänen und die Rollover-Strategie für Sensordaten gewährleisten Skalierbarkeit auch bei wachsenden Datenvolumina. Darüber hinaus sorgen sprachspezifische Analyzer für eine verbesserte Suchqualität, während Geo- und Zeitabfragen nativ unterstützt werden. Schließlich trägt die Alias-Strategie maßgeblich zur Stabilität bei, indem sie Schema-Migrationen ohne Ausfallzeiten ermöglicht.
Filter- & Suchfunktionen
Alle API-Anfragen laufen über den Search Orchestrator, einen dedizierten Service der Middleware. Er übernimmt nach der Weiterleitung durch das API Gateway die fachliche Validierung der Abfragen (erlaubte Filter, Feldnamen, Sortierungen) sowie die Autorisierung anhand der im JWT enthaltenen Claims (z. B. Lizenzrechte Open/Closed Data). Anschließend übersetzt er die Anfragen in optimierte Elasticsearch-Queries, die Geo-, Zeit- und Policy-Filter direkt durch Elasticsearch ausführen lassen. Die Ergebnisse werden vom Orchestrator angereichert, in ein standardkonformes JSON-LD im @graph-Format transformiert und an den Aufrufer zurückgegeben.
Um eine gleichbleibend hohe Performance und einen stabilen Betrieb sicherzustellen, sind mehrere technische Maßnahmen vorgesehen:
- Materialisierte Felder: gezielte Extraktion kritischer Attribute (Geo, Zeit, Kategorien, Lizenz) für schnelle Abfragen, während das vollständige JSON-LD im _source erhalten bleibt.
- Caching: Query-Caching in Elasticsearch für stark frequentierte Datensätze.
- Paging & Limitierung: deterministische Sortierung und effiziente Paginierung sichern konstante Antwortqualität auch bei großem Datenvolumen.
- Mehrsprachige Volltextsuche: spezialisierte Analyzer-Pipelines für Deutsch und Englisch.
- Geo- & Zeitabfragen: native Unterstützung durch Elasticsearch für Punkt-, Radius- und Polygonabfragen sowie Zeitfenster (z. B. Events, Meldungen).
Datenbezug & Synchronisation (Schnittstelle zu Los 2)
Die Übernahme der von Los 2 bereitgestellten Inhalte in die Middleware erfolgt über einen dedizierten ETL- bzw. Intake-Service. Seine Aufgabe besteht darin, die gelieferten Daten zuverlässig, konsistent und performant in die Such- und Abfrageschicht von Los 1 zu integrieren. Los 2 stellt die Daten über eine OpenAPI-konforme REST-Schnittstelle im JSON-LD-@graph-Format bereit. Nach der derzeitigen Spezifikation ist diese Schnittstelle ausschließlich als Pull-Mechanismus ausgelegt: Die Middleware ruft die Inhalte in periodischen Intervallen ab, in der Regel als vollständige, paginierte Datensätze. Ein natives Verfahren zur Bereitstellung von Deltas oder Änderungsinformationen ist in den aktuellen Leistungsbeschreibungen nicht vorgesehen.
Der Intake-Service deckt zwei zentrale Einsatzszenarien ab: Zum einen führt er initiale Vollabgleiche durch, bei denen sämtliche Inhalte von Los 2 abgerufen und in Elasticsearch indiziert werden. Zum anderen übernimmt er die laufende Synchronisation, die ebenfalls auf Pull-Basis erfolgt. Alle eingehenden Datensätze werden dabei validiert und normalisiert, sodass sowohl das vollständige JSON-LD im _source erhalten bleibt als auch gezielt materialisierte Felder für performante Abfragen zur Verfügung stehen. Für die Indexierung wird eine idempotente Upsert-Strategie eingesetzt, die unnötige Re-Indizierungen vermeidet und die Konsistenz der Datenbestände sicherstellt.
Da Pull-basierte Vollabgleiche zu erheblichen Datenmengen und vermeidbarer Last führen können, empfiehlt sich eine perspektivische Erweiterung der Schnittstelle um effizientere Mechanismen. Besonders wertvoll wären Delta-Endpunkte, die ausschließlich geänderte oder neue Datensätze bereitstellen, oder alternativ Push-Signale in Form von Webhooks, mit denen Los 2 Änderungen direkt an Los 1 signalisiert. Solche Verfahren würden den Synchronisationsprozess beschleunigen, die Netzwerklast reduzieren und zugleich die Betriebskosten auf beiden Seiten verringern, ohne den Grundsatz der JSON-LD-basierten Datenhaltung in Frage zu stellen.
Bereits heute stellt die DataCycle-Instanz von Los 2 die Filter created_since und modified_since bereit. Der Intake-Service von Los 1 nutzt diese Mechanismen, um Synchronisationen effizienter zu gestalten. Perspektivisch kann dies durch Webhooks ergänzt werden, die Änderungen direkt signalisieren.
Der Intake-Service ist damit die zentrale Brücke zwischen Los 2 und der Middleware. Er sorgt dafür, dass die Inhalte vollständig, konsistent und in geeigneter Form für die nachgelagerten Such- und API-Funktionen bereitstehen, und schafft zugleich die Grundlage für künftige Erweiterungen in Richtung effizienterer Synchronisationsverfahren.
Das folgende Diagramm visualisiert den beschriebenen Datenbezug:
@startuml
title Schnittstelle Los 2 → Los 1 (ETL, Indexierung, Alias-Switch)
!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Container.puml
actor "Scheduler" as sched
participant "ETL / Intake\n(Los 1)" as etl
participant "Los 2 API\n(JSON-LD @graph)" as l2
participant "Elasticsearch\n(Index-Cluster)" as os
== Periodischer PUll (Vollabzug) ==
sched -> etl : Start Initial-Sync (Domain-basiert)
etl -> l2 : GET /resources?page[size]=N\n(Headers: API-Key, TLS)
l2 --> etl : 200 @graph + links.next
etl -> etl : Validieren, Normalisieren/Flatten\nMaterialisierte Felder extrahieren
etl -> os : Bulk Upsert (_source=JSON-LD,\nmaterialisierte Felder)
loop solange links.next vorhanden
etl -> l2 : GET next
l2 --> etl : 200 @graph + links.next
etl -> os : Bulk Upsert (weiterer Batch)
end
etl -> os : Optional: Aufbau neuer Indexversion ...-v(N+1)
etl -> os : Validierung/Checks (Sample-Queries)
etl -> os : Alias-Switch (Blue/Green):\n[bct-*-alias] → ...-v(N+1)
@endumlDie Verarbeitung der Daten erfolgt entlang einer klar strukturierten Pipeline. Eingehende Datensätze werden zunächst normalisiert und validiert, um sicherzustellen, dass sie vollständig und schema.org/ODTA-konform sind. Im nächsten Schritt erfolgt ein Flattening und eine Transformation, bei der relevante Attribute extrahiert und mit zusätzlichen Metadaten wie Supplier-Informationen oder Lizenzangaben angereichert werden. Anschließend werden die Inhalte über eine optimierte Bulk-Indexierung in Elasticsearch übernommen, wodurch Ladeprozesse effizient und Reindexing-Latenzen minimal gehalten werden. Über Hash- oder Versionsfelder werden No-Op-Upserts erkannt, sodass unnötige Indexoperationen vermieden werden.
Technisch wird die Lösung als containerisierter Microservice umgesetzt. Sie umfasst Kubernetes-Deployments für kontinuierlich laufende Prozesse sowie CronJobs für periodische Batchläufe. Die Orchestrierung und das Monitoring erfolgen über Kubernetes in Verbindung mit GitOps, wodurch eine transparente Steuerung und Nachvollziehbarkeit sichergestellt ist. Abhängig vom Datenvolumen kann die Verarbeitung durch parallelisierte ETL-Pipelines skaliert werden.
Der Schnittstellenstandard bleibt dabei durchgängig gewahrt: Alle Daten werden im JSON-LD-@graph-Format verarbeitet, wie in Los 2 spezifiziert. Das vollständige JSON-LD wird im Index im _source gespeichert, um maximale Nachvollziehbarkeit und Zukunftssicherheit zu gewährleisten. Gleichzeitig werden die relevanten Such- und Filterfelder materialisiert, sodass die Abfrageperformance auch bei steigenden Datenvolumina konstant hoch bleibt.
Schnittstellen zu Los 3 und Los 4
Die Middleware ist eng mit den angrenzenden Losen 3 und 4 verzahnt und übernimmt dabei eine klare Vermittlerrolle zwischen Governance und Datenkonsum.
Im Zusammenspiel mit Los 3 (Policy/Governance) wird die zentrale Lizenzlogik umgesetzt. Die Unterscheidung zwischen offenen und geschützten Inhalten (Open vs. Closed Data) erfolgt serverseitig auf Grundlage der im JWT enthaltenen Claims. Darüber hinaus werden regionale oder feingranulare Zugriffsregeln - beispielsweise über Coverage-IDs - durch die Governance definiert und über eine Policy-Lookup-API in die Middleware eingebunden. Auf diese Weise stellt die Middleware sicher, dass alle von Los 3 administrierten Regeln konsequent und automatisiert bei der Datenbereitstellung durchgesetzt werden.
Gegenüber Los 4 (Widgets/Clients) fungiert die Middleware als zentraler Zugangspunkt zu den touristischen Daten. Widgets konsumieren die Schnittstellen direkt und profitieren dabei von stabilen Endpunkten, performanten Filtermöglichkeiten sowie einer deterministischen Sortierung und Paging-Strategie. Komplexe Abfragelogik bleibt vollständig auf der Serverseite, im Search Orchestrator, verankert. Dadurch werden die Widgets erheblich entlastet und können sich auf ihre primäre Aufgabe - die Visualisierung und Ausspielung der Daten - konzentrieren, ohne selbst komplexe Datenlogik implementieren zu müssen.
2. Technische Anforderungen (ohne Hosting)
(wie die Funktionalität applikationsseitig technisch umgesetzt wird)
Die Middleware stellt die zentrale Zugriffsschicht für die strukturierte Bereitstellung touristischer Inhalte dar. Sie wird als read-only API gemäß dem OpenAPI-Standard umgesetzt und kann optional auch über eine GraphQL-Schnittstelle angesprochen werden. Als standardisiertes Datenformat kommt JSON-LD zum Einsatz, wobei die Inhalte in einer @graph-Struktur gemäß schema.org und ODTA abgebildet werden. Dieses Format ist nicht nur maschinenlesbar, sondern erlaubt auch semantisch reichhaltige Darstellungen, die sich gut in bestehende touristische Datenökosysteme einfügen.
Im Fokus dieses Loses stehen nicht Hosting oder Infrastruktur, sondern die fachlich-technische Konzeption der API: insbesondere das Schnittstellendesign, das zugrunde liegende Datenmodell sowie die Filter- und Policy-Strategien. Ergänzend werden auch Aspekte wie Sicherheitsanforderungen auf Applikationsebene, Observability (inkl. Logging, Tracing, Metriken) sowie Maßnahmen zur Sicherung von Qualität und Developer Experience beschrieben.
Die Middleware ist funktional in eine übergreifende Systemlandschaft eingebettet und steht in definierten Beziehungen zu den anderen Losen:
- Los 2 (Datenintegration) liefert die zu veröffentlichenden Inhalte als bereits validierte JSON-LD-Objekte. Diese enthalten explizit gesetzte Angaben zu Lizenztyp (
openoderclosed) sowie zur regionalen Gültigkeit (Coverage, als Identifier oder Polygon). - Los 3 (DMS-Frontend) stellt die Governance sicher. Es verwaltet organisatorische Zuständigkeiten, Rechte und Policies - z. B. welche Inhalte in welchen Regionen als „closed“ freigegeben sind.
- Los 4 (Widgets/Clients) konsumiert die Middleware direkt. Für diese Nutzergruppe sind insbesondere stabile Schnittstellen, performante Filter und effiziente Caching-Mechanismen entscheidend.
Architekturprinzipien
Die Middleware folgt einem API-zentrierten, Headless-Ansatz. Die REST-Schnittstelle wird auf Basis von OpenAPI 3 definiert und bildet den primären Zugangspunkt. Optional kann sie durch eine GraphQL-Schnittstelle ergänzt werden, die ebenfalls ausschließlich lesend ist. Persisted Queries sowie Kosten- und Tiefenlimits sorgen dabei für Sicherheit und Planbarkeit.
Die Architektur ist modular im Microservice-Stil aufgebaut. Kernfunktionen wie Authentifizierung, Policy-Enforcement, Filterung, Logging und Caching werden jeweils als eigenständige, skalierbare Services konzipiert. Diese Trennung fördert nicht nur Wartbarkeit und Testbarkeit, sondern erlaubt auch eine gezielte Skalierung bei Lastspitzen.
Eine zentrale Entwurfsentscheidung betrifft den Umgang mit Caching: Dieser erfolgt technologieoffen, d. h. die konkrete Implementierung ist nicht vorgegeben. Vorgesehen sind z. B. in-memory-Caches, HTTP/Gateway-Caches oder optimierte Datenhaltung im Suchindex - nicht jedoch zentrale Schlüssel-Wert-Stores wie Redis. Diese Entscheidung reduziert Komplexität, minimiert Betriebsrisiken und erleichtert Hochverfügbarkeit ohne Single Points of Failure.
Die Inhalte selbst liegen in einer JSON-LD-basierten _source-Struktur vor, die alle Originaldaten enthält. Zusätzlich werden für such- und filterrelevante Felder (z. B. Geo-Koordinaten, Startdatum, CoverageId) materialisierte Kopien erzeugt, die eine performante Indexierung und Filterung ermöglichen.
Die Durchsetzung von Lizenz- und Geo-Policies erfolgt ausschließlich serverseitig . Dies verhindert, dass Clients durch eigene Modifikationen oder Umgehungen Zugriff auf geschützte Inhalte erhalten. Die Middleware agiert in diesem Punkt als Gatekeeper und berücksichtigt alle Policies bei der Anfrageverarbeitung automatisch.
Weitere zentrale Prinzipien betreffen die Versionierung und Abwärtskompatibilität (z. B. durch semantische Versionen, Sunset-Header und Deprecation-Strategien), die konsequente Umsetzung von Security-by-Default (z. B. „deny by default“, OIDC, kurze TTLs, Scope-Minimierung, Input-Validierung) sowie die Integration umfassender Observability-Mechanismen (Tracing, strukturierte Logs, Fehlerklassifikation nach Problem+JSON).
API-Strategie und Schnittstellenkontrakte
Die Middleware bietet ihre Inhalte standardmäßig als REST-API unter versionierten Endpunkten wie /v1/events oder /v1/places an. Die Antworten werden im Format application/ld+json bereitgestellt. Optional steht auch ein GraphQL-Zugang zur Verfügung. Hier gelten dieselben Freigabe- und Filterregeln wie bei REST, ergänzt durch Maßnahmen wie Persisted Queries und maximale Tiefenbeschränkungen.
Fehlermeldungen orientieren sich an RFC 9457 (Problem+JSON) und enthalten u. a. strukturierte Informationen zur Ursache sowie eine traceId zur korrelierten Analyse im Tracing.
Zugriffskontrolle für Open und Closed Data
Ein zentrales Merkmal der Middleware ist die differenzierte Behandlung von offenen und geschützten Inhalten („Open Data“ vs. „Closed Data“). Während offene Daten uneingeschränkt für alle zugänglich sind, unterliegt der Zugriff auf geschützte Inhalte einer zweistufigen Kontrolle:
- Berechtigung durch Rolle - nur Clients mit entsprechender Autorisierung (
bct.read.closed) dürfen Closed Data grundsätzlich abrufen. - Regionale Freigabe - selbst berechtigte Clients dürfen Closed Data nur für Regionen einsehen, für die sie gemäß Los 3 autorisiert sind.
Diese Trennung ist bewusst gewählt: Sie verhindert, dass z. B. ein Widget in Niederbayern Closed Events aus Oberbayern sieht, nur weil es eine technisch passende Suchanfrage gestellt hat. Policies gelten hier nicht als Suchfilter, sondern
Umsetzung der Zugriffskontrolle
Technisch erfolgt die Umsetzung in mehreren Schritten:
- Jeder Datensatz enthält die beiden Attribute
license(open/closed) undcoverageId(z. B.region:oberbayern). Diese werden bereits beim Ingest (Los 2) gesetzt und durch das DMS (Los 3) administriert. - Das vom Identity Provider ausgestellte JWT enthält nur die Claims
client_idund - falls autorisiert -bct.read.closed. Es enthält keine Regionsinformationen, da diese dynamisch gepflegt werden und nicht im Token verankert sein sollen. - Die Middleware fragt beim Policy-Service (oder direkt bei Los 3) zur Laufzeit die zulässigen Coverage-IDs für die gegebene Client-ID ab. Diese dürfen zur Performanceverbesserung lokal im API-Service temporär gecacht werden - z. B. als In-Memory-Cache pro Instanz oder Gateway-naher Cache.
- Basierend auf diesen Informationen ergänzt die Middleware jede Abfrage automatisch durch ein serverseitiges Filterkriterium:
(license = "open")
OR (license = "closed"
AND "bct.read.closed" ∈ jwt.scopes
AND coverageId ∈ getAllowedCoverageIds(client))Zusätzlich zu den CoverageIDs können Freigaben räumlich differenziert erfolgen. Dabei werden nicht nur einfache Regionen-IDs berücksichtigt, sondern auch komplexere Geoshapes wie Polygone (z. B. Landkreise, Destinationen) oder Linien (z. B. Routen, Touren). Diese Geometrien werden in Los 3 gepflegt und von der Middleware beim Policy-Lookup berücksichtigt. Dadurch ist es möglich, Zugriffsrechte granular auf bestimmte Gebiete oder Strecken zu beschränken, ohne dass Clients selbst komplexe Geo-Filterlogik implementieren müssen.
Diese Logik stellt sicher, dass keine nicht freigegebenen Inhalte ausgeliefert werden - unabhängig davon, wie eine Clientanfrage aussieht. Fachliche Filter (z. B. Zeitfenster, Volltext, Geo-Umkreis) wirken zusätzlich, ohne jedoch die Freigabelogik zu verändern. Um unnötige Policy-Requests zu vermeiden, werden Coverage-IDs pro Client temporär im In-Memory-Cache gehalten. Eine maximale TTL von 5-15 Minuten wird empfohlen.
Die Architektur bietet mehrere Vorteile:
- Ein klarer Schutzmechanismus für geschützte Inhalte - Clients sehen nur, was sie sehen dürfen.
- Die Governance bleibt zentral steuerbar - Rollen- und Regionszuordnungen werden ausschließlich in Los 3 gepflegt.
- Die Integration mit Widgets (Los 4) ist besonders elegant: Clients erhalten automatisch die für sie relevanten Daten, ohne komplexe Filterlogik implementieren zu müssen.
Sicherheit & Authentifizierung
Die Middleware folgt einem klar definierten und strikten Sicherheitsmodell, das den Schutz sensibler Daten ebenso berücksichtigt wie die Integrität der gesamten Plattform. Grundlage ist ein auf OpenID Connect (OIDC) basierender Authentifizierungs- und Autorisierungsmechanismus mit JWT-Tokens, die kurze Gültigkeitsdauern besitzen und ausschließlich die minimal notwendigen Scopes enthalten. Auf diese Weise wird das Prinzip der Rechte-Minimierung konsequent umgesetzt. Sämtliche Eingaben an die API werden nach den Vorgaben der OpenAPI-Spezifikation validiert. Parametergrenzen, Timeouts und Grenzwerte dienen als zusätzliche Schutzmaßnahmen gegen Missbrauch oder unerwünschte Lastspitzen. Auch die Ausgaben sind gehärtet: Sie folgen einem deterministischen Paging- und Sortiermodell und geben keine internen Fehler oder Stacktraces preis.
Da der Auftraggeber aktuell keinen zentralen Authentifizierungsdienst bereitstellt, wird der Identity Provider (z. B. Keycloak) vom Bieter im Rahmen von Los 1 bereitgestellt und betrieben. Der IdP ist losübergreifend nutzbar und unterstützt Standards wie OIDC/OAuth2 und optional SAML 2.0. Über einen Identity Broker ist zudem die Föderation mit externen Identity Providern - beispielsweise aus Los 2 - möglich. Damit wird eine nahtlose Integration verschiedener Authentifizierungsquellen unterstützt. Neben OIDC können auch etablierte Standards wie SAML 2.0 eingesetzt werden, wodurch Interoperabilität mit bestehenden Systemen gewährleistet ist.
Auf Funktionsebene stellt die Middleware ein einheitliches Single Sign-On (SSO) für alle BCT-Komponenten und angeschlossenen Partnerdienste bereit. Die Validierung von JWTs erfolgt direkt im vorgeschalteten API Gateway (z. B. Kong oder ein vergleichbarer Anbieter). Die differenzierte Rechtevergabe wird über rollen- und attributbasierte Zugriffskontrollmechanismen (RBAC/ABAC) umgesetzt, sodass beispielsweise zwischen offenen Daten („nur offene Daten“) und geschützten Partnerdaten differenziert werden kann. Ergänzend lassen sich feingranulare Policies - etwa zur Lizenzlogik oder zu Ratenbegrenzungen - durchsetzen.
Darüber hinaus werden umfassende Schutzmaßnahmen implementiert. Sämtliche Datenübertragungen sind durch Transportverschlüsselung mit TLS 1.3 abgesichert. Das API Gateway übernimmt zusätzliche Sicherheitsfunktionen und fungiert zugleich als WAF-Ersatz mit Mechanismen wie Rate Limits, IP-Blocklisten oder Geo-Filterung. Schließlich wird eine durchgängige Sicherheitsüberwachung gewährleistet: Alle relevanten Security-Events, darunter Logins, Tokenverwendungen oder Policy-Verstöße, werden zentral protokolliert, überwacht und können für Auswertungen oder Audits herangezogen werden.
Hinweis zu Assets: API-Antworten enthalten für Medien (inkl. Livestreams) ausschließlich Metadaten und Verweise; ein Proxy/Rewrite oder Durchleitung von Binärinhalten ist in Los 1 nicht vorgesehen.
Stabilität & Verfügbarkeit (applikationsseitig)
Die Middleware ist auf einen hochstabilen und fehlertoleranten Betrieb ausgelegt. Alle zentralen Komponenten - insbesondere die API-Services sowie der Elasticsearch-Suchcluster - laufen in hochverfügbaren Kubernetes-Clustern. Zur Absicherung auf Infrastrukturebene werden Azure Managed Disks und Verfügbarkeitszonen eingesetzt, sodass auch bei Hardware- oder Standortausfällen eine kontinuierliche Verfügbarkeit gewährleistet ist. Der Elasticsearch-Cluster selbst besteht aus mehreren Data- und Master-Nodes, was Konsistenz, Fehlertoleranz und eine automatische Replikation sicherstellt.
Die Bereitstellung und der Betrieb folgen modernen DevOps-Prinzipien. Rollouts und Konfigurationsänderungen werden über GitOps-Mechanismen (FluxCD) gesteuert. Dadurch sind sämtliche Änderungen nachvollziehbar, versioniert und auditierbar. Updates erfolgen nach dem Blue/Green-Prinzip, sowohl bei den API-Services als auch bei den Elasticsearch-Indizes, was eine unterbrechungsfreie Bereitstellung sicherstellt. Ergänzend kommt Infrastructure as Code (z. B. Terraform, Helm, Kustomize) zum Einsatz, wodurch Umgebungen reproduzierbar bereitgestellt werden können.
Zur Sicherstellung der Stabilität sind mehrere Strategien implementiert. Automatisches Failover garantiert, dass bei einem Knotenausfall sofort ein replizierter Pod oder Datenknoten übernimmt. Durch die Self-Healing-Funktionalitäten von Kubernetes werden Pod- oder Node-Ausfälle automatisch erkannt und betroffene Workloads neu gestartet. Lastspitzen können dynamisch durch horizontales Skalieren (Horizontal Pod Autoscaler, HPA) abgefangen werden. Für Sensorik-Daten, die typischerweise ein hohes Volumen aufweisen, sorgt ein Index State Management (ISM) dafür, dass unkontrolliertes Wachstum verhindert wird und die Query-Performance langfristig stabil bleibt.
Die Überwachung des Gesamtsystems erfolgt über eine vollständige Integration in einen modernen Observability-Stack, bestehend aus Prometheus, Grafana und OpenTelemetry. Health Checks auf API- und Datenebene stellen die laufende Funktionsfähigkeit sicher. Darüber hinaus werden proaktive Alerts definiert, die bei Auffälligkeiten wie erhöhten Fehler- oder Latenzraten automatisch ausgelöst werden, sodass Probleme frühzeitig erkannt und behoben werden können.
Monitoring & Observability (applikationsseitig)
Die Middleware ist von Beginn an auf vollständige Beobachtbarkeit ausgelegt. Sie erfasst Metriken zu Latenzen, Fehlerraten, Cache-Treffern und Query-Dauer, sodass sowohl technische als auch fachliche Leistungskennzahlen jederzeit transparent verfügbar sind. Für die verteilte Nachvollziehbarkeit von Anfragen werden Traces nach dem W3C TraceContext-Standard eingesetzt, die über alle beteiligten Komponenten hinweg korreliert werden können. Fehlerfälle werden konsequent als Problem+JSON zurückgegeben und enthalten eine eindeutige Trace-ID, die eine direkte Verknüpfung zu Logs und Metriken ermöglicht.
Ein besonderes Augenmerk liegt auf der Differenzierung zwischen verschiedenen Cache-Ebenen: Während Edge- und HTTP-Caches für die performante Auslieferung öffentlicher Daten genutzt werden, dienen interne Caches - etwa policy-bezogene Lookup-Caches - der Beschleunigung von Berechtigungsprüfungen.
Für die Auslieferung neuer Versionen oder Konfigurationsänderungen kommen GitOps-Mechanismen (FluxCD) zum Einsatz, wodurch Änderungen versioniert, auditierbar und jederzeit reproduzierbar bleiben. Blue/Green-Deployments ermöglichen Updates der API-Services sowie der Elasticsearch-Indizes ohne Ausfallzeiten. Ergänzend wird die Infrastruktur mit Infrastructure as Code (z. B. Terraform, Helm, Kustomize) verwaltet, sodass Umgebungen reproduzierbar und standardisiert aufgesetzt werden können.
Zur Stabilität tragen mehrere Mechanismen bei: Automatisches Failover stellt sicher, dass bei Knotenausfällen replizierte Pods oder Datenknoten nahtlos übernehmen. Kubernetes sorgt mit Self-Healing dafür, dass CrashLoop-, Node- oder Pod-Ausfälle automatisch erkannt und neu gestartet werden. Zusätzlich werden API-Services durch horizontale Skalierung (HPA) dynamisch an Lastspitzen angepasst. Für Sensordaten verhindert ein Index State Management (ISM) unkontrolliertes Wachstum und sichert dauerhaft eine stabile Query-Performance.
Die Überwachung des Gesamtsystems erfolgt durch die vollständige Integration in einen modernen Observability-Stack mit Prometheus, Grafana und OpenTelemetry. Health Checks auf API- und Datenebene gewährleisten die kontinuierliche Funktionsfähigkeit, während proaktive Alerts bei Auffälligkeiten - etwa ungewöhnlich hoher Fehler- oder Latenzraten - automatisch ausgelöst werden. Damit wird ein frühzeitiges Eingreifen ermöglicht, noch bevor es zu spürbaren Einschränkungen für die Nutzer kommt.
Serializer-Service (optional bei GraphQL-Erweiterung)
Für den Fall, dass neben der REST-API auch eine GraphQL-Schnittstelle bereitgestellt werden soll, ist die Einführung eines dedizierten Serializer-Services vorgesehen. Dieser übernimmt die Transformation der Suchergebnisse in das standardisierte JSON-LD-Format im @graph-Stil und stellt sicher, dass alle ausgelieferten Inhalte schema.org- sowie ODTA-konform strukturiert sind.
Der Serializer-Service wird modular als Microservice auf Basis von Spring Boot und Kotlin realisiert. Er kann flexibel in die Architektur integriert werden, ohne bestehende Komponenten zu verändern. Seine Hauptfunktionen sind:
- Konvertierung von Elasticsearch-Ergebnissen in valides JSON-LD mit eingebettetem
@context, - Fehlerausgabe nach RFC 9457 (Problem+JSON),
- Unterstützung von Sparse Fieldsets zur selektiven Feldreduktion,
- dynamische Sprachauswahl über
lang=de|en.
Die Notwendigkeit und Wirtschaftlichkeit einer solchen Komponente hängt maßgeblich vom tatsächlichen Bedarf an GraphQL-Unterstützung ab. Bei einer reinen REST-Nutzung kann die Serialisierung effizient im API-Service bzw. im Search Orchestrator erfolgen, sodass keine zusätzliche Service-Schicht und Latenz erforderlich ist. Sollte die Umsetzung von GraphQL beauftragt werden, kann der Serializer gezielt aktiviert oder ausgebaut werden - ohne Anpassungen an bestehenden Services.
Caching-Konzept
Die Middleware nutzt ein mehrstufiges, komponentenspezifisches Caching-Konzept, um Antwortzeiten zu optimieren, Lastspitzen abzufangen und den Betrieb effizient zu gestalten. Dabei gilt der Grundsatz: Es wird ausschließlich Open Data gecacht - Inhalte mit Zugriffsbeschränkung (Closed Data) unterliegen grundsätzlich keiner externen oder persistierenden Zwischenspeicherung.
Cache-Ebenen und Speicherorte
| Ebene | Komponente | Typ | Zweck |
|---|---|---|---|
| Edge-/Gateway-Cache | CDN, API-Gateway, WAF | HTTP-Cache, ETag, TTL | Entlastung des API-Backends für GET auf Open Data |
| Elasticsearch | Query-Caching | internes Query-Result-Cache | Performance bei wiederholten Abfragen |
| In-Memory-Caches | API- & Policy-Service | pro Instanz, TTL-basiert | Policy-Ergebnisse (z. B. Coverage-IDs), Token-Scopes |
| Client-seitig | Widgets, externe Integrationen | Browser-/Client-Cache (optional) | Nur für Open Data, steuerbar via Cache-Control |
Cachebarkeit
Die Entscheidung darüber, welche Inhalte überhaupt gecacht werden dürfen, richtet sich strikt nach ihrer Lizenzierung. Es werden ausschließlich Inhalte mit license=open in den Cache aufgenommen. Diese Einschränkung wird konsequent serverseitig erzwungen (policy-keyed Caching). Eine versehentliche Auslieferung von Closed Data aus Caches ist dadurch ausgeschlossen.
Für geschützte Inhalte (Closed Data) ist Caching auf HTTP-/Transportebene explizit deaktiviert. API-Gateway und WAF kontrollieren die Header Cache-Control, Vary, Authorization und Surrogate-Key, um eine Cache-Umgehung zuverlässig zu verhindern.
Cache-Dauer und Steuerung
Die Cache-Dauer ist abhängig von der jeweiligen Ebene innerhalb der Architektur:
- Edge-/Gateway-Cache: TTL typischerweise maximal 15 Minuten, abhängig vom Inhaltstyp (z. B. Events vs. Destinations)
- Elasticsearch Query Cache: Laufzeit gesteuert durch Elasticsearch selbst (RAM-basiert, LRU-Eviction)
- In-Memory-Caches: TTL in der Regel 1-5 Minuten (konfigurierbar), keine Persistenz
- Client-Cache: Steuerbar über
Cache-Control-Header, aber nur für explizit freigegebene Ressourcen
Bei sensiblen Inhalten (z. B. Lizenzwechsel, Regionsfreigaben) kann die Cache-Dauer auf 0 gesetzt und eine Revalidierung erzwungen werden.
Für hochfrequente Sensorikdaten mit 5-Minuten-Zyklus wird kein Stale-Caching zugelassen; diese Inhalte werden stets frisch aus dem Index geliefert. Edge-/Gateway-Caches werden hier explizit umgangen. Für statische Open-Data-Inhalte (z. B. Destinationsprofile) sind dagegen längere TTLs bis zu 15 Minuten möglich.
Konsistenz & Invalidierung
Um Inkonsistenzen zwischen gecachten und aktuellen Inhalten zu vermeiden, kommen folgende Maßnahmen zum Einsatz:
- Policy-Keyed Caching: Der Cache-Key basiert auf den geltenden Zugriffspolicies (z. B.
license=open), wodurch sichergestellt wird, dass nur zulässige Inhalte zwischengespeichert werden. - Soft Expiry + Revalidierung: Im Gateway kann ein Stale-While-Revalidate-Verfahren aktiviert werden, das veraltete Inhalte bei Bedarf automatisch aktualisiert.
- Index-Alias-Switching: Bei Datenmigrationen (z. B. bct-places-v2) bleiben die Aliasse konstant, sodass keine Cache-Invalidierung notwendig ist.
- Low TTL bei Policy-Daten: Policy-bezogene In-Memory-Caches (z. B. Coverage-IDs pro Client) haben kurze Lebensdauern und werden regelmäßig automatisch erneuert.
- Keine Cross-Tenant-Caches: Alle Caches sind strikt Mandanten- und Nutzerkontext-bezogen (z. B. per client_id, license), um Datenlecks zu verhindern.
Developer Experience
Entwickler profitieren von einer klaren Versionierung, gut dokumentierten Schnittstellen (Swagger/Redoc), einem standardisierten Fehlerkatalog sowie klaren Migrationshinweisen. Die Deprecation-Strategie folgt etablierten Verfahren (z. B. Sunset-Header, parallel verfügbare Versionen) und ermöglicht eine planbare API-Nutzung.
Zusammenfassung
Die Middleware von Los 1 bildet die zentrale Zugriffsschicht für offene und geschützte touristische Inhalte. Sie setzt die übergreifende Daten- und Governance-Logik konsequent um, ist klar getrennt in ihren Verantwortlichkeiten und in hohem Maße interoperabel mit den angrenzenden Losen 2 (Ingest), 3 (Governance) und 4 (Widgets).
Durch ihren modernen, API-zentrierten Aufbau, das robuste Sicherheitsmodell und die klare Policy-Architektur schafft sie eine stabile, skalierbare und nachvollziehbare Grundlage für die touristische Dateninfrastruktur.
Die folgende Architekturskizze visualisiert die zentralen Komponenten der Middleware (Los 1) sowie deren Einbettung in die angrenzenden Lose. Sie verdeutlicht insbesondere den API-zentrierten Aufbau, die Trennung von Policy- und Filterlogik, die serverseitige Durchsetzung der Freigaberegeln sowie die Integration von Identity Provider, Datenquelle (Los 2), Governance-Backend (Los 3) und den konsumierenden Clients (Los 4).
@startuml
!include <C4/C4_Container>
LAYOUT_LEFT_RIGHT()
together {
Person(consumer, "Datenkonsumenten", "Widgets/Apps/Portale (Los 4)")
Person(admin, "Fachadmin (Los 3)", "Pflegt Policies/Governance")
}
System_Boundary(bct, "BCT - Los 1 Middleware") {
Container(api_gw, "API Gateway", "logical", "JWT-Check, WAF, Rate-Limits, Edge-Cache")
Container(api, "API Service", "logical", "REST (OpenAPI), optional GraphQL, Read-only")
Container(policy, "Policy Layer", "logical", "Lizenz- & Geo-Enforcement (embedded oder OPA/ABAC)")
Container(cache, "In-Memory Cache", "logical", "temporäre Policy Lookups (TTL-basiert)")
Container(serializer, "Serializer Service (optional)", "logical", "JSON-LD @graph-Ausgabe")
Container(index, "Elasticsearch Cluster", "logical", "JSON-LD _source, materialisierte Felder, ISM")
Container(obs, "Observability Hooks", "logical", "Traces, Metrics, Logs, Problem+JSON")
Container(secret, "Secrets / Config", "logical", "Kubernetes Secrets, Konfiguration, Key-Management")
}
System_Ext(idp, "Identity Provider", "OIDC/JWT", "Tokenausstellung (Scopes, client_id)")
System_Ext(los2, "Los 2 - Datenintegration", "liefert JSON-LD + license + coverageId")
System_Ext(los3, "Los 3 - DMS", "pflegt Policies/Rollen/Regionen")
System_Ext(los4, "Los 4 - Widgets", "nutzen die Endpunkte")
Rel(consumer, api_gw, "HTTPS + JWT")
Rel(api_gw, api, "forwarded requests")
Rel(api, cache, "lookup(client_id/policies)")
Rel(api, policy, "getEffectiveFilter(jwt, query) + enforce()")
Rel(policy, los3, "dynamischer Policy Lookup (Coverage-IDs, Rollen)")
Rel(policy, index, "execute(searchDSL with enforced filters)")
Rel(api, serializer, "optional response rendering")
Rel(serializer, consumer, "JSON-LD @graph")
Rel(api, obs, "Telemetry")
Rel(api, secret, "env/config (KMS, mounted)")
Rel(admin, los3, "Policy-Pflege/RBAC")
Rel(los2, index, "Indizierte Daten (JSON-LD)")
Rel(los4, api_gw, "Konsum")
Rel(idp, consumer, "Login/OAuth2/OIDC", "JWT")
Rel(idp, api_gw, "JWKS/Token-Validation Metadata")
Rel(api, idp, "JWT Validierung (aud/iss/kid)")
' Hinweisboxen
UpdateElementStyle(policy, $fontColor="black", $bgColor="#FFE9B3", $borderColor="#C8A95A")
UpdateElementStyle(index, $fontColor="black", $bgColor="#E5F3FF", $borderColor="#6CA5D9")
UpdateElementStyle(cache, $bgColor="#F1F1F1", $borderColor="#999999")
UpdateElementStyle(serializer, $bgColor="#EAEAFF", $borderColor="#8888FF")
UpdateElementStyle(secret, $bgColor="#FDF6E3", $borderColor="#CBBF8D")
@enduml
3. Technische Anforderungen (Hosting)
(wie die Middleware betrieben wird, Plattformseite)
Die Middleware wird in einer hochverfügbaren, DSGVO-konformen Infrastruktur betrieben. Ziel ist es, eine zuverlässige und sichere Bereitstellung der touristischen Inhalte mit einer angestrebten Verfügbarkeit von ≥ 99,9 % zu gewährleisten. Neben der Stabilität stehen insbesondere Aspekte wie Nachvollziehbarkeit, Skalierbarkeit und die nahtlose Integration in die Gesamtlandschaft mit Los 2 (Datenintegration), Los 3 (Governance/DMS) und Los 4 (Widgets) im Vordergrund.
Dieses Dokument beschreibt die technischen Anforderungen an Hosting, Betrieb und Betriebsführung der Middleware. Die fachliche Logik - etwa zur API-Struktur, Filterlogik oder Policy-Enforcement - ist im Applikationskonzept (Los 1, ohne Hosting) definiert und wird hier nicht erneut behandelt. Stattdessen liegt der Fokus auf Plattformbetrieb, Netzsicherheit, Backups, Disaster Recovery, Monitoring, SLAs und der Übergabe an den Auftraggeber.
Betriebsumgebung und Architektur
Die Middleware wird ausschließlich in Rechenzentren innerhalb der Europäischen Union gehostet, idealerweise in Deutschland. Diese müssen mindestens nach ISO 27001 oder vergleichbaren Standards zertifiziert sein. Eine Speicherung oder Replikation der Daten in Drittländer ist nicht zulässig.
Infrastruktur & Clustermanagement
Die Betriebsplattform basiert auf einer Kubernetes-Umgebung mit einem hochverfügbaren Control-Plane-Setup und mindestens zwei Verfügbarkeitszonen bzw. physischen Hosts. Die Workloads werden in logisch getrennte Nodepools aufgeteilt:
- CPU-optimierte Nodes für API- und Policy-Komponenten,
- RAM-optimierte Nodes für den Suchindex (Elasticsearch),
- System- und Infrastrukturkomponenten für Observability und Logging.
Die Infrastruktur unterstützt Rolling Updates sowie Blue-Green Deployments, um Zero-Downtime während Releases sicherzustellen. Skalierung erfolgt bedarfsorientiert per Horizontal Pod Autoscaler (HPA). Der Zugang erfolgt über ein vorgelagertes API-Gateway mit integrierter Web Application Firewall (WAF). Optional ist ein Edge-Cache (z. B. CDN) zur Performanceoptimierung für GET-Anfragen möglich.
Visualisierung: Cluster-internes Deployment
Die folgende Abbildung zeigt den logischen Aufbau der Kubernetes-Umgebung für Los 1. Die API-Komponente kann wahlweise die Policy-Logik selbst eingebettet enthalten oder diese an einen optionalen OPA-/ABAC-Service auslagern. Darüber hinaus ist die Observability-Umgebung mit Prometheus, Grafana, Loki und OpenTelemetry als eigenständiger Namespace organisiert.
@startuml
!include <C4/C4_Deployment>
LAYOUT_TOP_DOWN()
' ========== Kubernetes Cluster ==========
Deployment_Node(k8s, "Kubernetes Cluster (EU/DE)", "v1.29", "HA Control Plane; ≥2 Worker/Zone") {
' --- Fach-Workloads ---
Deployment_Node(ns_api, "Namespace: api", "Workload") {
Container(api, "API Service (N≥2)", "Container", "REST, optional GraphQL, Policy embedded")
Container(policy, "Policy Layer (optional)", "Container", "OPA/ABAC - nur falls externe Policy gewünscht")
}
' --- Plattformdienste / Ops ---
Deployment_Node(ns_ops, "Namespace: ops", "Platform Services") {
Container(keycloak, "Keycloak", "StatefulSet", "Scopes, client_id, Rotation")
}
' --- Observability ---
Deployment_Node(ns_obs, "Namespace: observability", "Telemetry") {
Container(otel, "OpenTelemetry Collector", "DaemonSet", "Traces/Metrics/Logs Export")
Container(prom, "Prometheus", "StatefulSet", "Scraping/Alerting")
Container(graf, "Grafana", "Deployment", "Dashboards (Read-only für AG)")
Container(loki, "Loki", "StatefulSet", "Zentrales Log-Archiv (≥90 Tage)")
}
}
' ========== Externe/Managed Services (außerhalb des Clusters) ==========
Deployment_Node(ext, "Managed Services (EU/DE)", "außerhalb Cluster") {
Container(os, "Elasticsearch (Cluster)", "Managed", "Index & Facetten (replicated)")
Container(pg, "Keycloak DB", "Managed PostgreSQL", "Userstore, Realm/Config")
Container(idp, "Externer IdP (optional)", "OIDC/SAML", "Identity Brokering Quelle")
}
' ========== Flows ==========
Rel(api, policy, "evaluate(jwt, ctx)", "HTTP/mTLS (optional)")
Rel(api, os, "Search/Facets (enforced)", "HTTPS/mTLS")
Rel(api, keycloak, "JWKS/Metadata, Login-Redirects (OIDC)", "HTTPS")
Rel(keycloak, pg, "JDBC", "TLS")
Rel(idp, keycloak, "Identity Brokering", "HTTPS")
Rel(api, otel, "Traces/Metrics/Logs")
Rel(keycloak, otel, "Traces/Metrics/Logs")
Rel(otel, prom, "Remote Write / Scrape")
Rel(prom, graf, "Dashboards")
Rel(loki, graf, "Logs Viewer")
' Stil-Hinweise (optional dezent)
UpdateElementStyle(policy, $bgColor="#FFF3D6", $borderColor="#D8B25C")
UpdateElementStyle(os, $bgColor="#E5F3FF", $borderColor="#6CA5D9")
@enduml
Hochverfügbarkeit & Performance (plattformseitig)
Die gesamte Plattformarchitektur ist konsequent auf einen hochverfügbaren und fehlertoleranten Betrieb ausgelegt. Sämtliche API-Services werden mindestens zweifach betrieben und sind im active-active-Modus konfiguriert, sodass jederzeit Anfragen entgegengenommen und verarbeitet werden können - auch im Fall eines Teilausfalls. Der zugrundeliegende Elasticsearch-Cluster besteht aus mindestens drei Knoten mit dedizierten Rollen für Master- und Data-Nodes, wodurch sowohl die Konsistenz als auch die horizontale Skalierbarkeit der Suchinfrastruktur sichergestellt wird. Alle zentralen Komponenten sind zudem hinter Loadbalancern abgesichert, die in Kombination mit kontinuierlichen Health Checks eine unterbrechungsfreie Verfügbarkeit gewährleisten.
Zur Reduzierung der Antwortzeiten, insbesondere für stark frequentierte Open-Data-Abfragen, kommen Edge- oder Gateway-nahe Caching-Mechanismen zum Einsatz. Diese Caches sind strikt „policy-keyed“, d. h. es werden ausschließlich solche Inhalte zwischengespeichert, die universell freigegeben sind - etwa vollständig offene, lizenzfreie Datensätze. Auf diese Weise wird sichergestellt, dass geschützte Inhalte (Closed Data) nicht versehentlich über Caching-Systeme ausgeliefert oder unzureichend abgesichert werden.
Für die Bewertung von Zugriffspolicies - etwa bei regionenbezogenen Freigaben - wird die Zuordnung durch Los 3 bei Bedarf temporär im API-Service zwischengespeichert. Die Middleware setzt dabei ausschließlich auf instanznahe In-Memory-Caches. Auf eine zentrale Redis-Infrastruktur wird bewusst verzichtet, um zusätzliche Betriebsrisiken und potenzielle Single Points of Failure zu vermeiden.
Die Leistungsfähigkeit der Plattform wird regelmäßig durch Lasttests abgesichert - sowohl vor dem initialen Go-Live als auch bei jeder wesentlichen Änderung an der Architektur oder den Komponenten.
Für den Betrieb der Middleware gelten verbindliche Mindeststandards. Die angestrebte Verfügbarkeit liegt bei mindestens 99,9 % im Jahresmittel. Im Störungsfall (Priorität 1) beträgt die maximale Reaktionszeit höchstens drei Stunden, die vollständige Wiederherstellung muss innerhalb von zwölf Stunden erfolgen. Der Support ist über ein Ticketsystem, per E-Mail sowie telefonisch erreichbar. Ein klar benannter Ansprechpartner stellt die Kommunikationsfähigkeit auf Seiten des Anbieters sicher.
Auch im Change Management gelten klare Qualitätsstandards: Deployments erfolgen über CI/CD-Pipelines mit Canary- oder Rolling-Strategien, ergänzt durch nachvollziehbare Changelogs und geregelte Release-Verfahren. Die Sicherheit wird durch ein aktives Schwachstellenmanagement gewährleistet, das unter anderem Patches innerhalb von 48 Stunden, regelmäßige Scans und mindestens einmal jährlich durchgeführte Penetrationstests umfasst. Schließlich verpflichtet sich der Betreiber zur laufenden Pflege der technischen Dokumentation - insbesondere in den Bereichen Betrieb, Architektur und Rechteverwaltung.
Monitoring, Observability und Reporting (plattformseitig)
Die gesamte Plattform ist von Grund auf auf umfassende Beobachtbarkeit ausgelegt. Das technische Monitoring erfasst kontinuierlich zentrale Systemkennzahlen wie CPU- und RAM-Auslastung, Netzwerkaktivität, Antwortzeiten, Fehlerraten sowie die Trefferquoten in Policy-bezogenen Caches. Ergänzend werden auch geschäftsrelevante Kennzahlen (Business-KPIs) überwacht, darunter die Cache-Hit-Raten, das allgemeine Anfragevolumen sowie die Einhaltung der definierten SLAs. Technisch basiert das Observability-Setup auf einem bewährten Stack aus Prometheus, Grafana, Loki und OpenTelemetry.
Sämtliche Logdaten werden für mindestens 90 Tage gespeichert und dabei DSGVO-konform behandelt. Insbesondere personenbezogene Informationen wie JWTs oder nutzerspezifische Bezüge werden dabei pseudonymisiert verarbeitet. Für den Fall von Auffälligkeiten ist eine 24/7-Alarmierung vorgesehen, die auf einer Eskalationsmatrix (P1 bis P4) basiert. Der Auftraggeber erhält zudem einen lesenden Zugriff auf die Dashboards und wird durch regelmäßige Berichte über den Systemzustand informiert.
Sicherheit & Netzarchitektur
Die Plattform orientiert sich konsequent an einem strikten Security-by-Design-Ansatz, bei dem sämtliche Sicherheitsaspekte von Beginn an in die Architektur integriert sind. Sämtliche Verbindungen erfolgen mindestens verschlüsselt über TLS 1.2, idealerweise über TLS 1.3. Zusätzlich ist HTTP Strict Transport Security (HSTS) aktiv, um downgradesichere Kommunikation sicherzustellen. Das vorgeschaltete API-Gateway übernimmt zentrale Schutzfunktionen wie eine Web Application Firewall (WAF) mit Schutz vor den OWASP Top 10, Rate-Limiting zur Abwehr von Missbrauch, Header-Normalisierung sowie DDoS-Prävention.
Zugänge zu administrativen Bereichen sind ausschließlich über eine dedizierte Bastion-Umgebung oder ein VPN möglich, wobei stets eine Multi-Faktor-Authentifizierung vorausgesetzt wird. Maschinenzugriffe erfolgen ausschließlich über kurzlebige Zugangstokens oder temporäre Zertifikate, um unkontrollierte Dauerzugriffe zu vermeiden. Zugangsdaten und kryptografische Schlüssel werden zentral in einem Key Management System (KMS) verwaltet; eine regelmäßige Rotation erfolgt automatisiert.
Die Netzwerkarchitektur ist logisch segmentiert: Öffentliche Zugänge (z. B. Edge), Anwendungskomponenten (App) und datenhaltende Systeme wie Elasticsearch sind strikt voneinander getrennt. Abschließend werden sämtliche sicherheitsrelevanten und administrativen Aktionen revisionssicher protokolliert, um vollständige Transparenz und Nachvollziehbarkeit zu gewährleisten.
Backups & Disaster Recovery
Zur Sicherstellung der Wiederherstellbarkeit im Fehlerfall wurden umfassende Backup- und Disaster-Recovery-Maßnahmen definiert. Sämtliche relevanten Komponenten - darunter Index-Daten, API- und Gateway-Konfigurationen, Policy-Regeln sowie Dashboards - werden täglich gesichert. Diese Backups werden verschlüsselt gespeichert, beispielsweise in einem Object-Storage, und für einen Zeitraum von mindestens 14 Tagen vorgehalten. Zur Überprüfung der Wiederherstellbarkeit finden mindestens quartalsweise Tests statt, bevorzugt automatisiert gegen eine dedizierte Staging-Umgebung.
Die angestrebten Wiederherstellungsziele (Disaster-Recovery-Ziele) sind dabei klar definiert: Das Recovery Point Objective (RPO) liegt bei maximal 15 Minuten, das Recovery Time Objective (RTO) bei maximal vier bis acht Stunden. Ergänzend existiert ein detaillierter Failover-Plan, der Reaktionswege und Zuständigkeiten im Fall von Teil- oder Komplettausfällen festlegt.
Im laufenden Betrieb stellt ein durchgängiges Monitoring die Verfügbarkeit und Stabilität der Plattform sicher. Es umfasst eine 24/7-Überwachung mit entsprechender Alarmierung und einer Eskalationsmatrix. Der Auftraggeber erhält darüber hinaus Lesezugriff auf die relevanten Dashboards und wird regelmäßig in Form von SLA-Berichten über den Systemzustand informiert.
Betriebsinfrastruktur & externe Anbindung
Die folgende Skizze visualisiert zentrale Betriebsaspekte der Middleware aus Sicht der betreibenden Organisation. Sie zeigt insbesondere:
- die Anbindung an die Observability-Infrastruktur (Monitoring, Alerting, Dashboards),
- das externe Backup-Repository für Index- und Konfigurationssnapshots sowie
- die Integration mit externen Losen (z. B. Ingest-Komponenten aus Los 2, Auth-API aus Los 3).
AG-seitige Betriebsakteure erhalten über Grafana Read-only-Zugriff auf alle relevanten Dashboards. Snapshots und Konfigurationen werden automatisiert in ein objektbasiertes Langzeitarchiv überführt. Die Struktur orientiert sich an einem hochverfügbaren, sicheren und datenschutzkonformen Cloud-Betrieb gemäß Leistungsbeschreibung 2.7 und 3.
@startuml
!include <C4/C4_Deployment>
LAYOUT_TOP_DOWN()
Person(ops, "AG Betrieb", "Read-only Dashboards")
' --- Observability ---
Deployment_Node(obs, "Observability (EU/DE)", "Telemetry") {
Container(prom, "Prometheus", "Stateful", "Scraping/Alerting")
Container(graf, "Grafana", "Deployment", "Dashboards (RO für AG)")
Container(loki, "Loki", "Stateful", "Logs ≥90 Tage")
}
' --- Backup & DR ---
Deployment_Node(backup, "Backup & DR (EU/DE)", "Object Storage") {
Container(repo, "Backup-Repo", "Object Storage", "Index-Snapshots, Konfigs")
}
' --- Integration (Lose 2/3) ---
Deployment_Node(int, "Integrationszone (EU/DE)", "Private Subnet") {
Container(l2, "Los 2 Ingest", "Service/Queue", "Batch/Stream → Index")
Container(l3, "Los 3 AuthZ-API", "Read-only API", "client_id → coverageIds")
}
' --- Flows (aus Sicht Betrieb) ---
Rel(prom, graf, "Dashboards")
Rel(ops, graf, "HTTPS (RO)")
Rel(l2, repo, "Snapshots (indirekt via Index)", "TLS")
Rel(l3, graf, "Monitoring input (indirekt)")
@endumlÜbergabe & Ramp-down
Ein geregelter Projektabschluss ist integraler Bestandteil des Betriebsmodells und beginnt spätestens drei Monate vor dem vorgesehenen Projektende mit der detaillierten Übergabeplanung. Diese umfasst unter anderem die Bereitstellung einer vollständigen technischen Dokumentation, die Übertragung sämtlicher relevanter Rechte, gegebenenfalls die Bereitstellung des Quellcodes sowie die Klärung offener Punkte. Darüber hinaus finden Übergabeworkshops statt, um den Wissenstransfer zu gewährleisten. Der formale Abschluss des Projekts wird durch ein gemeinsam mit dem Auftraggeber erstelltes Abnahmeprotokoll abgesichert.
Zusammenfassung
Das Hosting- und Betriebskonzept für die Middleware stellt sicher, dass die Lösung nicht nur leistungsfähig und sicher, sondern auch wartbar, dokumentiert und integrationsfähig bleibt. Durch die klare Trennung von Zuständigkeiten, die Fokussierung auf resiliente Architekturprinzipien und die vollständige Transparenz gegenüber dem Auftraggeber entsteht eine Plattform, die den Anforderungen an eine moderne touristische Dateninfrastruktur gerecht wird.
Visualisierung: Gesamtbetrieb und Systemanbindung
Die folgenden Abbildungen verorten die Middleware im Gesamtbetrieb. Die Abbildung Kernfluss zeigt den End‑to‑End‑Pfad vom Client über Edge/WAF und API‑Gateway zum API‑Service (mit optionalem Policy‑Service) bis in den Index sowie die Authentifizierung via IdP. Die Abbildung Betriebs‑ & Nebensysteme ergänzt Observability, Backup/DR und die Anbindung an Los 2/3.
Schwerpunkte sind Segmentierung, Sicherheitsmaßnahmen (WAF, mTLS, KMS), die Telemetrie‑Kette und das optional ausgelagerte Policy‑Enforcement.
@startuml
!include <C4/C4_Deployment>
LAYOUT_TOP_DOWN()
Person(sp, "Clients (Los 4)", "Widgets/Portale")
Person(ops, "AG Betrieb", "Read-only Dashboards")
' --- Edge & DMZ kompakt ---
together {
Deployment_Node(edge, "Edge / CDN (EU)", "WAF/DoS/CDN") {
Container(edge_cache, "Edge-Cache", "HTTP Cache", "policy-keyed GET, optional")
}
Deployment_Node(dmz, "DMZ (EU/DE)", "Public Subnet") {
Container(api_gw, "API Gateway", "Reverse Proxy/WAF", "JWT-Check, Quotas, optional Cache")
}
}
' --- App Cluster (schlank) ---
Deployment_Node(k8s, "Kubernetes (EU/DE)", "v1.29") {
Container(keycloak, "Keycloak (IdP)", "Container", "OIDC/OAuth2; Brokering-fähig")
Container(api, "API Service (N≥2)", "Container", "REST (OpenAPI), optional GraphQL")
Container(policy, "Policy Service (optional)", "Container", "OPA/ABAC - alternativ in API")
}
' --- Data Layer & externer IdP ---
Deployment_Node(data, "Data Layer (EU/DE)", "Managed/Stateful") {
Container(os, "Elasticsearch (Cluster)", "Managed", "Index & Facetten (replicated)")
}
Deployment_Node(extidp_node, "Externer Identity Provider (EU/DE)", "OIDC/SAML SSO") {
Container(ext_idp, "External IdP", "VM/Managed", "Enterprise/Partner IdP")
}
Deployment_Node(keycloak_db_node, "Managed Keycloak DB (EU/DE)") {
Container(keycloak_db, "Keycloak DB", "Managed PostgreSQL", "Userstore, Realm/Config")
}
' --- Flows ---
Rel(sp, edge_cache, "HTTPS")
Rel(edge_cache, api_gw, "HTTPS (revalidate/fallback)")
' API-Path
Rel(api_gw, api, "mTLS; JWT geprüft")
Rel(api, policy, "evaluate(jwt,ctx)", "mTLS/HTTP (optional)")
Rel(policy, os, "Search/Facets (enforced)", "mTLS")
' Auth-Path (Redirects & Validation)
Rel(sp, keycloak, "OIDC/OAuth2 Redirects", "HTTPS")
Rel(ext_idp, keycloak, "Identity Brokering", "OIDC/SAML over HTTPS")
Rel(api_gw, keycloak, "JWKS/Metadata für JWT-Validation", "HTTPS")
Rel(keycloak, keycloak_db, "JDBC", "TLS")
' (optional) direkte Validierung auch in der API:
' Rel(api, keycloak, "JWKS/Metadata (optional)", "HTTPS")
@enduml
Zugrunde liegende Annahmen
Die nachfolgenden Punkte fassen zentrale Annahmen zusammen, die den aktuellen Architekturentscheidungen des Konzepts zugrunde liegen. Sie leiten sich aus den vorliegenden Leistungsbeschreibungen ab und bilden die konzeptionelle Grundlage für Planung, Umsetzung und Abstimmung mit angrenzenden Losen. Da einige dieser Annahmen im weiteren Projektverlauf zu verifizieren sind, dienen sie insbesondere der transparenten Kommunikation der aktuell angenommenen Rahmenbedingungen.
Datenbezug (Los 2 → Los 1)
- Es wird davon ausgegangen, dass Los 2 die strukturierten Daten über eine OpenAPI-konforme Schnittstelle im JSON-LD-@graph-Format bereitstellt. Diese ist unter https://bayerncloud.digital/daten-nutzen/api/ öffentlich dokumentiert.
- Nach derzeitiger Spezifikation ist kein Push-basiertes Verfahren vorgesehen; die Middleware von Los 1 ruft die Daten regelmäßig per Pull-Mechanismus ab.
Medienbereitstellung
- Innerhalb des JSON-LD-@graph-Formats werden mediale Inhalte wie Bilder oder Dokumente lediglich als Referenzen eingebunden. Die tatsächliche Auslieferung dieser Assets - also Hosting, Skalierung und Zugriff - liegt gemäß aktueller Lesart der Leistungsbeschreibung vollständig in der Verantwortung von Los 2 (dataCycle).
- Los 1 beschränkt sich daher auf die Bereitstellung der Metadaten und URLs dieser Medien. Es wird weder ein eigenes CDN betrieben noch ein Media-Store innerhalb der Middleware vorgehalten.
- Sollte im weiteren Projektverlauf abweichend entschieden werden, dass bestimmte mediale Inhalte über Los 1 ausgeliefert werden sollen, wären entsprechende Anpassungen in Architektur und Betrieb erforderlich - etwa hinsichtlich Speicher, Latenzoptimierung oder Zugriffskontrolle.
- Soweit Livestream-Informationen benötigt werden (z. B. Skipisten), werden diese nur als Link/URL bereitgestellt. Eine Bereitstellung über die Middleware (z. B. als Proxy, mit Caching, Transkodierung oder QoS-Garantien) ist nicht Bestandteil von Los 1. Sollte dies später gewünscht sein, wären separate Architektur- und Betriebserweiterungen (Storage/CDN, Bandbreite, Rechte/DRM) sowie eine Kalkulationsanpassung erforderlich.