TeamManager laat admins rollen wijzigen en leden verwijderen, maar de huidige rules op team_members staan dat niet toe:
updateRule: '@request.auth.id = id' — alleen self-update; db.updateTeamMember(anderId, {role}) faalt
deleteRule: null — alleen superusers; db.deleteTeamMember(id) faalt
Het beheerscherm is daarmee functieloos voor app-admins.
Daarnaast: twee verweven problemen
Privilege-escalatie (security): de huidige self-update-rule beperkt niet wélke velden — elke ingelogde gebruiker kan nu zijn eigen role naar "admin" patchen via de REST-API. De login-resync corrigeert dat pas bij de eerstvolgende login; tot die tijd heeft de gebruiker admin-toegang in de app. Moet dicht in dezelfde wijziging (anders wordt het door de nieuwe admin-rules pas écht gevaarlijk).
Rol-resync-conflict: de hook zet bij elke login de rol terug op basis van ENTRA_ADMIN_EMAILS (ADR-004). Elke UI-promotie zou dus bij de volgende login worden teruggedraaid — beheer via TeamManager blijft schijn zolang de resync ook demoteert.
updateRule: '(@request.auth.id = id && @request.body.role:isset = false) || @request.auth.role = "admin"' — self-update mag (onboarding raakt role niet), maar het role-veld alleen door admins; dicht meteen de escalatie.
deleteRule: '@request.auth.role = "admin"'
Resync wordt escalate-only (pb_hooks/team_members.pb.js): de allow-list garandeert admin-rechten (promotie bij login blijft werken), maar demoteert niet meer — UI-promoties blijven staan. Demotie loopt via TeamManager; allow-list-leden zijn niet via de UI te demoteren (allow-list wint bij volgende login). ADR-004 wordt hierop aangepast.
UI-toelichting in TeamManager bijgewerkt op het nieuwe gedrag.
Verificatie (mock-OIDC matrix)
User kan eigen role NIET wijzigen (escalatie dicht), wél eigen onboarding-velden
User kan andermans record niet wijzigen/verwijderen
Admin kan promoveren, demoteren en verwijderen
UI-promotie overleeft de volgende login van het lid (escalate-only)
Allow-list-lid blijft admin na login
Regressie: #22-matrix, #24-matrix, #18-harness, npm test
## Context (follow-up van #22)
TeamManager laat admins rollen wijzigen en leden verwijderen, maar de huidige rules op `team_members` staan dat niet toe:
- `updateRule: '@request.auth.id = id'` — alleen self-update; `db.updateTeamMember(anderId, {role})` faalt
- `deleteRule: null` — alleen superusers; `db.deleteTeamMember(id)` faalt
Het beheerscherm is daarmee functieloos voor app-admins.
## Daarnaast: twee verweven problemen
1. **Privilege-escalatie (security):** de huidige self-update-rule beperkt niet wélke velden — elke ingelogde gebruiker kan nu zijn eigen `role` naar `"admin"` patchen via de REST-API. De login-resync corrigeert dat pas bij de eerstvolgende login; tot die tijd heeft de gebruiker admin-toegang in de app. Moet dicht in dezelfde wijziging (anders wordt het door de nieuwe admin-rules pas écht gevaarlijk).
2. **Rol-resync-conflict:** de hook zet bij elke login de rol terug op basis van `ENTRA_ADMIN_EMAILS` (ADR-004). Elke UI-promotie zou dus bij de volgende login worden teruggedraaid — beheer via TeamManager blijft schijn zolang de resync ook demoteert.
## Fix
1. **Rules** (migratie `1781000003` + basis-migratie + setup-script-mirror):
- `updateRule: '(@request.auth.id = id && @request.body.role:isset = false) || @request.auth.role = "admin"'` — self-update mag (onboarding raakt `role` niet), maar het `role`-veld alleen door admins; dicht meteen de escalatie.
- `deleteRule: '@request.auth.role = "admin"'`
2. **Resync wordt escalate-only** (`pb_hooks/team_members.pb.js`): de allow-list garandeert admin-rechten (promotie bij login blijft werken), maar demoteert niet meer — UI-promoties blijven staan. Demotie loopt via TeamManager; allow-list-leden zijn niet via de UI te demoteren (allow-list wint bij volgende login). ADR-004 wordt hierop aangepast.
3. UI-toelichting in TeamManager bijgewerkt op het nieuwe gedrag.
## Verificatie (mock-OIDC matrix)
- [ ] User kan eigen `role` NIET wijzigen (escalatie dicht), wél eigen onboarding-velden
- [ ] User kan andermans record niet wijzigen/verwijderen
- [ ] Admin kan promoveren, demoteren en verwijderen
- [ ] UI-promotie overleeft de volgende login van het lid (escalate-only)
- [ ] Allow-list-lid blijft admin na login
- [ ] Regressie: #22-matrix, #24-matrix, #18-harness, npm test
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Context (follow-up van #22)
TeamManager laat admins rollen wijzigen en leden verwijderen, maar de huidige rules op
team_membersstaan dat niet toe:updateRule: '@request.auth.id = id'— alleen self-update;db.updateTeamMember(anderId, {role})faaltdeleteRule: null— alleen superusers;db.deleteTeamMember(id)faaltHet beheerscherm is daarmee functieloos voor app-admins.
Daarnaast: twee verweven problemen
rolenaar"admin"patchen via de REST-API. De login-resync corrigeert dat pas bij de eerstvolgende login; tot die tijd heeft de gebruiker admin-toegang in de app. Moet dicht in dezelfde wijziging (anders wordt het door de nieuwe admin-rules pas écht gevaarlijk).ENTRA_ADMIN_EMAILS(ADR-004). Elke UI-promotie zou dus bij de volgende login worden teruggedraaid — beheer via TeamManager blijft schijn zolang de resync ook demoteert.Fix
1781000003+ basis-migratie + setup-script-mirror):updateRule: '(@request.auth.id = id && @request.body.role:isset = false) || @request.auth.role = "admin"'— self-update mag (onboarding raaktroleniet), maar hetrole-veld alleen door admins; dicht meteen de escalatie.deleteRule: '@request.auth.role = "admin"'pb_hooks/team_members.pb.js): de allow-list garandeert admin-rechten (promotie bij login blijft werken), maar demoteert niet meer — UI-promoties blijven staan. Demotie loopt via TeamManager; allow-list-leden zijn niet via de UI te demoteren (allow-list wint bij volgende login). ADR-004 wordt hierop aangepast.Verificatie (mock-OIDC matrix)
roleNIET wijzigen (escalatie dicht), wél eigen onboarding-velden