@jmruthers/pace-core 0.5.109 → 0.5.111

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.
Files changed (240) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/{AuthService-DrHrvXNZ.d.ts → AuthService-CVgsgtaZ.d.ts} +8 -0
  3. package/dist/{DataTable-5HITILXS.js → DataTable-5W2HVLLV.js} +8 -8
  4. package/dist/{UnifiedAuthProvider-A7I23UCN.js → UnifiedAuthProvider-LUM3QLS5.js} +3 -3
  5. package/dist/{api-5I3E47G2.js → api-SIZPFBFX.js} +5 -3
  6. package/dist/{audit-65VNHEV2.js → audit-5JI5T3SL.js} +2 -2
  7. package/dist/{chunk-P72NKAT5.js → chunk-2BIDKXQU.js} +157 -120
  8. package/dist/chunk-2BIDKXQU.js.map +1 -0
  9. package/dist/{chunk-S4D3Z723.js → chunk-ACYQNYHB.js} +7 -7
  10. package/dist/{chunk-D6MEKC27.js → chunk-EFVQBYFN.js} +2 -2
  11. package/dist/{chunk-EZ64QG2I.js → chunk-I5YM5BGS.js} +2 -2
  12. package/dist/{chunk-Q7APDV6H.js → chunk-IWJYNWXN.js} +13 -5
  13. package/dist/chunk-IWJYNWXN.js.map +1 -0
  14. package/dist/{chunk-YFMENCR4.js → chunk-JE2GFA3O.js} +3 -3
  15. package/dist/{chunk-AUXS7XSO.js → chunk-MW73E7SP.js} +35 -11
  16. package/dist/chunk-MW73E7SP.js.map +1 -0
  17. package/dist/{chunk-F6TSYCKP.js → chunk-PXXS26G5.js} +68 -29
  18. package/dist/chunk-PXXS26G5.js.map +1 -0
  19. package/dist/{chunk-UW2DE6JX.js → chunk-TD4BXGPE.js} +4 -4
  20. package/dist/{chunk-EYSXQ756.js → chunk-TDFBX7KJ.js} +2 -2
  21. package/dist/{chunk-WWNOVFDC.js → chunk-UGVU7L7N.js} +52 -90
  22. package/dist/chunk-UGVU7L7N.js.map +1 -0
  23. package/dist/{chunk-2W4WKJVF.js → chunk-X7SPKHYZ.js} +290 -255
  24. package/dist/chunk-X7SPKHYZ.js.map +1 -0
  25. package/dist/{chunk-3TKTL5AZ.js → chunk-ZL45MG76.js} +60 -60
  26. package/dist/chunk-ZL45MG76.js.map +1 -0
  27. package/dist/components.js +10 -10
  28. package/dist/hooks.d.ts +11 -1
  29. package/dist/hooks.js +9 -7
  30. package/dist/hooks.js.map +1 -1
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.js +13 -13
  33. package/dist/providers.d.ts +2 -2
  34. package/dist/providers.js +2 -2
  35. package/dist/rbac/index.d.ts +46 -29
  36. package/dist/rbac/index.js +9 -9
  37. package/dist/utils.js +1 -1
  38. package/docs/api/classes/ColumnFactory.md +1 -1
  39. package/docs/api/classes/ErrorBoundary.md +1 -1
  40. package/docs/api/classes/InvalidScopeError.md +4 -4
  41. package/docs/api/classes/MissingUserContextError.md +4 -4
  42. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  43. package/docs/api/classes/PermissionDeniedError.md +4 -4
  44. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  45. package/docs/api/classes/RBACAuditManager.md +8 -8
  46. package/docs/api/classes/RBACCache.md +8 -8
  47. package/docs/api/classes/RBACEngine.md +9 -8
  48. package/docs/api/classes/RBACError.md +4 -4
  49. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  50. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  51. package/docs/api/classes/StorageUtils.md +1 -1
  52. package/docs/api/enums/FileCategory.md +1 -1
  53. package/docs/api/interfaces/AggregateConfig.md +1 -1
  54. package/docs/api/interfaces/ButtonProps.md +1 -1
  55. package/docs/api/interfaces/CardProps.md +1 -1
  56. package/docs/api/interfaces/ColorPalette.md +1 -1
  57. package/docs/api/interfaces/ColorShade.md +1 -1
  58. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  59. package/docs/api/interfaces/DataRecord.md +1 -1
  60. package/docs/api/interfaces/DataTableAction.md +1 -1
  61. package/docs/api/interfaces/DataTableColumn.md +1 -1
  62. package/docs/api/interfaces/DataTableProps.md +1 -1
  63. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  64. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  65. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  66. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  67. package/docs/api/interfaces/FileMetadata.md +1 -1
  68. package/docs/api/interfaces/FileReference.md +1 -1
  69. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  70. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  71. package/docs/api/interfaces/FileUploadProps.md +1 -1
  72. package/docs/api/interfaces/FooterProps.md +1 -1
  73. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  74. package/docs/api/interfaces/InputProps.md +1 -1
  75. package/docs/api/interfaces/LabelProps.md +1 -1
  76. package/docs/api/interfaces/LoginFormProps.md +1 -1
  77. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  78. package/docs/api/interfaces/NavigationContextType.md +1 -1
  79. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  80. package/docs/api/interfaces/NavigationItem.md +1 -1
  81. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  82. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  83. package/docs/api/interfaces/Organisation.md +1 -1
  84. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  85. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  86. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  87. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  88. package/docs/api/interfaces/PaceAppLayoutProps.md +27 -27
  89. package/docs/api/interfaces/PaceLoginPageProps.md +4 -4
  90. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  91. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  92. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  93. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  94. package/docs/api/interfaces/PaletteData.md +1 -1
  95. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  96. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  97. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  98. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  99. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  100. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  101. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  102. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  103. package/docs/api/interfaces/RBACConfig.md +19 -8
  104. package/docs/api/interfaces/RBACLogger.md +5 -5
  105. package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
  106. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  107. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  108. package/docs/api/interfaces/RouteConfig.md +19 -6
  109. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  110. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  111. package/docs/api/interfaces/StorageConfig.md +1 -1
  112. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  113. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  114. package/docs/api/interfaces/StorageListOptions.md +1 -1
  115. package/docs/api/interfaces/StorageListResult.md +1 -1
  116. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  117. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  118. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  119. package/docs/api/interfaces/StyleImport.md +1 -1
  120. package/docs/api/interfaces/SwitchProps.md +1 -1
  121. package/docs/api/interfaces/ToastActionElement.md +1 -1
  122. package/docs/api/interfaces/ToastProps.md +1 -1
  123. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  124. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  125. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  126. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  127. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  128. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  129. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  130. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  131. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  132. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  133. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  134. package/docs/api/interfaces/UserEventAccess.md +1 -1
  135. package/docs/api/interfaces/UserMenuProps.md +1 -1
  136. package/docs/api/interfaces/UserProfile.md +1 -1
  137. package/docs/api/modules.md +44 -43
  138. package/docs/api-reference/hooks.md +8 -4
  139. package/docs/architecture/rpc-function-standards.md +3 -1
  140. package/docs/best-practices/common-patterns.md +3 -3
  141. package/docs/best-practices/deployment.md +10 -4
  142. package/docs/best-practices/performance.md +11 -3
  143. package/docs/core-concepts/organisations.md +8 -8
  144. package/docs/core-concepts/permissions.md +133 -72
  145. package/docs/documentation-index.md +0 -2
  146. package/docs/migration/rbac-migration.md +65 -66
  147. package/docs/rbac/README.md +114 -38
  148. package/docs/rbac/advanced-patterns.md +15 -22
  149. package/docs/rbac/api-reference.md +63 -16
  150. package/docs/rbac/examples.md +12 -12
  151. package/docs/rbac/getting-started.md +19 -19
  152. package/docs/rbac/quick-start.md +110 -35
  153. package/docs/rbac/troubleshooting.md +127 -3
  154. package/package.json +1 -1
  155. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +913 -0
  156. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +609 -0
  157. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +434 -0
  158. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +120 -0
  159. package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +519 -0
  160. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +316 -0
  161. package/src/components/DataTable/examples/__tests__/InitialPageSizeExample.test.tsx +211 -0
  162. package/src/components/FileUpload/FileUpload.tsx +2 -8
  163. package/src/components/NavigationMenu/NavigationMenu.test.tsx +38 -4
  164. package/src/components/NavigationMenu/NavigationMenu.tsx +71 -6
  165. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +193 -63
  166. package/src/components/PaceAppLayout/PaceAppLayout.tsx +102 -135
  167. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +41 -2
  168. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +61 -6
  169. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +71 -21
  170. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +113 -41
  171. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +155 -45
  172. package/src/components/PaceLoginPage/PaceLoginPage.tsx +30 -1
  173. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +63 -5
  174. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +156 -72
  175. package/src/hooks/__tests__/useRBAC.unit.test.ts +4 -38
  176. package/src/hooks/index.ts +1 -1
  177. package/src/hooks/useFileDisplay.ts +51 -0
  178. package/src/hooks/usePermissionCache.test.ts +112 -68
  179. package/src/hooks/usePermissionCache.ts +55 -15
  180. package/src/rbac/README.md +81 -39
  181. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +3 -3
  182. package/src/rbac/__tests__/engine.comprehensive.test.ts +15 -6
  183. package/src/rbac/__tests__/rbac-core.test.tsx +1 -1
  184. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +57 -4
  185. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +3 -2
  186. package/src/rbac/adapters.tsx +4 -4
  187. package/src/rbac/api.test.ts +39 -15
  188. package/src/rbac/api.ts +27 -9
  189. package/src/rbac/audit.test.ts +2 -2
  190. package/src/rbac/audit.ts +14 -5
  191. package/src/rbac/cache.test.ts +12 -0
  192. package/src/rbac/cache.ts +29 -9
  193. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +1 -1
  194. package/src/rbac/components/NavigationGuard.tsx +14 -14
  195. package/src/rbac/components/NavigationProvider.test.tsx +1 -1
  196. package/src/rbac/components/PagePermissionGuard.tsx +22 -38
  197. package/src/rbac/components/PagePermissionProvider.test.tsx +1 -1
  198. package/src/rbac/components/PermissionEnforcer.tsx +19 -15
  199. package/src/rbac/components/RoleBasedRouter.tsx +16 -9
  200. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +123 -107
  201. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
  202. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +121 -103
  203. package/src/rbac/config.ts +2 -0
  204. package/src/rbac/docs/event-based-apps.md +6 -6
  205. package/src/rbac/engine.ts +27 -7
  206. package/src/rbac/hooks/useCan.test.ts +29 -2
  207. package/src/rbac/hooks/usePermissions.test.ts +25 -25
  208. package/src/rbac/hooks/usePermissions.ts +47 -23
  209. package/src/rbac/hooks/useRBAC.simple.test.ts +1 -8
  210. package/src/rbac/hooks/useRBAC.test.ts +3 -40
  211. package/src/rbac/hooks/useRBAC.ts +0 -55
  212. package/src/rbac/hooks/useResolvedScope.ts +23 -31
  213. package/src/rbac/permissions.test.ts +11 -7
  214. package/src/rbac/security.test.ts +2 -2
  215. package/src/rbac/security.ts +23 -8
  216. package/src/rbac/types.test.ts +2 -2
  217. package/src/rbac/types.ts +1 -2
  218. package/src/services/EventService.ts +41 -13
  219. package/src/services/__tests__/EventService.test.ts +25 -4
  220. package/src/services/interfaces/IEventService.ts +1 -0
  221. package/src/utils/file-reference.ts +9 -0
  222. package/dist/chunk-2W4WKJVF.js.map +0 -1
  223. package/dist/chunk-3TKTL5AZ.js.map +0 -1
  224. package/dist/chunk-AUXS7XSO.js.map +0 -1
  225. package/dist/chunk-F6TSYCKP.js.map +0 -1
  226. package/dist/chunk-P72NKAT5.js.map +0 -1
  227. package/dist/chunk-Q7APDV6H.js.map +0 -1
  228. package/dist/chunk-WWNOVFDC.js.map +0 -1
  229. package/docs/rbac/breaking-changes-v3.md +0 -222
  230. package/docs/rbac/migration-guide.md +0 -260
  231. /package/dist/{DataTable-5HITILXS.js.map → DataTable-5W2HVLLV.js.map} +0 -0
  232. /package/dist/{UnifiedAuthProvider-A7I23UCN.js.map → UnifiedAuthProvider-LUM3QLS5.js.map} +0 -0
  233. /package/dist/{api-5I3E47G2.js.map → api-SIZPFBFX.js.map} +0 -0
  234. /package/dist/{audit-65VNHEV2.js.map → audit-5JI5T3SL.js.map} +0 -0
  235. /package/dist/{chunk-S4D3Z723.js.map → chunk-ACYQNYHB.js.map} +0 -0
  236. /package/dist/{chunk-D6MEKC27.js.map → chunk-EFVQBYFN.js.map} +0 -0
  237. /package/dist/{chunk-EZ64QG2I.js.map → chunk-I5YM5BGS.js.map} +0 -0
  238. /package/dist/{chunk-YFMENCR4.js.map → chunk-JE2GFA3O.js.map} +0 -0
  239. /package/dist/{chunk-UW2DE6JX.js.map → chunk-TD4BXGPE.js.map} +0 -0
  240. /package/dist/{chunk-EYSXQ756.js.map → chunk-TDFBX7KJ.js.map} +0 -0
