dominus-sdk-python-dev 2.1.8__py3-none-any.whl → 2.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -316,6 +316,75 @@ class AuthNamespace:
316
316
  body={"scope_ids": scope_ids}
317
317
  )
318
318
 
319
+ # Role-tenant junction
320
+ async def get_role_tenants(self, role_id: str) -> List[Dict[str, Any]]:
321
+ """Get tenants assigned to role."""
322
+ return await self._client._request(
323
+ endpoint=f"/api/guardian/roles/{role_id}/tenants",
324
+ method="GET"
325
+ )
326
+
327
+ async def add_role_tenants(self, role_id: str, tenant_ids: List[str]) -> Dict[str, Any]:
328
+ """Add tenants to role."""
329
+ return await self._client._request(
330
+ endpoint=f"/api/guardian/roles/{role_id}/tenants",
331
+ body={"tenant_ids": tenant_ids}
332
+ )
333
+
334
+ async def remove_role_tenants(self, role_id: str, tenant_ids: List[str]) -> Dict[str, Any]:
335
+ """Remove tenants from role."""
336
+ return await self._client._request(
337
+ endpoint=f"/api/guardian/roles/{role_id}/tenants",
338
+ method="DELETE",
339
+ body={"tenant_ids": tenant_ids}
340
+ )
341
+
342
+ # Role-category junction
343
+ async def get_role_categories(self, role_id: str) -> List[Dict[str, Any]]:
344
+ """Get categories assigned to role."""
345
+ return await self._client._request(
346
+ endpoint=f"/api/guardian/roles/{role_id}/categories",
347
+ method="GET"
348
+ )
349
+
350
+ async def add_role_categories(self, role_id: str, category_ids: List[str]) -> Dict[str, Any]:
351
+ """Add categories to role."""
352
+ return await self._client._request(
353
+ endpoint=f"/api/guardian/roles/{role_id}/categories",
354
+ body={"category_ids": category_ids}
355
+ )
356
+
357
+ async def remove_role_categories(self, role_id: str, category_ids: List[str]) -> Dict[str, Any]:
358
+ """Remove categories from role."""
359
+ return await self._client._request(
360
+ endpoint=f"/api/guardian/roles/{role_id}/categories",
361
+ method="DELETE",
362
+ body={"category_ids": category_ids}
363
+ )
364
+
365
+ # Role-subtype junction
366
+ async def get_role_subtypes(self, role_id: str) -> List[Dict[str, Any]]:
367
+ """Get subtypes assigned to role."""
368
+ return await self._client._request(
369
+ endpoint=f"/api/guardian/roles/{role_id}/subtypes",
370
+ method="GET"
371
+ )
372
+
373
+ async def add_role_subtypes(self, role_id: str, subtype_ids: List[str]) -> Dict[str, Any]:
374
+ """Add subtypes to role."""
375
+ return await self._client._request(
376
+ endpoint=f"/api/guardian/roles/{role_id}/subtypes",
377
+ body={"subtype_ids": subtype_ids}
378
+ )
379
+
380
+ async def remove_role_subtypes(self, role_id: str, subtype_ids: List[str]) -> Dict[str, Any]:
381
+ """Remove subtypes from role."""
382
+ return await self._client._request(
383
+ endpoint=f"/api/guardian/roles/{role_id}/subtypes",
384
+ method="DELETE",
385
+ body={"subtype_ids": subtype_ids}
386
+ )
387
+
319
388
  # ========================================
320
389
  # SCOPES
321
390
  # ========================================
@@ -383,6 +452,52 @@ class AuthNamespace:
383
452
  method="DELETE"
384
453
  )
385
454
 
