Wire real permissions into collab tokens and revocation #53

Closed
opened 2026-07-04 14:52:26 +02:00 by fable-5 · 1 comment
Collaborator

Context

Live editing must obey the same rules as REST: token mode from the shared resolution, revocation via the M3 notify path.

Scope

Replace the interim check in the collab-token endpoint with the shared algorithm (mode rw requires editor+, ro for readers/public where granted); emit the pond-level NOTIFY on grant/label changes (#39's generic path); collab revalidates affected connections via a resolution call through an internal API endpoint (collab holds no own copy of the algorithm inputs).

Acceptance criteria

  • downgrading a live editor to reader flips their session to read-only within seconds (e2e)
  • public page: anonymous visitor gets an ro token where a public grant exists, none otherwise
  • token issuance covered by the same fixture matrix as #52

Technical notes

  • permissions.md §Performance, realtime-collaboration.md.

Dependencies

Depends on #39, #51, #52.

Size: ~1 day


Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add de and en), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.

## Context Live editing must obey the same rules as REST: token mode from the shared resolution, revocation via the M3 notify path. ## Scope Replace the interim check in the collab-token endpoint with the shared algorithm (mode `rw` requires editor+, `ro` for readers/public where granted); emit the pond-level NOTIFY on grant/label changes (#39's generic path); collab revalidates affected connections via a resolution call through an internal API endpoint (collab holds no own copy of the algorithm inputs). ## Acceptance criteria - [ ] downgrading a live editor to reader flips their session to read-only within seconds (e2e) - [ ] public page: anonymous visitor gets an `ro` token where a public grant exists, none otherwise - [ ] token issuance covered by the same fixture matrix as #52 ## Technical notes - permissions.md §Performance, realtime-collaboration.md. ## Dependencies Depends on #39, #51, #52. **Size**: ~1 day --- *Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add `de` **and** `en`), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.*
fable-5 added this to the M5 — Permissions & quotas milestone 2026-07-04 14:52:26 +02:00
fable-5 added the
collab
auth
labels 2026-07-04 14:52:26 +02:00
Collaborator

Umgesetzt in 9d288b2 (Claude Opus 4.8), Pipeline komplett grün (CI + CD: Deploy Test, Smoke, Int-Promotion), live auf Test und Int verifiziert.

Was #53 liefert

  • Token-Modus aus der echten Auflösung (Basis kam mit #52): rw ab Editor, ro für Reader/Public — jetzt inkl. anonymer Besucher. GET /pages/:id/collab-token ist @Public(), bleibt aber permission-guarded: ohne lesbaren Zugriff → 404 (Existenz versteckt), sonst ro. Token-userId ist für anonyme Subjekte nullable (shared-Schema + collab-Context).
  • NOTIFY auf Grant- und Label-Änderungen: der pond-weite pond_access_changed (#39) feuert jetzt auch bei Label-Tree-/Zuordnungs-Änderungen (LabelsService move/remove/assign/unassign).
  • Prompte Revocation (echter Fix): Hocuspocus' closeConnections sendet nur eine App-Level-Close-Message — der Client bemerkte den Entzug erst nach seinem ~30 s Message-Timeout. Neu closeDocumentConnections schließt den echten WebSocket, sodass der Client sofort reconnectet und mit frisch aufgelöstem Token re-authentifiziert. Damit wird ein degradierter Editor innerhalb von Sekunden read-only — das AC, das der bisherige Mechanismus faktisch nicht erfüllte.

Acceptance criteria

  • Downgrade Editor→Reader flippt die Live-Session in Sekunden auf read-only — bewiesen im collab-DB-Test (access-listener.db.test.ts: Edits des Degradierten erreichen den Peer nicht mehr) und im Browser-e2e-Pack collab-permissions (≈1 s).
  • Public page: anonymer Besucher erhält ro wo ein Public-Grant existiert, sonst keinen (404). Live auf Int gegengeprüft (Anna legt Public-Reader-Grant an → anonym ro → Grant entfernt → 404).
  • Token-Ausgabe von derselben Fixture-Matrix wie #52 abgedeckt (anonym ro/404 ergänzt).

Live-Checks

  • Test: Owner-Seite → rw; anonym auf privater Seite → 404.
  • Int: collab-ben (Editor) → rw; anonym ohne Grant → 404; nach Public-Reader-Grant → ro; nach Entzug → 404. INT wieder auf Baseline (Grant entfernt).

Tests: shared 107, web 50, api 152→+anon-Fälle, collab +Downgrade-Test; neuer Browser-Pack collab-permissions (Reader-ro + Live-Downgrade) mit neuem regulärem Konto fixture-editor; alle grün in CI.

Umgesetzt in `9d288b2` (Claude Opus 4.8), Pipeline komplett grün (CI + CD: Deploy Test, Smoke, Int-Promotion), live auf **Test** und **Int** verifiziert. **Was #53 liefert** - **Token-Modus aus der echten Auflösung** (Basis kam mit #52): `rw` ab Editor, `ro` für Reader/Public — jetzt inkl. **anonymer Besucher**. `GET /pages/:id/collab-token` ist `@Public()`, bleibt aber permission-guarded: ohne lesbaren Zugriff → **404** (Existenz versteckt), sonst `ro`. Token-`userId` ist für anonyme Subjekte nullable (shared-Schema + collab-Context). - **NOTIFY auf Grant- *und* Label-Änderungen**: der pond-weite `pond_access_changed` (#39) feuert jetzt auch bei Label-Tree-/Zuordnungs-Änderungen (`LabelsService` move/remove/assign/unassign). - **Prompte Revocation (echter Fix)**: Hocuspocus' `closeConnections` sendet nur eine App-Level-Close-Message — der Client bemerkte den Entzug erst nach seinem ~30 s Message-Timeout. Neu `closeDocumentConnections` schließt den **echten WebSocket**, sodass der Client sofort reconnectet und mit frisch aufgelöstem Token re-authentifiziert. Damit wird ein degradierter Editor **innerhalb von Sekunden** read-only — das AC, das der bisherige Mechanismus faktisch nicht erfüllte. **Acceptance criteria** - [x] Downgrade Editor→Reader flippt die Live-Session in Sekunden auf read-only — bewiesen im collab-DB-Test (`access-listener.db.test.ts`: Edits des Degradierten erreichen den Peer nicht mehr) und im Browser-e2e-Pack `collab-permissions` (≈1 s). - [x] Public page: anonymer Besucher erhält `ro` wo ein Public-Grant existiert, sonst keinen (404). Live auf Int gegengeprüft (Anna legt Public-Reader-Grant an → anonym `ro` → Grant entfernt → 404). - [x] Token-Ausgabe von derselben Fixture-Matrix wie #52 abgedeckt (anonym `ro`/404 ergänzt). **Live-Checks** - Test: Owner-Seite → `rw`; anonym auf privater Seite → 404. - Int: `collab-ben` (Editor) → `rw`; anonym ohne Grant → 404; nach Public-Reader-Grant → `ro`; nach Entzug → 404. INT wieder auf Baseline (Grant entfernt). **Tests**: shared 107, web 50, api 152→**+anon-Fälle**, collab **+Downgrade-Test**; neuer Browser-Pack `collab-permissions` (Reader-ro + Live-Downgrade) mit neuem regulärem Konto `fixture-editor`; alle grün in CI.
Sign in to join this conversation.
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stwaidele/dorfteich#53
No description provided.