@@ -128,7 +128,7 @@ Permissions for specific features or capabilities:
128
128
 
129
129
  // Notifications
130
130
  'send:notifications'
131
- 'manage:notifications'
131
+ 'update:notifications'
132
132
 
133
133
  // API Access
134
134
  'api:read'
@@ -141,26 +141,34 @@ Permissions for specific features or capabilities:
141
141
  ### Basic Permission Checking
142
142
 
143
143
  ```typescript
144
- import { useRBAC } from '@jmruthers/pace-core';
144
+ import { useCan } from '@jmruthers/pace-core/rbac';
145
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
145
146
 
146
147
  function UserManagement() {
147
- const { hasPermission } = useRBAC();
148
+ const { user, selectedOrganisationId } = useUnifiedAuth();
149
+ const { can: canRead } = useCan(
150
+ user?.id || '',
151
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
152
+ 'read:users'
153
+ );
154
+ const { can: canCreate } = useCan(
155
+ user?.id || '',
156
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
157
+ 'create:users'
158
+ );
159
+ const { can: canDelete } = useCan(
160
+ user?.id || '',
161
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
162
+ 'delete:users'
163
+ );
148
164
 
149
165
  return (
150
166
  <div>
151
167
  <h1>User Management</h1>
152
168
 
153
- {hasPermission('read:users') && (
154
- <UserList />
155
- )}
156
-
157
- {hasPermission('create:users') && (
158
- <CreateUserButton />
159
- )}
160
-
161
- {hasPermission('delete:users') && (
162
- <DeleteUserButton />
163
- )}
169
+ {canRead && <UserList />}
170
+ {canCreate && <CreateUserButton />}
171
+ {canDelete && <DeleteUserButton />}
164
172
  </div>
165
173
  );
166
174
  }
@@ -169,24 +177,26 @@ function UserManagement() {
169
177
  ### Resource-Based Permission Checking
170
178
 
171
179
  ```typescript
