Pond member management UI #54

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

Context

Pond Admins manage who participates, respecting membership quotas (vision: default 5 editors / 50 readers on personal ponds).

Scope

Pond settings 'Members': list current pond-scope grants grouped by role with search; add member by exact username or e-mail (no directory browsing — privacy) with role choice; change role; remove; enforce and display quota usage ('3 of 5 editor seats'); personal-pond rule surfaced (no second admin option there); pending states are not needed (no invitation flow in v1 — adding is immediate; document this simplification in the UI copy).

Acceptance criteria

  • adding/removing members works and takes effect immediately (second-browser e2e)
  • quota exhaustion disables the add action with a localized explanation
  • non-admin members see the member list read-only (transparency) but no management actions
  • shared ponds support multiple pond admins; personal ponds refuse it (UI + API test)

Technical notes

  • permissions.md §Roles, #22 (quota checks: editors_per_pond, readers_per_pond consumed here).

Dependencies

Depends on #22, #52.

Size: ~1.5 days


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 Pond Admins manage who participates, respecting membership quotas (vision: default 5 editors / 50 readers on personal ponds). ## Scope Pond settings 'Members': list current pond-scope grants grouped by role with search; add member by exact username or e-mail (no directory browsing — privacy) with role choice; change role; remove; enforce and display quota usage ('3 of 5 editor seats'); personal-pond rule surfaced (no second admin option there); pending states are not needed (no invitation flow in v1 — adding is immediate; document this simplification in the UI copy). ## Acceptance criteria - [ ] adding/removing members works and takes effect immediately (second-browser e2e) - [ ] quota exhaustion disables the add action with a localized explanation - [ ] non-admin members see the member list read-only (transparency) but no management actions - [ ] shared ponds support multiple pond admins; personal ponds refuse it (UI + API test) ## Technical notes - permissions.md §Roles, #22 (quota checks: `editors_per_pond`, `readers_per_pond` consumed here). ## Dependencies Depends on #22, #52. **Size**: ~1.5 days --- *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:27 +02:00
fable-5 added the
frontend
auth
labels 2026-07-04 14:52:27 +02:00
Collaborator

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

