docs(phase-2): Phase 2 in acht Meilensteine schneiden (#56)
This commit was merged in pull request #56.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# #029 M16 – SCIM-Endpunkt als Alternative zum Abgleich
|
||||
|
||||
**Status:** offen
|
||||
**Im Tracker:** [#49](https://git.wilde-server.de/florian.wilde/Laufzettel/issues/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](028-graph-quelle.md) 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
|
||||
Reference in New Issue
Block a user