Use Permission Names
Permission configuration should use stable permission-name sets so changes are readable, reviewable, and easy to roll back.
SyncTV has two role layers. Keep them separate.
| Layer | Roles | Scope |
|---|---|---|
| Global user role | root, admin, user | Platform administration, user management, room management, system settings |
| Room role | creator, admin, member, guest | Playback, members, media, chat, and settings inside one room |
A global admin is not automatically a room admin. A room admin is not a platform administrator.
| Role | Boundary |
|---|---|
root | Super administrator; can manage root/admin/user accounts, global settings, and all rooms |
admin | Platform administrator; can manage normal users and rooms, but cannot modify root or equally privileged admins |
user | Normal user; uses rooms and media features according to business permissions |
User status is derived from ban records:
| Status | Effect |
|---|---|
active | Can log in, create rooms, and join rooms |
banned | Cannot log in, create rooms, or join rooms |
| Room role | Default meaning |
|---|---|
creator | Room creator; has all room permissions and cannot be weakened by room settings |
admin | Room administrator; can manage members, playback, media, room settings, and moderation by default |
member | Normal member; can chat, use WebRTC, create/edit their own media resources, delete their own media resources by ownership, and view media resources/member/chat data by default |
guest | Guest, not a room member. Guests have no media-resource, chat, or administration permissions by default. A room can only grant guest-safe capabilities such as member list, chat history, or WebRTC |
Room roles provide base permissions. Room settings and member overrides then add or remove permissions.
Guests can enter public rooms that explicitly allow guest access, but they do not become room members. Guest permissions use their own ceiling and do not inherit from member.
| Capability | Default | Can be granted through guest permissions | Notes |
|---|---|---|---|
| Basic realtime room state | Yes | No setting required | Lets the client show room existence, settings, and playback state after connecting |
| Member list | No | view_member_list | Read-only |
| Chat history | No | view_chat_history | Read-only |
| WebRTC signaling | No | use_webrtc | Allows signaling participation only; does not grant room administration |
| Media resources | No | No | Guests cannot read, browse, or manage media resources |
| Chat sending | No | No | send_chat is only for signed-in members |
| Playback control, member management, room settings | No | No | Requires a signed-in member with the matching permission |
Effective permissions are evaluated in three layers:
Rules:
creator always has all room permissions.memberAddedPermissions cannot exceed the admin-level ceiling.guestAddedPermissions uses a dedicated guest ceiling. It cannot grant media-resource, chat-write, or administration permissions.DELETE_ROOM is not a room-delegable permission. Room deletion belongs to the creator or the platform management plane.Runtime settings and administration surfaces use stable snake_case permission names.
| Permission name | Meaning |
|---|---|
send_chat | Send chat messages |
create_media_resource | Create media resources and edit media resources created by the actor |
delete_media_resource_any | Delete media resources created by other users or without a recorded creator |
reorder_media_resources | Reorder media resources |
clear_media_resources | Clear media resource queues |
live_control | Manage live streams and create publish keys |
play_control | Play, pause, and seek |
change_current_media | Switch current media |
change_playback_rate | Change playback speed |
approve_member | Approve or reject join requests |
kick_member | Kick members and start a temporary rejoin cooldown |
set_member_permissions | Change member permissions |
add_member | Add members directly |
set_room_settings | Modify room settings |
delete_chat | Delete chat messages |
delete_room | Delete room; not a normal room-delegable permission |
view_media_resources | View media resources |
view_member_list | View member list |
view_chat_history | View chat history |
use_webrtc | Use WebRTC voice/video features |
Deleting a media resource created by the actor is an ownership business rule, not a separate permission bit. A member can always delete their own media resources, even without create_media_resource; creating media resources and editing their own media resources require create_media_resource.
Room settings control join policy, room features, and default permissions.
| Setting | Default | Meaning |
|---|---|---|
password | Empty | Initial password on room creation; password APIs update it later |
allowGuestJoin | false | Allow guests to join |
maxMembers | 100 | Maximum members; upper bound 10000 |
requireApproval | false | Require join approval |
allowAutoJoin | true | Allow eligible users to auto-join |
chatEnabled | true | Enable chat |
autoPlay | {} | Auto-play policy, for example {"enabled":true,"mode":1,"delay":5} |
adminAddedPermissions / adminRemovedPermissions | Empty permission set | Admin default permission changes |
memberAddedPermissions / memberRemovedPermissions | Empty permission set | Member default permission changes |
guestAddedPermissions / guestRemovedPermissions | Empty permission set | Guest default permission changes |
Example:
synctv room settings get <ROOM_ID>synctv room settings update <ROOM_ID> --settings-json '{"requireApproval":true}'Member overrides are for exceptions, such as muting one member, granting playback control to one member, or removing ban capability from one administrator.
Semantics:
added_permissions adds normal member permissions.removed_permissions removes normal member permissions.adminAddedPermissions and adminRemovedPermissions.creator permissions has no effect.Management rules:
User preferences are database-backed user-level settings, not YAML configuration.
| Field | Default | Meaning |
|---|---|---|
two_factor_enabled | false | User-level 2FA |
notifications.room_invitation_in_app | true | In-app room invitation notifications |
notifications.room_event_in_app | true | In-app room event notifications |
notifications.system_announcement_in_app | true | In-app system announcements |
notifications.room_invitation_email | false | Email room invitation notifications |
notifications.room_event_email | false | Email room event notifications |
notifications.system_announcement_email | true | Email system announcements |
Provider instance bindings are not user preferences. They are stored on provider credentials when the user logs in to a provider through a specific instance. The database table also has a settings JSONB extension payload for low-priority experimental preferences. Stable product preferences should use explicit columns. Do not store secrets, tokens, cookies, passwords, or provider credentials in it.
2FA constraints:
Use Permission Names
Permission configuration should use stable permission-name sets so changes are readable, reviewable, and easy to roll back.
Separate Scopes
Platform admin and room admin are separate concepts. Diagnose permission issues by layer first.
Preferences Are Runtime Data
User preferences are changed through API/CLI and should not live in YAML or Helm values.
Verify Behavior
After changing join rules, permissions, or 2FA, test real login, room join, and playback flows.