Files
Laufzettel/docs/issues/029-scim-endpunkt.md
T
Florian Wilde 41778529fc
Prüfung / pruefung (pull_request) Canceled after 0s
Prüfung / e2e (pull_request) Canceled after 0s
docs(phase-2): Phase 2 in acht Meilensteine schneiden
Phase 2 stand bisher nur als acht Stichpunkte im Epic. Jetzt je Meilenstein eine
Datei mit Ziel, Aufgaben und Akzeptanzkriterien, dazu im Tracker gespiegelt:
#48 bis #55, zusammen 76 h geschaetzt.

Die Reihenfolge ist nicht beliebig. M15 fuehrt die Quellenart ein, die M16
braucht; M17 legt die Zusammensetzung fest, auf der M18 aufsitzt. Die anderen
vier haengen an nichts und koennen jederzeit dazwischen.

Drei Entscheidungen fallen vor dem Code und stehen je Meilenstein als erste
Aufgabe mit Empfehlung:

- Wie ein Baustein die Unveraenderlichkeit einer veroeffentlichten Version
  ueberlebt (Verweis im Entwurf, tiefe Kopie beim Veroeffentlichen). Ein Lauf
  sieht weiterhin konkrete Schritte und muss nichts lernen.
- Wo Anhaenge liegen (Dateisystem, Metadaten in der Datenbank) -- mit der
  Folge, dass Compose-Stand, native Installation und sicherung.md ein Volume
  brauchen. Eine Sicherung, die nur die Datenbank mitnimmt, verliert ab dort
  Daten.
- Was eine Selbstauskunft zeigt: Titel, Status, Zeitraum, Geraet, aber keine
  Schritte, Notizen, Kommentare oder Anhaenge. In einem Lauf stehen
  Arbeitsnotizen ueber Menschen; eine Selbstauskunft ist keine Akteneinsicht.

Refs #2
2026-10-04 18:20:12 +02:00

3.2 KiB
Raw Blame History

#029 M16 – SCIM-Endpunkt als Alternative zum Abgleich

Status: offen Im Tracker: #49 Meilenstein: v0.2.0 Labels: phase-2, backend Geschätzt: 12 h Tatsächlich: –

Ziel

Der Abgleich holt heute. Ein Identitätsanbieter kann auch schicken — authentik, Entra ID und Okta sprechen dafür SCIM 2.0. Das ist der Weg für Häuser, die Laufzettel keinen Lesezugriff auf ihr Verzeichnis geben wollen oder aus einem Netz heraus betreiben, das das Verzeichnis nicht erreicht.

Setzt #028 voraus: die Quellenart SCIM braucht die Weiche.

Zu entscheiden

  • Ein Token je Quelle, als Hash gespeichert — Empfehlung, dasselbe Verfahren wie beim lokalen Passwort (argon2). Es wird einmal angezeigt und ist danach nicht mehr lesbar. Das Token identifiziert die Quelle und damit den Kunden; es ist der einzige Mandantenbeweis, den ein Push mitbringt.
  • Was bei DELETE /Users/{id} geschieht: aktiv = false, nicht löschen. Das ist die Regel des ganzen Projekts, und ein Identitätsanbieter, der löschen will, bekommt 204 — aber die Zeile bleibt, weil Läufe an ihr hängen. Das muss in der Anleitung stehen, sonst wirkt es wie ein Fehler.

Aufgaben

  • Route Handler unter src/app/api/scim/v2/: Users (GET mit Filter userName eq, POST), Users/{id} (GET, PUT, PATCH, DELETE), dazu ServiceProviderConfig, Schemas, ResourceTypes — ohne die drei weigern sich manche Anbieter, überhaupt anzufangen
  • Jeder dieser Handler prüft selbst: das Token, und daraus die Quelle und den Kunden. Die Hülle unter (app) liegt hier nicht darüber (CLAUDE.md)
  • Zuordnung: externalId → externeId, userName → upn, name.givenName/familyName, emails[primary] → mail, active → aktiv, urn:ietf:params:scim:schemas:extension:enterprise:2.0:User für department und manager
  • Antwortform nach RFC 7644: schemas, id, meta.resourceType, meta.location, bei Listen totalResults/itemsPerPage/startIndex; Fehler als urn:ietf:params:scim:api:messages:2.0:Error
  • PATCH mit op: add|replace|remove auf den Pfaden, die die Anbieter wirklich schicken — nicht der ganze Standard
  • Idempotenz: zweimal dasselbe POST ergibt 409, nicht eine zweite Person
  • Protokolleintrag je Vorgang, mit der Quelle als Urheber (Systemlauf, kein Benutzer)
  • Admin → Verzeichnis: Token erzeugen, einmal anzeigen, widerrufen; letzte Zustellung sichtbar
  • Anleitung Kapitel 06: Einrichtung in authentik und in Entra ID

Akzeptanzkriterien

  • Test gegen aufgezeichnete Anfragen von authentik und Entra ID (Form, nicht erfunden): anlegen, aktualisieren, deaktivieren, wieder aktivieren
  • Test: ohne Token 401, mit fremdem Token kein Zugriff auf die Personen einer anderen Quelle
  • Test: DELETE setzt aktiv = false und löscht nichts
  • Test: zweimal dasselbe POST ergibt 409 und keine zweite Zeile
  • Test: das Token steht nur als Hash in der Datenbank und in keiner Antwort
  • Test: eine Quelle der Art SCIM wird vom Zeitplan nicht abgeglichen — sie bekommt geschickt