6.7 KiB
10 – Legacy-API-Kunden & Zugriffsbereinigung
Ausgangspunkt
Das Legacy-System speichert API-Zugriffe nicht applikationsseitig. In Produktion ist Symfony-Logging deaktiviert (logging_enabled: false, sfNoLogger). API-Nutzung ist daher nicht zuverlässig aus der Anwendung rekonstruierbar.
Stattdessen wird der API-Cutover aus den migrierten Daten abgeleitet:
- Legacy-API-User sind in
users.registration_type = apiuserbzw. über die Rolleapi-onlyerkennbar. - Legacy-API-Keys wurden bewusst nicht übernommen.
- Legacy-API-Credentials wie
apiReadAccess/apiWriteAccesswurden nicht 1:1 pro User persistiert, sondern in neue Sanctum-Abilities übersetzt. - Zahlungs-/Freigabestatus kann nur über importierte
legacy_invoicesbzw. später über Grandfathering-Daten bewertet werden.
Legacy-Regeln
Im alten Symfony-Frontend gilt:
- API-fähige Routen sind in
apps/frontend/config/routing.ymlmitapi_access: truemarkiert. ApiAccessFilterweistX-ApiKeyauf nicht-API-Routen mit HTTP 501 ab.ApiKeyGuardAuthFilterliestX-ApiKeyund suchtsfGuardUserProfile.api_key.- Wird ein Profil gefunden, wird dessen User für den Request eingeloggt.
- Wenn bereits eine gültige Web-Session existiert, kann die API technisch auch ohne gültigen API-Key laufen, sofern Credentials passen.
SecureApiAccessFilterverlangt:GET/HEAD→apiReadAccessPOST/PUT/DELETE→apiWriteAccess- andere Methoden → HTTP 405
- Einzelne Actions verlangen zusätzlich Symfony-Credentials wie
editor. ApiKeyGuardAuthFilterprüft nicht selbstis_active.
Neue Bewertungsregel
Für den Cutover erhalten nur noch Kunden Zugriff, die im migrierten System fachlich freigabefähig sind:
- Kandidat ist
registration_type = apiuseroder hat Rolleapi-only. - User ist aktiv (
is_active = true). - Die letzte importierte Legacy-Rechnung des Users hat
status = paid.
Alle anderen Kandidaten werden nicht automatisch freigeschaltet:
needs_review: aktiver API-Kandidat ohne importierte Legacy-Rechnung.blocked: inaktiver API-Kandidat oder letzte Rechnung nicht bezahlt.
Report-Command
php artisan api:legacy-customers-report
php artisan api:legacy-customers-report --classification=eligible
php artisan api:legacy-customers-report --portal=businessportal24
php artisan api:legacy-customers-report --no-report
Der Command schreibt standardmäßig:
storage/app/private/migration/legacy-api-customers-*.json
Der Report enthält:
- Kandidatenregel und bekannte Datenlücken
- Zusammenfassung nach
eligible,needs_review,blocked - User-ID, E-Mail, Portal, Legacy-ID
- Rollen und Registration-Type
- letzte Legacy-Rechnung inkl. Status, Datum, Betrag
- empfohlene Aktion:
invite_to_generate_sanctum_tokenmanual_billing_review_requireddo_not_grant_api_access
Aktuelle Datenlage
In der migrierten Datenbank wurden bisher gefunden:
- 195 User mit
registration_type = apiuser - 1 API-User mit archivierter Legacy-Rechnung
- diese Rechnung ist bezahlt
Damit ist nach aktueller Datenlage nur ein API-User automatisch freigabefähig. Die übrigen API-User müssen entweder manuell geprüft werden oder benötigen zusätzliche Legacy-Billing-/Vertragsdaten.
Noch fehlende Daten
Für eine harte finale Entscheidung fehlen ggf.:
- vollständige Legacy-Zuordnung von API-Usern zu zahlenden Vertrags-/Billing-Usern, falls API-User nicht selbst Rechnungsempfänger waren
- explizite Legacy-Credential-Zuordnung
apiReadAccess/apiWriteAccesspro User, falls feiner alsapiuser/api-onlybenötigt - aktuelle fachliche Liste aktiver API-Kunden vom Auftraggeber, falls Rechnungsarchiv nicht ausreicht
Ohne diese Daten ist die sichere Standardeinstellung:
- nur
eligibleautomatisch zur Token-Migration einladen needs_reviewnicht automatisch freischaltenblockednicht freischalten
Token-Erstellung im neuen System
Die Customer-Seite für API-Tokens ist zusätzlich technisch abgesichert. Ein User kann nur dann einen Sanctum-Token erstellen, wenn:
users.is_active = true- mindestens eine der folgenden Bedingungen erfüllt ist:
- aktiver neuer Zahlungsstatus in
user_payment_options(status = active, aktueller Zeitraum gültig) - aktiver Bestandsschutz in
user_payment_options(status = grandfathered,grandfathered_until >= today) - Übergangsweise: letzte importierte Legacy-Rechnung ist
paid
- aktiver neuer Zahlungsstatus in
Damit bekommen reaktivierte oder neue Kunden künftig keinen API-Zugang über alte Rechnungen, sondern erst über die neue aktive Zahlungs-/Vertragslogik. Bereits erstellte Tokens inaktiver User werden zusätzlich bei API-Requests blockiert.
API-Usage-Logging
Neue API-Requests werden persistent in api_usage_logs protokolliert:
user_idpersonal_access_token_id- HTTP-Methode
- Pfad
- Route-Name
- Statuscode
- IP-Adresse
- User-Agent
- Dauer in Millisekunden
- Zeitpunkt
Nicht gespeichert werden:
- Bearer-Token im Klartext
- Legacy-
api_key - Request-Payloads
Auch abgewiesene Legacy-Key-Requests (410 Gone) und Requests inaktiver User (403) werden geloggt.
API-Rate-Limiting
Die /api/v1-Routen sind zusätzlich per Middleware EnsureApiTokenRateLimit limitiert:
- Limit: 60 Requests pro Minute
- bevorzugter Schlüssel: Sanctum-/Bearer-Token-ID
- Fallback: SHA-256-Fingerprint des Bearer-Tokens, danach User-ID/IP
- inaktive User werden vorher per
EnsureApiUserIsActiveblockiert - überschrittene Limits liefern HTTP 429 mit
Retry-After,X-RateLimit-LimitundX-RateLimit-Remaining
Damit wird ein einzelner stark nutzender Client begrenzt, ohne andere Tokens desselben Users sofort mitzusperren.
API-Usage-Reporting
Die protokollierten API-Requests können per Artisan-Command ausgewertet werden:
php artisan api:usage-report
php artisan api:usage-report --from=2026-04-01 --to=2026-04-30
php artisan api:usage-report --user=123
php artisan api:usage-report --status=403
php artisan api:usage-report --no-report
Der Command schreibt standardmäßig:
storage/app/private/migration/api-usage-*.json
Der Report enthält:
- Gesamtzahl Requests
- eindeutige User und Sanctum-Tokens
- 2xx-/4xx-/5xx-Verteilung
- durchschnittliche Dauer
- Top-Pfade
- Statuscode-Verteilung
- Top-User und Top-Tokens
- letzte Requests im gefilterten Zeitraum
Damit ist die neue API-Nutzung ab Cutover nicht mehr von Webserver-Logs abhängig und kann regelmäßig exportiert oder später in eine Admin-UI übernommen werden.
P7-Abgrenzung Newsletter
newsletter/unsubscribe wird bewusst nicht als Legacy-API-Endpoint umgesetzt. Es gibt dafür keinen relevanten Legacy-API-Client. Newsletter-Abmeldung und externer Newsletter-Dienst werden nach der Migration im neuen Frontend sauber neu implementiert.