172
- import { useRBAC } from '@jmruthers/pace-core';
180
+ import { useCan } from '@jmruthers/pace-core/rbac';
181
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
173
182
 
174
183
  function EventActions({ event }) {
175
- const { canAccess } = useRBAC();
184
+ const { user, selectedOrganisationId, selectedEventId } = useUnifiedAuth();
185
+ const scope = {
186
+ organisationId: selectedOrganisationId || '',
187
+ eventId: selectedEventId || undefined,
188
+ appId: undefined
189
+ };
190
+
191
+ const { can: canRead } = useCan(user?.id || '', scope, 'read:events');
192
+ const { can: canUpdate } = useCan(user?.id || '', scope, 'update:events');
193
+ const { can: canDelete } = useCan(user?.id || '', scope, 'delete:events');
176
194
 
177
195
  return (
178
196
  <div>
179
- {canAccess('events', 'read') && (
180
- <ViewEventButton event={event} />
181
- )}
182
-
183
- {canAccess('events', 'update') && (
184
- <EditEventButton event={event} />
185
- )}
186
-
187
- {canAccess('events', 'delete') && (
188
- <DeleteEventButton event={event} />
189
- )}
197
+ {canRead && <ViewEventButton event={event} />}
198
+ {canUpdate && <EditEventButton event={event} />}
199
+ {canDelete && <DeleteEventButton event={event} />}
190
200
  </div>
191
201
  );
192
202
  }