455
+ # Scope-tenant junction
456
+ async def get_scope_tenants(self, scope_id: str) -> List[Dict[str, Any]]:
457
+ """Get tenants assigned to scope."""
458
+ return await self._client._request(
459
+ endpoint=f"/api/guardian/scopes/{scope_id}/tenants",
460
+ method="GET"
461
+ )
462
+
463
+ async def add_scope_tenants(self, scope_id: str, tenant_ids: List[str]) -> Dict[str, Any]:
464
+ """Add tenants to scope."""
465
+ return await self._client._request(
466
+ endpoint=f"/api/guardian/scopes/{scope_id}/tenants",
467
+ body={"tenant_ids": tenant_ids}
468
+ )
469
+
470
+ async def remove_scope_tenants(self, scope_id: str, tenant_ids: List[str]) -> Dict[str, Any]:
471
+ """Remove tenants from scope."""
472
+ return await self._client._request(
473
+ endpoint=f"/api/guardian/scopes/{scope_id}/tenants",
474
+ method="DELETE",
475
+ body={"tenant_ids": tenant_ids}
476
+ )
477
+
478
+ # Scope-category junction
479
+ async def get_scope_categories(self, scope_id: str) -> List[Dict[str, Any]]:
480
+ """Get categories assigned to scope."""
481
+ return await self._client._request(
482
+ endpoint=f"/api/guardian/scopes/{scope_id}/categories",
483
+ method="GET"
484
+ )
485
+
486
+ async def add_scope_categories(self, scope_id: str, category_ids: List[str]) -> Dict[str, Any]:
487
+ """Add categories to scope."""
488
+ return await self._client._request(
489
+ endpoint=f"/api/guardian/scopes/{scope_id}/categories",
490
+ body={"category_ids": category_ids}
491
+ )
492
+
493
+ async def remove_scope_categories(self, scope_id: str, category_ids: List[str]) -> Dict[str, Any]:
494
+ """Remove categories from scope."""
495
+ return await self._client._request(
496
+ endpoint=f"/api/guardian/scopes/{scope_id}/categories",
497
+ method="DELETE",
498
+ body={"category_ids": category_ids}
499
+ )
500
+
386
501
  # ========================================
387
502
  # CLIENTS (PSK/Machine Auth)
388
503
  # ========================================
@@ -490,6 +605,75 @@ class AuthNamespace:
490
605
  body={"tenant_ids": tenant_ids}
491
606
  )
492
607
 
608
+ # Client-role junction
609
+ async def get_client_roles(self, client_id: str) -> List[Dict[str, Any]]:
610
+ """Get roles assigned to client."""
611
+ return await self._client._request(
612
+ endpoint=f"/api/guardian/clients/{client_id}/roles",
613
+ method="GET"
614
+ )
615
+
616
+ async def add_client_roles(self, client_id: str, role_ids: List[str]) -> Dict[str, Any]:
617
+ """Add roles to client."""
618
+ return await self._client._request(
619
+ endpoint=f"/api/guardian/clients/{client_id}/roles",
620
+ body={"role_ids": role_ids}
621
+ )
622
+
623
+ async def remove_client_roles(self, client_id: str, role_ids: List[str]) -> Dict[str, Any]:
624
+ """Remove roles from client."""
625
+ return await self._client._request(
626
+ endpoint=f"/api/guardian/clients/{client_id}/roles",
627
+ method="DELETE",
628
+ body={"role_ids": role_ids}
629
+ )
630
+
631
+ # Client-scope junction
632
+ async def get_client_scopes(self, client_id: str) -> List[Dict[str, Any]]:
633
+ """Get scopes assigned to client."""
634
+ return await self._client._request(
635
+ endpoint=f"/api/guardian/clients/{client_id}/scopes",
636
+ method="GET"
637
+ )
638
+
639
+ async def add_client_scopes(self, client_id: str, scope_ids: List[str]) -> Dict[str, Any]:
640
+ """Add scopes to client."""
641
+ return await self._client._request(
642
+ endpoint=f"/api/guardian/clients/{client_id}/scopes",
643
+ body={"scope_ids": scope_ids}
644
+ )
645
+
646
+ async def remove_client_scopes(self, client_id: str, scope_ids: List[str]) -> Dict[str, Any]:
647
+ """Remove scopes from client."""
648
+ return await self._client._request(
649
+ endpoint=f"/api/guardian/clients/{client_id}/scopes",
650
+ method="DELETE",
651
+ body={"scope_ids": scope_ids}
652
+ )
653
+
654
+ # Client-subtype junction
655
+ async def get_client_subtypes(self, client_id: str) -> List[Dict[str, Any]]:
656
+ """Get subtypes assigned to client."""
657
+ return await self._client._request(
658
+ endpoint=f"/api/guardian/clients/{client_id}/subtypes",
659
+ method="GET"
660
+ )
661
+
662
+ async def add_client_subtypes(self, client_id: str, subtype_ids: List[str]) -> Dict[str, Any]:
663
+ """Add subtypes to client."""
664
+ return await self._client._request(
665
+ endpoint=f"/api/guardian/clients/{client_id}/subtypes",
666
+ body={"subtype_ids": subtype_ids}
667
+ )
668
+
669
+ async def remove_client_subtypes(self, client_id: str, subtype_ids: List[str]) -> Dict[str, Any]:
670
+ """Remove subtypes from client."""
671
+ return await self._client._request(
672
+ endpoint=f"/api/guardian/clients/{client_id}/subtypes",
673
+ method="DELETE",
674
+ body={"subtype_ids": subtype_ids}
675
+ )
676
+
493
677
  # ========================================
