🚌 Bus Fleet Manager (BFM)

M-Tours · Sitzverwaltung für den webhook-getriebenen TripBuilder-Pivot
Umgebung: dev · e2e live

BFM empfängt Buchungs-Webhooks von Nezasa/TripBuilder, reserviert Sitze und stellt ein einbettbares Sitzplan-Widget für SmartPlanner bereit. Diese Seite bündelt die Live-Umgebung, die Widget-Demo und die Integrations-Doku für Nezasa.

Admin — Fleet Manager

Die BFM-Verwaltung: Busse, Sitzplan-Editor, Zustiegspunkte, Buchungen.

noch keine Auth Login (Logto, multi-tenant) ist als Nächstes geplant.

Admin öffnen ↗

Widget-Demo

SmartPlanner-Simulation: Buchung wählen → Sitzplan-Widget lädt live im iframe, Passagier zuweisen.

Demo öffnen →

Widget (roh)

Die einbettbare Seite selbst — braucht ?bookingRef + token.

/widget.html →

Integration für Nezasa

Der vollständige Vertrag steht im Repo unter context/CONTRACT_NEZASA.md. Kurzfassung:

1 · Buchungs-Webhook (Nezasa → BFM)

Nezasa registriert eine Subscription (modules/webhooks) auf unseren Endpoint. BFM verifiziert die Signatur und reserviert Sitze.

POST https://bfm-dev.p2p.travel/webhooks/nezasa
Header  X-Nezasa-Signature: <bare-hex HMAC-SHA256(hexDecode(secret), RAW body)>
Header  X-Nezasa-Event: booking_completed | cancellation_completed
Events  booking_completed → Sitze reservieren · cancellation_completed → freigeben
Idempotenz: dedupe auf payload.delivery (UUID) · kein Retry → Reconcile-Pfad
Enrichment: payload ist dünn → GET booking.url (/bookings/v1.13/<refId>)
            liefert rental-car productExternalRefId (= Bus) + Pax + Datum

2 · Sitz-Widget im SmartPlanner (iframe + postMessage)

SmartPlanners Backend mintet ein kurzlebiges, origin-gebundenes Token und bettet die BFM-Seite als iframe ein.

// 2a. Token minten (Backend, mit gemeinsamem Mint-Key)
POST https://bfm-dev.p2p.travel/v1/widget/token
Header  X-Mint-Key: <WIDGET_MINT_KEY>
Body    { "bookingRef": "...", "origin": "https://<embed-origin>" }
→ { "token": "<jwt>", "exp": ... }

// 2b. iframe einbetten + Token per postMessage übergeben
<iframe src="https://bfm-dev.p2p.travel/widget.html"></iframe>
iframe.contentWindow.postMessage(
  { type: "bfm:set-token", token, bookingRef, apiBase }, "https://bfm-dev.p2p.travel");

Das Widget meldet Ereignisse hoch: { source:"bfm-seat-map", action:"ready"|"assigned"|"resize" }. Alternativ als Web-Component (<bfm-seat-map>) einbettbar.

3 · Auth-Modell (drei getrennte Mechanismen)

KanalMechanismusStatus
Webhook (Nezasa → BFM)X-Nezasa-Signature HMAC-SHA256, 64-hex Shared Secretlive
Widget (SmartPlanner → BFM-API)kurzlebiges, origin-gebundenes minted JWT (HS256), scoped auf bookingReflive
Enrichment-Read (BFM → Nezasa)Api-Key Bearer zur Booking-API v1.13Token offen
Admin-User-LoginLogto (OIDC, multi-tenant) — geplantnächster Slice

4 · Offene Punkte (mit Nezasa zu bestätigen)