Was #54 liefert

  • Member-zentrische API (apps/api/src/members/) über die pond-scope-User-Grants (#51/#52): GET /ponds/:id/members (jedes Mitglied — Transparenz: Liste nach effektiver Rolle gruppiert + Seat-Nutzung + canManage), POST (Hinzufügen per exaktem Username oder E-Mail, kein Directory-Browsing), PATCH :userId (Rolle ändern), DELETE :userId (entfernen) — Mutationen Pond-Admin-gated über den Guard.
  • Seat-Quotas editors_per_pond / readers_per_pond (#22) werden beim Hinzufügen/Rollenwechsel in einer per-Pond advisory-locked Transaktion durchgesetzt (Zählung kann nicht racen); Admins sind unbegrenzt. Owner-Mitgliedschaft ist geschützt, persönliche Teiche verweigern einen zweiten Admin (shared Grant-Regel), der letzte Pond-Admin ist nicht entfernbar. Jede Änderung invalidiert den Pond-Permission-Cache und feuert den pond_access_changed-NOTIFY (#39/#53).
  • Member-UI (apps/web/src/members/): MemberManager in den Teich-Einstellungen — Liste nach Rolle + Suche + Seat-Anzeige („1 von 5 Bearbeiter-Plätzen"), Hinzufügen-Formular (bei vollem Seat deaktiviert mit lokalisierter Erklärung), Rollenwechsel + Entfernen; read-only für Nicht-Admins (Transparenz); persönlicher-Teich-Hinweis. Kein Einladungsflow (v1): Hinzufügen wirkt sofort, die UI-Copy sagt das.

Acceptance criteria

  • Hinzufügen/Entfernen wirkt sofort (Second-Browser-e2e: der Eingeladene sieht den Teich unmittelbar nach dem Add).
  • Quota-Erschöpfung deaktiviert die Add-Aktion mit lokalisierter Erklärung (Browser-e2e via abgesenktem Editor-Limit; API erzwingt zusätzlich quota_exceeded).
  • Nicht-Admin-Mitglieder sehen die Liste read-only (Transparenz), ohne Verwaltungsaktionen.
  • Shared-Teiche erlauben mehrere Pond-Admins; persönliche Teiche verweigern es (UI + API-Test).

Live-Checks

  • Test: persönlicher Teich → nur Owner (pond_admin, isOwner), canManage true, Seats 0/5 · 0/50; zweiter Admin → grant_pond_admin_personal_pond; unbekannt → member_not_found.
  • Int („Collab Test"): Anna (Admin/Owner) + Ben (Editor), Seats 1/5; Ben read-only (canManage false, POST → 403); Duplikat → member_exists; Rollenwechsel editor↔reader (Seats 1/5 ↔ 0/5) je 200. Baseline wiederhergestellt.

Tests: members.e2e.db.test.ts (Add/Change/Remove, Seat-Erschöpfung, Personal-Pond- + Owner-Regeln, read-only-Transparenz, Last-Admin) — api-DB 161 grün; neuer Browser-Pack members.spec.ts (Second-Browser-Sofortzugriff, Quota-Disable, Nicht-Admin-read-only) mit eigenem CI-Step.

Umgesetzt in `7f1c49d` (Claude Opus 4.8), Pipeline komplett grün (CI + CD: Deploy Test, Smoke, Int-Promotion), live auf **Test** und **Int** verifiziert. **Was #54 liefert** - **Member-zentrische API** (`apps/api/src/members/`) über die pond-scope-User-Grants (#51/#52): `GET /ponds/:id/members` (jedes Mitglied — Transparenz: Liste nach effektiver Rolle gruppiert + Seat-Nutzung + `canManage`), `POST` (Hinzufügen per **exaktem Username oder E-Mail**, kein Directory-Browsing), `PATCH :userId` (Rolle ändern), `DELETE :userId` (entfernen) — Mutationen Pond-Admin-gated über den Guard. - **Seat-Quotas** `editors_per_pond` / `readers_per_pond` (#22) werden beim Hinzufügen/Rollenwechsel in einer per-Pond advisory-locked Transaktion durchgesetzt (Zählung kann nicht racen); Admins sind unbegrenzt. Owner-Mitgliedschaft ist geschützt, persönliche Teiche verweigern einen zweiten Admin (shared Grant-Regel), der letzte Pond-Admin ist nicht entfernbar. Jede Änderung invalidiert den Pond-Permission-Cache und feuert den `pond_access_changed`-NOTIFY (#39/#53). - **Member-UI** (`apps/web/src/members/`): `MemberManager` in den Teich-Einstellungen — Liste nach Rolle + Suche + Seat-Anzeige („1 von 5 Bearbeiter-Plätzen"), Hinzufügen-Formular (bei vollem Seat deaktiviert mit lokalisierter Erklärung), Rollenwechsel + Entfernen; **read-only für Nicht-Admins** (Transparenz); persönlicher-Teich-Hinweis. Kein Einladungsflow (v1): Hinzufügen wirkt sofort, die UI-Copy sagt das. **Acceptance criteria** - [x] Hinzufügen/Entfernen wirkt sofort (Second-Browser-e2e: der Eingeladene sieht den Teich unmittelbar nach dem Add). - [x] Quota-Erschöpfung deaktiviert die Add-Aktion mit lokalisierter Erklärung (Browser-e2e via abgesenktem Editor-Limit; API erzwingt zusätzlich `quota_exceeded`). - [x] Nicht-Admin-Mitglieder sehen die Liste read-only (Transparenz), ohne Verwaltungsaktionen. - [x] Shared-Teiche erlauben mehrere Pond-Admins; persönliche Teiche verweigern es (UI + API-Test). **Live-Checks** - Test: persönlicher Teich → nur Owner (pond_admin, isOwner), `canManage` true, Seats 0/5 · 0/50; zweiter Admin → `grant_pond_admin_personal_pond`; unbekannt → `member_not_found`. - Int („Collab Test"): Anna (Admin/Owner) + Ben (Editor), Seats 1/5; Ben read-only (`canManage` false, POST → 403); Duplikat → `member_exists`; Rollenwechsel editor↔reader (Seats 1/5 ↔ 0/5) je 200. Baseline wiederhergestellt. **Tests**: `members.e2e.db.test.ts` (Add/Change/Remove, Seat-Erschöpfung, Personal-Pond- + Owner-Regeln, read-only-Transparenz, Last-Admin) — api-DB 161 grün; neuer Browser-Pack `members.spec.ts` (Second-Browser-Sofortzugriff, Quota-Disable, Nicht-Admin-read-only) mit eigenem CI-Step.
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#54
No description provided.