494
678
  # TENANTS
495
679
  # ========================================
@@ -703,6 +887,75 @@ class AuthNamespace:
703
887
  method="DELETE"
704
888
  )
705
889
 
890
+ # Subtype-tenant junction
891
+ async def get_subtype_tenants(self, subtype_id: str) -> List[Dict[str, Any]]:
892
+ """Get tenants assigned to subtype."""
893
+ return await self._client._request(
894
+ endpoint=f"/api/guardian/subtypes/{subtype_id}/tenants",
895
+ method="GET"
896
+ )
897
+
898
+ async def add_subtype_tenants(self, subtype_id: str, tenant_ids: List[str]) -> Dict[str, Any]:
899
+ """Add tenants to subtype."""
900
+ return await self._client._request(
901
+ endpoint=f"/api/guardian/subtypes/{subtype_id}/tenants",
902
+ body={"tenant_ids": tenant_ids}
903
+ )
904
+
905
+ async def remove_subtype_tenants(self, subtype_id: str, tenant_ids: List[str]) -> Dict[str, Any]:
906
+ """Remove tenants from subtype."""
907
+ return await self._client._request(
908
+ endpoint=f"/api/guardian/subtypes/{subtype_id}/tenants",
909
+ method="DELETE",
910
+ body={"tenant_ids": tenant_ids}
911
+ )
912
+
913
+ # Subtype-category junction
914
+ async def get_subtype_categories(self, subtype_id: str) -> List[Dict[str, Any]]:
915
+ """Get categories assigned to subtype."""
916
+ return await self._client._request(
917
+ endpoint=f"/api/guardian/subtypes/{subtype_id}/categories",
918
+ method="GET"
919
+ )
920
+
921
+ async def add_subtype_categories(self, subtype_id: str, category_ids: List[str]) -> Dict[str, Any]:
922
+ """Add categories to subtype."""
923
+ return await self._client._request(
924
+ endpoint=f"/api/guardian/subtypes/{subtype_id}/categories",
925
+ body={"category_ids": category_ids}
926
+ )
927
+
928
+ async def remove_subtype_categories(self, subtype_id: str, category_ids: List[str]) -> Dict[str, Any]:
929
+ """Remove categories from subtype."""
930
+ return await self._client._request(
931
+ endpoint=f"/api/guardian/subtypes/{subtype_id}/categories",
932
+ method="DELETE",
933
+ body={"category_ids": category_ids}
934
+ )
935
+
936
+ # Subtype-scope junction
937
+ async def get_subtype_scopes(self, subtype_id: str) -> List[Dict[str, Any]]:
938
+ """Get scopes assigned to subtype."""
939
+ return await self._client._request(
940
+ endpoint=f"/api/guardian/subtypes/{subtype_id}/scopes",
941
+ method="GET"
942
+ )
943
+
944
+ async def add_subtype_scopes(self, subtype_id: str, scope_ids: List[str]) -> Dict[str, Any]:
945
+ """Add scopes to subtype."""
946
+ return await self._client._request(
947
+ endpoint=f"/api/guardian/subtypes/{subtype_id}/scopes",
948
+ body={"scope_ids": scope_ids}
949
+ )
950
+
951
+ async def remove_subtype_scopes(self, subtype_id: str, scope_ids: List[str]) -> Dict[str, Any]:
952
+ """Remove scopes from subtype."""
953
+ return await self._client._request(
954
+ endpoint=f"/api/guardian/subtypes/{subtype_id}/scopes",
955
+ method="DELETE",
956
+ body={"scope_ids": scope_ids}
957
+ )
958
+
706
959
  # ========================================
