2828 ("providers" , "write" , "Write workspace provider configuration" ),
2929 ("providers" , "override:self" , "Override providers in own user preferences" ),
3030 ("opensearch" , "admin" , "Administer OpenSearch security" ),
31-
3231 # Users / RBAC
3332 ("users" , "list" , "List users" ),
3433 ("users" , "read" , "Read user profile" ),
4039 ("roles" , "edit" , "Edit custom roles" ),
4140 ("roles" , "delete" , "Delete custom roles" ),
4241 ("audit" , "read" , "Read audit log" ),
43-
4442 # Connectors
4543 ("connectors" , "list:own" , "List own connectors" ),
4644 ("connectors" , "list:all" , "List all connectors in the workspace" ),
4745 ("connectors" , "create" , "Create connectors" ),
4846 ("connectors" , "delete:own" , "Delete own connectors" ),
4947 ("connectors" , "delete:any" , "Delete any connector" ),
5048 ("connectors" , "use" , "Use connector OAuth and browse" ),
51-
5249 # Knowledge
5350 ("knowledge" , "upload" , "Upload documents" ),
5451 ("knowledge" , "delete:own" , "Delete own documents" ),
5956 ("kf" , "edit:own" , "Edit own knowledge filters" ),
6057 ("kf" , "edit:any" , "Edit any knowledge filter" ),
6158 ("kf" , "share" , "Share knowledge filters" ),
62-
6359 # Chat / search
6460 ("chat" , "use" , "Use chat" ),
6561 ("search" , "use" , "Use search" ),
6662 ("conversations" , "read:own" , "Read own conversations" ),
6763 ("conversations" , "read:all" , "Read all conversations" ),
6864 ("conversations" , "delete:own" , "Delete own conversations" ),
6965 ("conversations" , "delete:any" , "Delete any conversation" ),
70-
7166 # Flows / agent
7267 ("flows" , "read" , "Read flows" ),
7368 ("flows" , "edit" , "Edit flows" ),
7469 ("agent" , "prompt:override" , "Override agent system prompt for self" ),
7570 ("agent" , "prompt:global" , "Edit global agent system prompt" ),
76-
7771 # API keys
7872 ("apikeys" , "create:self" , "Create own API keys" ),
7973 ("apikeys" , "revoke:self" , "Revoke own API keys" ),
@@ -93,7 +87,11 @@ def permission_name(resource: str, action: str) -> str:
9387BUILTIN_ROLES : list [tuple [str , str , str ]] = [
9488 # (id, name, description)
9589 ("role-admin" , "admin" , "Full control over infra, users, and all data." ),
96- ("role-developer" , "developer" , "Manages own connectors, flows, and ingestion. No infra writes." ),
90+ (
91+ "role-developer" ,
92+ "developer" ,
93+ "Manages own connectors, flows, and ingestion. No infra writes." ,
94+ ),
9795 ("role-user" , "user" , "Default end-user. Chat, search, and own connectors." ),
9896 ("role-viewer" , "viewer" , "Read-only chat and search." ),
9997]
@@ -106,35 +104,56 @@ def _admin_perms() -> set[str]:
106104def _developer_perms () -> set [str ]:
107105 return {
108106 # NOTE: providers are admin-only — no provider perms for developers.
109- "connectors:list:own" , "connectors:create" , "connectors:delete:own" , "connectors:use" ,
110- "knowledge:upload" , "knowledge:delete:own" , "knowledge:read:own" ,
111- "kf:create" , "kf:edit:own" ,
112- "chat:use" , "search:use" ,
113- "conversations:read:own" , "conversations:delete:own" ,
114- "flows:read" , "flows:edit" ,
107+ "connectors:list:own" ,
108+ "connectors:create" ,
109+ "connectors:delete:own" ,
110+ "connectors:use" ,
111+ "knowledge:upload" ,
112+ "knowledge:delete:own" ,
113+ "knowledge:read:own" ,
114+ "kf:create" ,
115+ "kf:edit:own" ,
116+ "chat:use" ,
117+ "search:use" ,
118+ "conversations:read:own" ,
119+ "conversations:delete:own" ,
120+ "flows:read" ,
121+ "flows:edit" ,
115122 "agent:prompt:override" ,
116- "apikeys:create:self" , "apikeys:revoke:self" ,
123+ "apikeys:create:self" ,
124+ "apikeys:revoke:self" ,
117125 }
118126
119127
120128def _user_perms () -> set [str ]:
121129 return {
122130 # NOTE: providers are admin-only — no provider perms for users.
123- "connectors:list:own" , "connectors:create" , "connectors:delete:own" , "connectors:use" ,
124- "knowledge:upload" , "knowledge:delete:own" , "knowledge:read:own" ,
125- "kf:create" , "kf:edit:own" ,
126- "chat:use" , "search:use" ,
127- "conversations:read:own" , "conversations:delete:own" ,
131+ "connectors:list:own" ,
132+ "connectors:create" ,
133+ "connectors:delete:own" ,
134+ "connectors:use" ,
135+ "knowledge:upload" ,
136+ "knowledge:delete:own" ,
137+ "knowledge:read:own" ,
138+ "kf:create" ,
139+ "kf:edit:own" ,
140+ "chat:use" ,
141+ "search:use" ,
142+ "conversations:read:own" ,
143+ "conversations:delete:own" ,
128144 "flows:read" ,
129145 "agent:prompt:override" ,
130- "apikeys:create:self" , "apikeys:revoke:self" ,
146+ "apikeys:create:self" ,
147+ "apikeys:revoke:self" ,
131148 }
132149
133150
134151def _viewer_perms () -> set [str ]:
135152 return {
136- "chat:use" , "search:use" ,
137- "conversations:read:own" , "conversations:delete:own" ,
153+ "chat:use" ,
154+ "search:use" ,
155+ "conversations:read:own" ,
156+ "conversations:delete:own" ,
138157 "flows:read" ,
139158 }
140159
@@ -151,6 +170,7 @@ def _viewer_perms() -> set[str]:
151170# Idempotent seeder
152171# ---------------------------------------------------------------------------
153172
173+
154174async def seed_roles_and_permissions (session : AsyncSession ) -> None :
155175 """Insert any missing roles/permissions/role_permissions. Safe to call repeatedly.
156176
@@ -160,8 +180,7 @@ async def seed_roles_and_permissions(session: AsyncSession) -> None:
160180
161181 # Permissions
162182 existing_perms = {
163- p .name : p
164- for p in (await session .execute (select (Permission ))).scalars ().all ()
183+ p .name : p for p in (await session .execute (select (Permission ))).scalars ().all ()
165184 }
166185 perm_id_by_name : dict [str , str ] = {p .name : p .id for p in existing_perms .values ()}
167186
@@ -183,10 +202,7 @@ async def seed_roles_and_permissions(session: AsyncSession) -> None:
183202 await session .flush ()
184203
185204 # Roles
186- existing_roles = {
187- r .name : r
188- for r in (await session .execute (select (Role ))).scalars ().all ()
189- }
205+ existing_roles = {r .name : r for r in (await session .execute (select (Role ))).scalars ().all ()}
190206 for role_id , role_name , description in BUILTIN_ROLES :
191207 if role_name in existing_roles :
192208 continue
@@ -201,10 +217,7 @@ async def seed_roles_and_permissions(session: AsyncSession) -> None:
201217 await session .flush ()
202218
203219 # Re-fetch so we have IDs for the just-inserted rows.
204- role_id_by_name = {
205- r .name : r .id
206- for r in (await session .execute (select (Role ))).scalars ().all ()
207- }
220+ role_id_by_name = {r .name : r .id for r in (await session .execute (select (Role ))).scalars ().all ()}
208221
209222 # Role permissions (additive only — never remove perms set by an admin via UI)
210223 existing_rp = set (
0 commit comments