@@ -237,7 +247,6 @@ const PERMISSIONS = {
237
247
  ORG_CREATE: 'create:organisations',
238
248
  ORG_UPDATE: 'update:organisations',
239
249
  ORG_DELETE: 'delete:organisations',
240
- ORG_MANAGE: 'manage:organisations',
241
250
  } as const;
242
251
  ```
243
252
 
@@ -260,7 +269,7 @@ const ROLE_PERMISSIONS = {
260
269
  PERMISSIONS.ORG_CREATE,
261
270
  PERMISSIONS.ORG_UPDATE,
262
271
  PERMISSIONS.ORG_DELETE,
263
- PERMISSIONS.ORG_MANAGE,
272
+ // Note: ORG_MANAGE removed - use ORG_UPDATE instead
264
273
  ],
265
274
 
266
275
  manager: [
@@ -285,14 +294,19 @@ const ROLE_PERMISSIONS = {
285
294
  ### Component-Level Enforcement
286
295
 
287
296
  ```typescript
288
- import { useRBAC } from '@jmruthers/pace-core';
297
+ import { useCan } from '@jmruthers/pace-core/rbac';
298
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
289
299
 
290
300
  function ProtectedComponent({ children, permission }) {
291
- const { hasPermission } = useRBAC();
301
+ const { user, selectedOrganisationId } = useUnifiedAuth();
302
+ const { can, isLoading } = useCan(
303
+ user?.id || '',
304
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
305
+ permission
306
+ );
292
307
 
293
- if (!hasPermission(permission)) {
294
- return null; // Or return an access denied component
295
- }
308
+ if (isLoading) return <div>Checking permissions...</div>;
309
+ if (!can) return null; // Or return an access denied component
296
310
 
297
311
  return children;
298
312
  }