707
960
  # PAGES
708
961
  # ========================================
@@ -712,10 +965,16 @@ class AuthNamespace:
712
965
  path: str,
713
966
  name: str,
714
967
  description: Optional[str] = None,
715
- is_active: bool = True
968
+ is_active: bool = True,
969
+ show_in_nav: bool = True
716
970
  ) -> Dict[str, Any]:
717
971
  """Create a new page."""
718
- body = {"path": path, "name": name, "is_active": is_active}
972
+ body = {
973
+ "path": path,
974
+ "name": name,
975
+ "is_active": is_active,
976
+ "show_in_nav": show_in_nav
977
+ }
719
978
  if description:
720
979
  body["description"] = description
721
980
 
@@ -753,7 +1012,8 @@ class AuthNamespace:
753
1012
  path: Optional[str] = None,
754
1013
  name: Optional[str] = None,
755
1014
  description: Optional[str] = None,
756
- is_active: Optional[bool] = None
1015
+ is_active: Optional[bool] = None,
1016
+ show_in_nav: Optional[bool] = None
757
1017
  ) -> Dict[str, Any]:
758
1018
  """Update page."""
759
1019
  body = {}
@@ -765,6 +1025,8 @@ class AuthNamespace:
765
1025
  body["description"] = description
766
1026
  if is_active is not None:
767
1027
  body["is_active"] = is_active
1028
+ if show_in_nav is not None:
1029
+ body["show_in_nav"] = show_in_nav
768
1030
 
769
1031
  return await self._client._request(
770
1032
  endpoint=f"/api/guardian/pages/{page_id}",
@@ -833,6 +1095,110 @@ class AuthNamespace:
833
1095
  body={"scope_ids": scope_ids}
834
1096
  )
835
1097
 
