--- status: archived created: '2026-03-16' tags: - auth - roles priority: high created_at: '2026-03-16T07:51:49.636Z' depends_on: - 004-poll-data-model updated_at: '2026-03-16T09:18:35.900Z' transitions: - status: archived at: '2026-03-16T09:18:35.900Z' --- # Role & Permission System > **Status**: ๐Ÿ“ฆ Archived ยท **Priority**: High ยท **Created**: 2026-03-16 ยท **Tags**: auth, roles ## Overview Each poll has a role-based permission system. The owner assigns roles to users they discover or invite. Roles control what actions a user can perform on a poll. ## Design ### Roles & Permissions | Action | Viewer | Participant | Moderator | Owner | |---|---|---|---|---| | View poll & results | โœ… | โœ… | โœ… | โœ… | | Add options | โŒ | โœ… | โœ… | โœ… | | Vote | โŒ | โœ… | โœ… | โœ… | | Add/remove users | โŒ | โŒ | โœ… | โœ… | | Start/stop poll | โŒ | โŒ | โœ… | โœ… | | Delete poll | โŒ | โŒ | โŒ | โœ… | ### Implementation - Owner is implicit (poll.ownerId === userId) - Roles stored in `poll.roles[]` array - Role changes are broadcast to all connected peers - Moderators can invite users by peer ID (discovered via spec 007) or by sharing a poll link - Permission checks happen both client-side (UI) and on message receipt (owner validates) ### Invite Flow 1. Owner/moderator discovers a user (see spec 007) or has their peer ID 2. Assigns them a role โ†’ updates `poll.roles[]` 3. When that user connects, they receive the poll state including their role 4. Users without a role who connect via link get `viewer` by default ## Plan - [ ] Implement role assignment data model - [ ] Create permission check utility (`canVote()`, `canModerate()`, etc.) - [ ] Build user management UI in poll detail page - [ ] Implement role change broadcast over PeerJS - [ ] Owner-side validation of incoming messages against roles ## Test - [ ] Viewer cannot vote or add options - [ ] Participant can vote and add options - [ ] Moderator can add/remove users and start/stop poll - [ ] Only owner can delete - [ ] Unknown users connecting via link get viewer role