@@ -326,14 +340,20 @@ function ProtectedRoute({ children, page }) {
326
340
  ### Data-Level Enforcement
327
341
 
328
342
  ```typescript
329
- import { useRBAC } from '@jmruthers/pace-core';
343
+ import { useCan } from '@jmruthers/pace-core/rbac';
344
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
330
345
 
331
346
  function DataTable({ data, actions }) {
332
- const { canAccess } = useRBAC();
333
-
334
- const availableActions = actions.filter(action =>
335
- canAccess(action.resource, action.operation)
336
- );
347
+ const { user, selectedOrganisationId } = useUnifiedAuth();
348
+ const scope = { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined };
349
+
350
+ // Check permissions for each action
351
+ const availableActions = actions.filter(action => {
352
+ const permission = `${action.operation}:${action.resource}`;
353
+ // Note: For multiple permissions, consider using usePermissions hook
354
+ // or useMultiplePermissions for better performance
355
+ return true; // Simplified - in practice, check each permission
356
+ });
337
357
 
338
358
  return (
339
359
  <table>
@@ -361,17 +381,21 @@ const permission = buildPermissionString('users', 'read'); // 'read:users'
361
381
  ### Checking Multiple Permissions
362
382
 
363
383
  ```typescript
364
- import { useRBAC } from '@jmruthers/pace-core';
384
+ import { usePermissions } from '@jmruthers/pace-core/rbac';
385
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
365
386
 
366
387
  function AdvancedComponent() {
367
- const { hasPermission } = useRBAC();
388
+ const { user, selectedOrganisationId } = useUnifiedAuth();
389
+ const { hasPermission, hasAllPermissions } = usePermissions(
390
+ user?.id || '',
391
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined }
392
+ );
368
393
 
369
- const canManageUsers = hasPermission('manage:users') ||
370
- (hasPermission('read:users') && hasPermission('update:users'));
394
+ const canUpdateUsers = hasAllPermissions(['read:users', 'update:users']);
371
395
 
372
396
  return (
373
397
  <div>
374
- {canManageUsers && <UserManagementPanel />}
398
+ {canUpdateUsers && <UserManagementPanel />}
375
399
  </div>
376
400
  );
377
401
  }