1098
+ async def set_page_tenants(self, page_id: str, tenant_ids: List[str]) -> List[Dict[str, Any]]:
1099
+ """Set all tenants for page (replaces existing)."""
1100
+ return await self._client._request(
1101
+ endpoint=f"/api/guardian/pages/{page_id}/tenants",
1102
+ method="PUT",
1103
+ body={"tenant_ids": tenant_ids}
1104
+ )
1105
+
1106
+ # Page-category junction
1107
+ async def get_page_categories(self, page_id: str) -> List[Dict[str, Any]]:
1108
+ """Get categories assigned to page."""
1109
+ return await self._client._request(
1110
+ endpoint=f"/api/guardian/pages/{page_id}/categories",
1111
+ method="GET"
1112
+ )
1113
+
1114
+ async def add_page_categories(self, page_id: str, category_ids: List[str]) -> Dict[str, Any]:
1115
+ """Add categories to page."""
1116
+ return await self._client._request(
1117
+ endpoint=f"/api/guardian/pages/{page_id}/categories",
1118
+ method="POST",
1119
+ body={"category_ids": category_ids}
1120
+ )
1121
+
1122
+ async def remove_page_categories(self, page_id: str, category_ids: List[str]) -> Dict[str, Any]:
1123
+ """Remove categories from page."""
1124
+ return await self._client._request(
1125
+ endpoint=f"/api/guardian/pages/{page_id}/categories",
1126
+ method="DELETE",
1127
+ body={"category_ids": category_ids}
1128
+ )
1129
+
1130
+ async def set_page_categories(self, page_id: str, category_ids: List[str]) -> List[Dict[str, Any]]:
1131
+ """Set all categories for page (replaces existing)."""
1132
+ return await self._client._request(
1133
+ endpoint=f"/api/guardian/pages/{page_id}/categories",
1134
+ method="PUT",
1135
+ body={"category_ids": category_ids}
1136
+ )
1137
+
1138
+ # Page excluded scopes (blocklist - users with these scopes CANNOT access)
1139
+ async def get_page_excluded_scopes(self, page_id: str) -> List[Dict[str, Any]]:
1140
+ """Get excluded scopes for page."""
1141
+ return await self._client._request(
1142
+ endpoint=f"/api/guardian/pages/{page_id}/excluded-scopes",
1143
+ method="GET"
1144
+ )
1145
+
1146
+ async def add_page_excluded_scopes(self, page_id: str, scope_ids: List[str]) -> Dict[str, Any]:
1147
+ """Add excluded scopes to page."""
1148
+ return await self._client._request(
1149
+ endpoint=f"/api/guardian/pages/{page_id}/excluded-scopes",
1150
+ method="POST",
1151
+ body={"scope_ids": scope_ids}
1152
+ )
1153
+
1154
+ async def remove_page_excluded_scopes(self, page_id: str, scope_ids: List[str]) -> Dict[str, Any]:
1155
+ """Remove excluded scopes from page."""
1156
+ return await self._client._request(
1157
+ endpoint=f"/api/guardian/pages/{page_id}/excluded-scopes",
1158
+ method="DELETE",
1159
+ body={"scope_ids": scope_ids}
1160
+ )
1161
+
1162
+ async def set_page_excluded_scopes(self, page_id: str, scope_ids: List[str]) -> List[Dict[str, Any]]:
1163
+ """Set all excluded scopes for page (replaces existing)."""
1164
+ return await self._client._request(
1165
+ endpoint=f"/api/guardian/pages/{page_id}/excluded-scopes",
1166
+ method="PUT",
1167
+ body={"scope_ids": scope_ids}
1168
+ )
1169
+
1170
+ # Page excluded roles (blocklist - users with these roles CANNOT access)
1171
+ async def get_page_excluded_roles(self, page_id: str) -> List[Dict[str, Any]]:
1172
+ """Get excluded roles for page."""
1173
+ return await self._client._request(
1174
+ endpoint=f"/api/guardian/pages/{page_id}/excluded-roles",
1175
+ method="GET"
1176
+ )
1177
+
1178
+ async def add_page_excluded_roles(self, page_id: str, role_ids: List[str]) -> Dict[str, Any]:
1179
+ """Add excluded roles to page."""
1180
+ return await self._client._request(
1181
+ endpoint=f"/api/guardian/pages/{page_id}/excluded-roles",
1182
+ method="POST",
1183
+ body={"role_ids": role_ids}
1184
+ )
1185
+
1186
+ async def remove_page_excluded_roles(self, page_id: str, role_ids: List[str]) -> Dict[str, Any]:
1187
+ """Remove excluded roles from page."""
1188
+ return await self._client._request(
1189
+ endpoint=f"/api/guardian/pages/{page_id}/excluded-roles",
1190
+ method="DELETE",
1191
+ body={"role_ids": role_ids}
1192
+ )
1193
+
1194
+ async def set_page_excluded_roles(self, page_id: str, role_ids: List[str]) -> List[Dict[str, Any]]:
1195
+ """Set all excluded roles for page (replaces existing)."""
1196
+ return await self._client._request(
1197
+ endpoint=f"/api/guardian/pages/{page_id}/excluded-roles",
1198
+ method="PUT",
1199
+ body={"role_ids": role_ids}
1200
+ )
1201
+
836
1202
  # ========================================
837
1203
  # NAVIGATION
838
1204
  # ========================================
@@ -841,14 +1207,39 @@ class AuthNamespace:
841
1207
  self,
842
1208
  title: str,
843
1209
  icon: Optional[str] = None,
1210
+ description: Optional[str] = None,
844
1211
  page_id: Optional[str] = None,
845
1212
  parent_id: Optional[str] = None,
846
- sort_order: int = 0
1213
+ item_type: str = "link",
1214
+ is_active: bool = True,
1215
+ sort_order: int = 0,
1216
+ is_expanded_default: bool = False
847
1217
  ) -> Dict[str, Any]:
848
- """Create a new navigation item."""
849
- body = {"title": title, "sort_order": sort_order}
1218
+ """
1219
+ Create a new navigation item.
1220
+
1221
+ Args:
1222
+ title: Display title
1223
+ icon: Icon name/class
1224
+ description: Description text
1225
+ page_id: Associated page ID
1226
+ parent_id: Parent nav item ID (for hierarchical nav)
1227
+ item_type: Type - 'link', 'header', or 'group_label'
1228
+ is_active: Whether item is active
1229
+ sort_order: Sort position
1230
+ is_expanded_default: Whether group is expanded by default
1231
+ """
1232
+ body = {
1233
+ "title": title,
1234
+ "sort_order": sort_order,
1235
+ "item_type": item_type,
1236
+ "is_active": is_active,
1237
+ "is_expanded_default": is_expanded_default
1238
+ }
850
1239
  if icon:
851
1240
  body["icon"] = icon
1241
+ if description:
1242
+ body["description"] = description
852
1243
  if page_id:
853
1244
  body["page_id"] = page_id
854
1245
  if parent_id:
@@ -868,12 +1259,40 @@ class AuthNamespace:
868
1259
 
869
1260
  async def list_nav_items(
870
1261
  self,
1262
+ tenant_id: Optional[str] = None,
1263
+ parent_id: Optional[str] = None,
1264
+ is_active: Optional[bool] = None,
871
1265
  limit: int = 100,
872
- offset: int = 0
1266
+ offset: int = 0,
1267
+ order_by: Optional[str] = None,
1268
+ order_desc: Optional[bool] = None
873
1269
  ) -> Dict[str, Any]:
874
- """List all navigation items."""
1270
+ """
1271
+ List navigation items with optional filters.
1272
+
1273
+ Args:
1274
+ tenant_id: Filter by tenant ID
1275
+ parent_id: Filter by parent nav item ID
1276
+ is_active: Filter by active status
1277
+ limit: Max items to return
1278
+ offset: Pagination offset
1279
+ order_by: Sort field
1280
+ order_desc: Sort descending
1281
+ """
1282
+ params = f"?limit={limit}&offset={offset}"
1283
+ if tenant_id:
1284
+ params += f"&tenant_id={tenant_id}"
1285
+ if parent_id:
1286
+ params += f"&parent_id={parent_id}"
1287
+ if is_active is not None:
1288
+ params += f"&is_active={str(is_active).lower()}"
1289
+ if order_by:
1290
+ params += f"&order_by={order_by}"
1291
+ if order_desc is not None:
1292
+ params += f"&order_desc={str(order_desc).lower()}"
1293
+
875
1294
  return await self._client._request(
876
- endpoint=f"/api/guardian/nav-items?limit={limit}&offset={offset}",
1295
+ endpoint=f"/api/guardian/nav-items{params}",
877
1296
  method="GET"
878
1297
  )
879
1298
 
@@ -882,7 +1301,13 @@ class AuthNamespace:
882
1301
  nav_id: str,
883
1302
  title: Optional[str] = None,
884
1303
  icon: Optional[str] = None,
885
- sort_order: Optional[int] = None
1304
+ description: Optional[str] = None,
1305
+ page_id: Optional[str] = None,
1306
+ parent_id: Optional[str] = None,
1307
+ item_type: Optional[str] = None,
1308
+ is_active: Optional[bool] = None,
1309
+ sort_order: Optional[int] = None,
1310
+ is_expanded_default: Optional[bool] = None
886
1311
  ) -> Dict[str, Any]:
887
1312
  """Update navigation item."""
888
1313
  body = {}
@@ -890,8 +1315,20 @@ class AuthNamespace:
890
1315
  body["title"] = title
891
1316
  if icon is not None:
892
1317
  body["icon"] = icon
1318
+ if description is not None:
1319
+ body["description"] = description
1320
+ if page_id is not None:
1321
+ body["page_id"] = page_id
1322
+ if parent_id is not None:
1323
+ body["parent_id"] = parent_id
1324
+ if item_type is not None:
1325
+ body["item_type"] = item_type
1326
+ if is_active is not None:
1327
+ body["is_active"] = is_active
893
1328
  if sort_order is not None:
894
1329
  body["sort_order"] = sort_order
1330
+ if is_expanded_default is not None:
1331
+ body["is_expanded_default"] = is_expanded_default
895
1332
 
896
1333
  return await self._client._request(
897
1334
  endpoint=f"/api/guardian/nav-items/{nav_id}",
@@ -929,6 +1366,98 @@ class AuthNamespace:
929
1366
  body={"tenant_ids": tenant_ids}
930
1367
  )
931
1368
 
1369
+ # Nav-scope junction
1370
+ async def get_nav_scopes(self, nav_id: str) -> List[Dict[str, Any]]:
1371
+ """Get scopes assigned to nav item."""
1372
+ return await self._client._request(
1373
+ endpoint=f"/api/guardian/nav-items/{nav_id}/scopes",
1374
+ method="GET"
1375
+ )
1376
+
1377
+ async def add_nav_scopes(self, nav_id: str, scope_ids: List[str]) -> Dict[str, Any]:
1378
+ """Add scopes to nav item."""
1379
+ return await self._client._request(
1380
+ endpoint=f"/api/guardian/nav-items/{nav_id}/scopes",
1381
+ body={"scope_ids": scope_ids}
1382
+ )
1383
+
1384
+ async def remove_nav_scopes(self, nav_id: str, scope_ids: List[str]) -> Dict[str, Any]:
1385
+ """Remove scopes from nav item."""
1386
+ return await self._client._request(
1387
+ endpoint=f"/api/guardian/nav-items/{nav_id}/scopes",
1388
+ method="DELETE",
1389
+ body={"scope_ids": scope_ids}
1390
+ )
1391
+
1392
+ # Nav-role junction
1393
+ async def get_nav_roles(self, nav_id: str) -> List[Dict[str, Any]]:
1394
+ """Get roles assigned to nav item."""
1395
+ return await self._client._request(
1396
+ endpoint=f"/api/guardian/nav-items/{nav_id}/roles",
1397
+ method="GET"
1398
+ )
1399
+
1400
+ async def add_nav_roles(self, nav_id: str, role_ids: List[str]) -> Dict[str, Any]:
1401
+ """Add roles to nav item."""
1402
+ return await self._client._request(
1403
+ endpoint=f"/api/guardian/nav-items/{nav_id}/roles",
1404
+ body={"role_ids": role_ids}
1405
+ )
1406
+
1407
+ async def remove_nav_roles(self, nav_id: str, role_ids: List[str]) -> Dict[str, Any]:
1408
+ """Remove roles from nav item."""
1409
+ return await self._client._request(
1410
+ endpoint=f"/api/guardian/nav-items/{nav_id}/roles",
1411
+ method="DELETE",
1412
+ body={"role_ids": role_ids}
1413
+ )
1414
+
1415
+ # Nav-subtype junction
1416
+ async def get_nav_subtypes(self, nav_id: str) -> List[Dict[str, Any]]:
1417
+ """Get subtypes assigned to nav item."""
1418
+ return await self._client._request(
1419
+ endpoint=f"/api/guardian/nav-items/{nav_id}/subtypes",
1420
+ method="GET"
1421
+ )
1422
+
1423
+ async def add_nav_subtypes(self, nav_id: str, subtype_ids: List[str]) -> Dict[str, Any]:
1424
+ """Add subtypes to nav item."""
1425
+ return await self._client._request(
1426
+ endpoint=f"/api/guardian/nav-items/{nav_id}/subtypes",
1427
+ body={"subtype_ids": subtype_ids}
1428
+ )
1429
+
1430
+ async def remove_nav_subtypes(self, nav_id: str, subtype_ids: List[str]) -> Dict[str, Any]:
1431
+ """Remove subtypes from nav item."""
1432
+ return await self._client._request(
1433
+ endpoint=f"/api/guardian/nav-items/{nav_id}/subtypes",
1434
+ method="DELETE",
1435
+ body={"subtype_ids": subtype_ids}
1436
+ )
1437
+
1438
+ # Nav-category junction
1439
+ async def get_nav_categories(self, nav_id: str) -> List[Dict[str, Any]]:
1440
+ """Get categories assigned to nav item."""
1441
+ return await self._client._request(
1442
+ endpoint=f"/api/guardian/nav-items/{nav_id}/categories",
1443
+ method="GET"
1444
+ )
1445
+
1446
+ async def add_nav_categories(self, nav_id: str, category_ids: List[str]) -> Dict[str, Any]:
1447
+ """Add categories to nav item."""
1448
+ return await self._client._request(
1449
+ endpoint=f"/api/guardian/nav-items/{nav_id}/categories",
1450
+ body={"category_ids": category_ids}
1451
+ )
1452
+
1453
+ async def remove_nav_categories(self, nav_id: str, category_ids: List[str]) -> Dict[str, Any]:
1454
+ """Remove categories from nav item."""
1455
+ return await self._client._request(
1456
+ endpoint=f"/api/guardian/nav-items/{nav_id}/categories",
1457
+ method="DELETE",
1458
+ body={"category_ids": category_ids}
1459
+ )
1460
+
932
1461
  # ========================================
933
1462
  # SECURE TABLES
934
1463
  # ========================================