@@ -380,10 +404,15 @@ function AdvancedComponent() {
380
404
  ### Conditional Permission Rendering
381
405
 
382
406
  ```typescript
383
- import { useRBAC } from '@jmruthers/pace-core';
407
+ import { usePermissions } from '@jmruthers/pace-core/rbac';
408
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
384
409
 
385
410
  function ConditionalActions() {
386
- const { hasPermission } = useRBAC();
411
+ const { user, selectedOrganisationId } = useUnifiedAuth();
412
+ const { hasPermission } = usePermissions(
413
+ user?.id || '',
414
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined }
415
+ );
387
416
 
388
417
  return (
389
418
  <div>
@@ -430,7 +459,7 @@ const USER_PERMISSIONS = {
430
459
  CREATE: 'create:users',
431
460
  UPDATE: 'update:users',
432
461
  DELETE: 'delete:users',
433
- MANAGE: 'manage:users',
462
+ // Note: 'manage' operation has been removed - use UPDATE instead
434
463
  } as const;
435
464
 
436
465
  const EVENT_PERMISSIONS = {
@@ -445,15 +474,22 @@ const EVENT_PERMISSIONS = {
445
474
  ### 3. Use Permission HOCs
446
475
 
447
476
  ```typescript
477
+ import { useCan } from '@jmruthers/pace-core/rbac';
478
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
479
+
448
480
  // Create a Higher-Order Component for permission checking
449
481
  function withPermission(permission: string) {
450
482
  return function<P extends object>(Component: React.ComponentType<P>) {
451
483
  return function PermissionWrapper(props: P) {
452
- const { hasPermission } = useRBAC();
484
+ const { user, selectedOrganisationId } = useUnifiedAuth();
485
+ const { can, isLoading } = useCan(
486
+ user?.id || '',
487
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
488
+ permission
489
+ );
453
490
 
454
- if (!hasPermission(permission)) {
455
- return null;
456
- }
491
+ if (isLoading) return <div>Checking permissions...</div>;
492
+ if (!can) return null;
457
493
 
458
494
  return <Component {...props} />;
459
495
  };
@@ -467,19 +503,23 @@ const ProtectedUserList = withPermission('read:users')(UserList);
467
503
  ### 4. Implement Permission Caching
468
504
 
469
505
  ```typescript
470
- import { useMemo } from 'react';
471
- import { useRBAC } from '@jmruthers/pace-core';
506
+ import { usePermissions } from '@jmruthers/pace-core/rbac';
507
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
472
508
 
473
509
  function OptimizedComponent() {
474
- const { hasPermission } = useRBAC();
510
+ const { user, selectedOrganisationId } = useUnifiedAuth();
511
+ const { hasPermission } = usePermissions(
512
+ user?.id || '',
513
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined }
514
+ );
475
515
 
476
- // Cache permission checks
477
- const permissions = useMemo(() => ({
516
+ // Permission map is already cached by usePermissions hook
517
+ const permissions = {
478
518
  canRead: hasPermission('read:users'),
479
519
  canCreate: hasPermission('create:users'),
480
520
  canUpdate: hasPermission('update:users'),
481
521
  canDelete: hasPermission('delete:users'),
482
- }), [hasPermission]);
522
+ };
483
523
 
484
524
  return (
485
525
  <div>
@@ -495,18 +535,24 @@ function OptimizedComponent() {
495
535
  ### 5. Handle Permission Loading States
496
536
 
497
537
  ```typescript
498
- import { useRBAC } from '@jmruthers/pace-core';
538
+ import { useCan } from '@jmruthers/pace-core/rbac';
539
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
499
540
 
500
541
  function PermissionAwareComponent() {
501
- const { hasPermission, loading } = useRBAC();
542
+ const { user, selectedOrganisationId } = useUnifiedAuth();
543
+ const { can, isLoading } = useCan(
544
+ user?.id || '',
545
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
546
+ 'read:users'
547
+ );
502
548
 
503
- if (loading) {
549
+ if (isLoading) {
504
550
  return <div>Loading permissions...</div>;
505
551
  }
506
552
 
507
553
  return (
508
554
  <div>
509
- {hasPermission('read:users') && <UserList />}
555
+ {can && <UserList />}
510
556
  </div>
511
557
  );
512
558
  }
@@ -653,16 +699,23 @@ function getResourcePermissions(resource: string) {
653
699
  const FEATURE_PERMISSIONS = {
654
700
  ANALYTICS: 'view:analytics',
655
701
  EXPORT: 'export:data',
656
- NOTIFICATIONS: 'manage:notifications',
657
- SETTINGS: 'manage:settings',
702
+ NOTIFICATIONS: 'update:notifications',
703
+ SETTINGS: 'update:settings',
658
704
  } as const;
659
705
 
706
+ import { useCan } from '@jmruthers/pace-core/rbac';
707
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
708
+
660
709
  function FeatureFlag({ permission, children }) {
661
- const { hasPermission } = useRBAC();
710
+ const { user, selectedOrganisationId } = useUnifiedAuth();
711
+ const { can, isLoading } = useCan(
712
+ user?.id || '',
713
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
714
+ permission
715
+ );
662
716
 
663
- if (!hasPermission(permission)) {
664
- return null;
665
- }
717
+ if (isLoading) return <div>Checking permissions...</div>;
718
+ if (!can) return null;
666
719
 
667
720
  return children;
668
721
  }
@@ -714,17 +767,25 @@ function ConditionalActions({ item }) {
714
767
  ### Debugging Tools
715
768
 
716
769
  ```typescript
717
- import { useRBAC } from '@jmruthers/pace-core';
770
+ import { useRBAC, usePermissions } from '@jmruthers/pace-core/rbac';
771
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
718
772
 
719
773
  function PermissionDebugger() {
720
- const { user, roles, permissions, hasPermission } = useRBAC();
774
+ const { user, selectedOrganisationId } = useUnifiedAuth();
775
+ const rbac = useRBAC(); // For role information
776
+ const { permissions, hasPermission } = usePermissions(
777
+ user?.id || '',
778
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined }
779
+ );
721
780
 
722
781
  return (
723
782
  <div>
724
783
  <h3>Permission Debug Info</h3>
725
784
  <p>User: {user?.email}</p>
726
- <p>Roles: {roles.map(r => r.name).join(', ')}</p>
727
- <p>Permissions: {permissions.map(p => p.name).join(', ')}</p>
785
+ <p>Global Role: {rbac.globalRole || 'None'}</p>
786
+ <p>Organisation Role: {rbac.organisationRole || 'None'}</p>
787
+ <p>Event Role: {rbac.eventAppRole || 'None'}</p>
788
+ <p>Permissions: {Object.keys(permissions).filter(k => permissions[k as Permission]).join(', ')}</p>
728
789
 
729
790
  <h4>Permission Tests</h4>
730
791
  <p>Can read users: {hasPermission('read:users') ? 'Yes' : 'No'}</p>
@@ -54,8 +54,6 @@ This index mirrors the folder layout in `packages/core/docs/` so teams can quick
54
54
  - [Advanced patterns](./rbac/advanced-patterns.md)
55
55
  - [Super admin guide](./rbac/super-admin-guide.md)
56
56
  - [RLS integration](./rbac/rbac-rls-integration.md)
57
- - [Migration guide](./rbac/migration-guide.md)
58
- - [Breaking changes v3](./rbac/breaking-changes-v3.md)
59
57
  - [Troubleshooting](./rbac/troubleshooting.md)
60
58
  - [Legacy RLS README](./rbac/README-rbac-rls-integration.md)
61
59
 
@@ -95,15 +95,27 @@ The new RBAC system includes enhanced security features that are automatically e
95
95
 
96
96
  ### 2. Hook API Changes
97
97
 
98
- **Old (Legacy)**:
98
+ **Old (Legacy - REMOVED)**:
99
99
  ```tsx
100
- const { hasPermission, roles, permissions } = useRBAC();
100
+ // REMOVED - useRBAC().hasPermission() no longer exists
101
+ const { hasPermission } = useRBAC();
101
102
  ```
102
103
 
103
104
  **New (RBAC Module)**:
104
105
  ```tsx
105
- const { hasPermission, isLoading } = useCan();
106
- const { permissions, isLoading: permissionsLoading } = usePermissions({ userId, scope });
106
+ // Use useCan() for single permission checks
107
+ import { useCan } from '@jmruthers/pace-core/rbac';
108
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
109
+
110
+ const { user, selectedOrganisationId } = useUnifiedAuth();
111
+ const { can, isLoading } = useCan(
112
+ user?.id || '',
113
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
114
+ 'read:users'
115
+ );
116
+
117
+ // ✅ Use usePermissions() for permission maps
118
+ const { permissions, isLoading: permissionsLoading } = usePermissions(user?.id || '', scope);
107
119
  ```
108
120
 
109
121
  ### 3. Permission Check Changes
@@ -190,11 +202,11 @@ import { useCan, usePermissions, PermissionGuard } from '@jmruthers/pace-core/rb
190
202
 
191
203
  ### Step 2: Update Hook Usage
192
204
 
193
- **Before (Legacy)**:
205
+ **Before (Legacy - REMOVED)**:
194
206
  ```tsx
207
+ // ❌ REMOVED - useRBAC().hasPermission() no longer exists
195
208
  function UserActions() {
196
- const { hasPermission, roles, permissions } = useRBAC();
197
-
209
+ const { hasPermission } = useRBAC(); // This API has been removed
198
210
  const canEdit = hasPermission('update:users');
199
211
  const canDelete = hasPermission('delete:users');
200
212
 
@@ -209,28 +221,25 @@ function UserActions() {
209
221
 
210
222
  **After (New RBAC)**:
211
223
  ```tsx
212
- function UserActions({ userId, scope }) {
213
- const { hasPermission, isLoading } = useCan();
214
- const [canEdit, setCanEdit] = useState(false);
215
- const [canDelete, setCanDelete] = useState(false);
224
+ import { useCan } from '@jmruthers/pace-core/rbac';
225
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
216
226
 
217
- useEffect(() => {
218
- const checkPermissions = async () => {
219
- if (!isLoading) {
220
- const [editPerm, deletePerm] = await Promise.all([
221
- hasPermission('update:users', { userId, scope }),
222
- hasPermission('delete:users', { userId, scope })
223
- ]);
224
-
225
- setCanEdit(editPerm);
226
- setCanDelete(deletePerm);
227
- }
228
- };
229
-
230
- checkPermissions();
231
- }, [hasPermission, isLoading, userId, scope]);
227
+ function UserActions() {
228
+ const { user, selectedOrganisationId } = useUnifiedAuth();
229
+ const scope = { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined };
230
+
231
+ const { can: canEdit, isLoading: isLoadingEdit } = useCan(
232
+ user?.id || '',
233
+ scope,
234
+ 'update:users'
235
+ );
236
+ const { can: canDelete, isLoading: isLoadingDelete } = useCan(
237
+ user?.id || '',
238
+ scope,
239
+ 'delete:users'
240
+ );
232
241
 
233
- if (isLoading) return <div>Loading permissions...</div>;
242
+ if (isLoadingEdit || isLoadingDelete) return <div>Loading permissions...</div>;
234
243
 
235
244
  return (
236
245
  <div>
@@ -347,32 +356,34 @@ export async function POST(request: Request) {
347
356
 
348
357
  ### Pattern 1: Simple Permission Check
349
358
 
350
- **Before**:
359
+ **Before (REMOVED)**:
351
360
  ```tsx
361
+ // ❌ REMOVED - useRBAC().hasPermission() no longer exists
352
362
  const { hasPermission } = useRBAC();
353
363
  const canEdit = hasPermission('update:users');
354
364
  ```
355
365
 
356
366
  **After**:
357
367
  ```tsx
358
- const { hasPermission, isLoading } = useCan();
359
- const [canEdit, setCanEdit] = useState(false);
368
+ import { useCan } from '@jmruthers/pace-core/rbac';
369
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
370
+
371
+ const { user, selectedOrganisationId } = useUnifiedAuth();
372
+ const { can: canEdit, isLoading } = useCan(
373
+ user?.id || '',
374
+ { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined },
375
+ 'update:users'
376
+ );
360
377
 
361
- useEffect(() => {
362
- const checkPermission = async () => {
363
- if (!isLoading) {
364
- const editPerm = await hasPermission('update:users', { userId, scope });
365
- setCanEdit(editPerm);
366
- }
367
- };
368
- checkPermission();
369
- }, [hasPermission, isLoading, userId, scope]);
378
+ if (isLoading) return <div>Loading...</div>;
379
+ return canEdit ? <EditButton /> : null;
370
380
  ```
371
381
 
372
382
  ### Pattern 2: Multiple Permission Checks
373
383
 
374
- **Before**:
384
+ **Before (REMOVED)**:
375
385
  ```tsx
386
+ // ❌ REMOVED - useRBAC().hasPermission() no longer exists
376
387
  const { hasPermission } = useRBAC();
377
388
  const canRead = hasPermission('read:users');
378
389
  const canCreate = hasPermission('create:users');
@@ -382,32 +393,20 @@ const canDelete = hasPermission('delete:users');
382
393
 
383
394
  **After**:
384
395
  ```tsx
385
- import { useMultiplePermissions } from '@jmruthers/pace-core/rbac';
386
-
387
- const { checkMultiple, isLoading } = useMultiplePermissions();
388
- const [permissions, setPermissions] = useState({});
389
-
390
- useEffect(() => {
391
- const checkAllPermissions = async () => {
392
- if (!isLoading) {
393
- const results = await checkMultiple([
394
- { userId, scope, permission: 'read:users' },
395
- { userId, scope, permission: 'create:users' },
396
- { userId, scope, permission: 'update:users' },
397
- { userId, scope, permission: 'delete:users' }
398
- ]);
399
-
400
- const permMap = results.reduce((acc, result) => {
401
- acc[result.permission] = result.allowed;
402
- return acc;
403
- }, {});
404
-
405
- setPermissions(permMap);
406
- }
407
- };
408
-
409
- checkAllPermissions();
410
- }, [checkMultiple, isLoading, userId, scope]);
396
+ import { usePermissions } from '@jmruthers/pace-core/rbac';
397
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
398
+
399
+ const { user, selectedOrganisationId } = useUnifiedAuth();
400
+ const scope = { organisationId: selectedOrganisationId || '', eventId: undefined, appId: undefined };
401
+ const { hasPermission, isLoading } = usePermissions(user?.id || '', scope);
402
+
403
+ // Synchronous checks against loaded permission map
404
+ const canRead = hasPermission('read:users');
405
+ const canCreate = hasPermission('create:users');
406
+ const canUpdate = hasPermission('update:users');
407
+ const canDelete = hasPermission('delete:users');
408
+
409
+ if (isLoading) return <div>Loading permissions...</div>;
411
410
  ```
412
411
 
413
412
  ### Pattern 3: Component Guards