@jmruthers/pace-core 0.5.142 → 0.5.144

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 (125) hide show
  1. package/dist/{chunk-TUJSIWX6.js → chunk-FC46D3KC.js} +49 -20
  2. package/dist/chunk-FC46D3KC.js.map +1 -0
  3. package/dist/components.js +1 -1
  4. package/dist/index.js +1 -1
  5. package/docs/api/classes/ColumnFactory.md +1 -1
  6. package/docs/api/classes/ErrorBoundary.md +1 -1
  7. package/docs/api/classes/InvalidScopeError.md +1 -1
  8. package/docs/api/classes/MissingUserContextError.md +1 -1
  9. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  10. package/docs/api/classes/PermissionDeniedError.md +1 -1
  11. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  12. package/docs/api/classes/RBACAuditManager.md +1 -1
  13. package/docs/api/classes/RBACCache.md +1 -1
  14. package/docs/api/classes/RBACEngine.md +1 -1
  15. package/docs/api/classes/RBACError.md +1 -1
  16. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  17. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  18. package/docs/api/classes/StorageUtils.md +1 -1
  19. package/docs/api/enums/FileCategory.md +1 -1
  20. package/docs/api/interfaces/AggregateConfig.md +1 -1
  21. package/docs/api/interfaces/BadgeProps.md +1 -1
  22. package/docs/api/interfaces/ButtonProps.md +1 -1
  23. package/docs/api/interfaces/CalendarProps.md +1 -1
  24. package/docs/api/interfaces/CardProps.md +1 -1
  25. package/docs/api/interfaces/ColorPalette.md +1 -1
  26. package/docs/api/interfaces/ColorShade.md +1 -1
  27. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  28. package/docs/api/interfaces/DataRecord.md +1 -1
  29. package/docs/api/interfaces/DataTableAction.md +1 -1
  30. package/docs/api/interfaces/DataTableColumn.md +1 -1
  31. package/docs/api/interfaces/DataTableProps.md +1 -1
  32. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  33. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  34. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  35. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  36. package/docs/api/interfaces/EventLogoProps.md +1 -1
  37. package/docs/api/interfaces/ExportColumn.md +1 -1
  38. package/docs/api/interfaces/ExportOptions.md +1 -1
  39. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  40. package/docs/api/interfaces/FileMetadata.md +1 -1
  41. package/docs/api/interfaces/FileReference.md +1 -1
  42. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  43. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  44. package/docs/api/interfaces/FileUploadProps.md +1 -1
  45. package/docs/api/interfaces/FooterProps.md +1 -1
  46. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  47. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  48. package/docs/api/interfaces/InputProps.md +1 -1
  49. package/docs/api/interfaces/LabelProps.md +1 -1
  50. package/docs/api/interfaces/LoginFormProps.md +1 -1
  51. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  52. package/docs/api/interfaces/NavigationContextType.md +1 -1
  53. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  54. package/docs/api/interfaces/NavigationItem.md +1 -1
  55. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  56. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  57. package/docs/api/interfaces/Organisation.md +1 -1
  58. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  59. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  60. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  61. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  62. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  63. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  64. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  65. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  66. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  67. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  68. package/docs/api/interfaces/PaletteData.md +1 -1
  69. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  70. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  71. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  72. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  73. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  74. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  75. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  76. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  77. package/docs/api/interfaces/RBACConfig.md +1 -1
  78. package/docs/api/interfaces/RBACLogger.md +1 -1
  79. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  80. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  81. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  82. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  83. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  84. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  85. package/docs/api/interfaces/RouteConfig.md +1 -1
  86. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  87. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  88. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  89. package/docs/api/interfaces/StorageConfig.md +1 -1
  90. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  91. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  92. package/docs/api/interfaces/StorageListOptions.md +1 -1
  93. package/docs/api/interfaces/StorageListResult.md +1 -1
  94. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  95. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  96. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  97. package/docs/api/interfaces/StyleImport.md +1 -1
  98. package/docs/api/interfaces/SwitchProps.md +1 -1
  99. package/docs/api/interfaces/TabsContentProps.md +1 -1
  100. package/docs/api/interfaces/TabsListProps.md +1 -1
  101. package/docs/api/interfaces/TabsProps.md +1 -1
  102. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  103. package/docs/api/interfaces/TextareaProps.md +1 -1
  104. package/docs/api/interfaces/ToastActionElement.md +1 -1
  105. package/docs/api/interfaces/ToastProps.md +1 -1
  106. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  107. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  108. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  109. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  110. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  111. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  112. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  113. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  114. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  115. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  116. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  117. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  118. package/docs/api/interfaces/UserEventAccess.md +1 -1
  119. package/docs/api/interfaces/UserMenuProps.md +1 -1
  120. package/docs/api/interfaces/UserProfile.md +1 -1
  121. package/docs/api/modules.md +2 -2
  122. package/docs/rbac/README.md +9 -4
  123. package/package.json +1 -1
  124. package/src/components/NavigationMenu/NavigationMenu.tsx +82 -21
  125. package/dist/chunk-TUJSIWX6.js.map +0 -1
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / RouteConfig
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / RouteConfig
2
2
 
3
3
  # Interface: RouteConfig
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / SecureDataContextType
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / SecureDataContextType
2
2
 
3
3
  # Interface: SecureDataContextType
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / SecureDataProviderProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / SecureDataProviderProps
2
2
 
3
3
  # Interface: SecureDataProviderProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / SessionRestorationLoaderProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / SessionRestorationLoaderProps
2
2
 
3
3
  # Interface: SessionRestorationLoaderProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / StorageConfig
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / StorageConfig
2
2
 
3
3
  # Interface: StorageConfig
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / StorageFileInfo
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / StorageFileInfo
2
2
 
3
3
  # Interface: StorageFileInfo
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / StorageFileMetadata
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / StorageFileMetadata
2
2
 
3
3
  # Interface: StorageFileMetadata
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / StorageListOptions
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / StorageListOptions
2
2
 
3
3
  # Interface: StorageListOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / StorageListResult
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / StorageListResult
2
2
 
3
3
  # Interface: StorageListResult
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / StorageUploadOptions
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / StorageUploadOptions
2
2
 
3
3
  # Interface: StorageUploadOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / StorageUploadResult
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / StorageUploadResult
2
2
 
3
3
  # Interface: StorageUploadResult
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / StorageUrlOptions
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / StorageUrlOptions
2
2
 
3
3
  # Interface: StorageUrlOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / StyleImport
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / StyleImport
2
2
 
3
3
  # Interface: StyleImport
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / SwitchProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / SwitchProps
2
2
 
3
3
  # Interface: SwitchProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / TabsContentProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / TabsContentProps
2
2
 
3
3
  # Interface: TabsContentProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / TabsListProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / TabsListProps
2
2
 
3
3
  # Interface: TabsListProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / TabsProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / TabsProps
2
2
 
3
3
  # Interface: TabsProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / TabsTriggerProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / TabsTriggerProps
2
2
 
3
3
  # Interface: TabsTriggerProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / TextareaProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / TextareaProps
2
2
 
3
3
  # Interface: TextareaProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / ToastActionElement
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / ToastActionElement
2
2
 
3
3
  # Interface: ToastActionElement
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / ToastProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / ToastProps
2
2
 
3
3
  # Interface: ToastProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UnifiedAuthContextType
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UnifiedAuthContextType
2
2
 
3
3
  # Interface: UnifiedAuthContextType
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UnifiedAuthProviderProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UnifiedAuthProviderProps
2
2
 
3
3
  # Interface: UnifiedAuthProviderProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UseInactivityTrackerOptions
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UseInactivityTrackerOptions
2
2
 
3
3
  # Interface: UseInactivityTrackerOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UseInactivityTrackerReturn
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UseInactivityTrackerReturn
2
2
 
3
3
  # Interface: UseInactivityTrackerReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UsePublicEventOptions
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UsePublicEventOptions
2
2
 
3
3
  # Interface: UsePublicEventOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UsePublicEventReturn
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UsePublicEventReturn
2
2
 
3
3
  # Interface: UsePublicEventReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UsePublicFileDisplayOptions
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UsePublicFileDisplayOptions
2
2
 
3
3
  # Interface: UsePublicFileDisplayOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UsePublicFileDisplayReturn
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UsePublicFileDisplayReturn
2
2
 
3
3
  # Interface: UsePublicFileDisplayReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UsePublicRouteParamsReturn
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UsePublicRouteParamsReturn
2
2
 
3
3
  # Interface: UsePublicRouteParamsReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UseResolvedScopeOptions
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UseResolvedScopeOptions
2
2
 
3
3
  # Interface: UseResolvedScopeOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UseResolvedScopeReturn
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UseResolvedScopeReturn
2
2
 
3
3
  # Interface: UseResolvedScopeReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UseResourcePermissionsOptions
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UseResourcePermissionsOptions
2
2
 
3
3
  # Interface: UseResourcePermissionsOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UserEventAccess
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UserEventAccess
2
2
 
3
3
  # Interface: UserEventAccess
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UserMenuProps
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UserMenuProps
2
2
 
3
3
  # Interface: UserMenuProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.142](../README.md) / [Exports](../modules.md) / UserProfile
1
+ [@jmruthers/pace-core - v0.5.144](../README.md) / [Exports](../modules.md) / UserProfile
2
2
 
3
3
  # Interface: UserProfile
4
4
 
@@ -1,6 +1,6 @@
1
- [@jmruthers/pace-core - v0.5.142](README.md) / Exports
1
+ [@jmruthers/pace-core - v0.5.144](README.md) / Exports
2
2
 
3
- # @jmruthers/pace-core - v0.5.142
3
+ # @jmruthers/pace-core - v0.5.144
4
4
 
5
5
  **`File`**
6
6
 
@@ -188,15 +188,18 @@ if (appConfig?.requires_event) {
188
188
 
189
189
  ```tsx
190
190
  import { UnifiedAuthProvider, OrganisationProvider } from '@jmruthers/pace-core';
191
- import { setRBACAppName } from '@jmruthers/pace-core/utils';
192
191
 
193
- // CRITICAL: Set app name globally for RBAC resolution
192
+ // CRITICAL: App name is automatically resolved from environment variable
193
+ // Make sure VITE_APP_NAME (or NEXT_PUBLIC_APP_NAME) is set in your .env file
194
+ // Optionally, you can also call setRBACAppName() to override:
195
+ // import { setRBACAppName } from '@jmruthers/pace-core/utils';
196
+ // setRBACAppName('your-app-name');
197
+
194
198
  const APP_NAME = import.meta.env.VITE_APP_NAME;
195
- setRBACAppName(APP_NAME);
196
199
 
197
200
  function App() {
198
201
  return (
199
- <UnifiedAuthProvider supabaseClient={supabase}>
202
+ <UnifiedAuthProvider supabaseClient={supabase} appName={APP_NAME}>
200
203
  <OrganisationProvider>
201
204
  <YourApp />
202
205
  </OrganisationProvider>
@@ -205,6 +208,8 @@ function App() {
205
208
  }
206
209
  ```
207
210
 
211
+ **Note**: The `appName` prop on `UnifiedAuthProvider` is used for other features. RBAC resolution automatically uses the environment variable (`VITE_APP_NAME` or `NEXT_PUBLIC_APP_NAME`). You can optionally call `setRBACAppName()` if you need to override the environment variable.
212
+
208
213
  ### 2. Protect Pages with PagePermissionGuard
209
214
 
210
215
  **⚠️ CRITICAL: Always use `PagePermissionGuard` for page-level access. This is the ONLY way to ensure permissions are checked correctly.**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmruthers/pace-core",
3
- "version": "0.5.142",
3
+ "version": "0.5.144",
4
4
  "description": "Clean, modern React component library with Tailwind v4 styling and native utilities",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -437,14 +437,24 @@ export const NavigationMenu = React.forwardRef<
437
437
  logger.warn('NavigationMenu', 'useRBAC not available, permission filtering disabled');
438
438
  }
439
439
 
440
+ // Get event context state for checking readiness
441
+ // Store the raw value to check if it's undefined (tests without event provider)
442
+ const eventLoadingRaw = authContext?.eventLoading;
443
+ const eventLoading = eventLoadingRaw ?? false;
444
+ const selectedEvent = authContext?.selectedEvent || null;
445
+ // Check org context readiness: use isContextReady if available, otherwise fall back to checking selectedOrganisation
446
+ // This handles both production (with isContextReady) and test scenarios (without it)
447
+ const orgContextReady = authContext?.isContextReady ?? (authContext?.selectedOrganisation?.id ? true : false);
448
+
440
449
  // Get resolved scope for permission checks
450
+ // Note: Always call useResolvedScope (hooks must be called unconditionally)
451
+ // When filterByPermissions is false, we'll simply ignore the resolved scope
441
452
  const { supabase } = authContext || {};
442
453
  const { selectedOrganisation } = authContext || {};
443
- const selectedEvent = authContext?.selectedEvent || null;
444
- const { resolvedScope, isLoading: scopeLoading } = useResolvedScope({
445
- supabase: supabase || null,
446
- selectedOrganisationId: selectedOrganisation?.id || null,
447
- selectedEventId: selectedEvent?.event_id || null
454
+ const { resolvedScope, isLoading: scopeLoading, error: scopeError } = useResolvedScope({
455
+ supabase: filterByPermissions ? (supabase || null) : null,
456
+ selectedOrganisationId: filterByPermissions ? (selectedOrganisation?.id || null) : null,
457
+ selectedEventId: filterByPermissions ? (selectedEvent?.event_id || null) : null
448
458
  });
449
459
 
450
460
  // Stabilize scope object to prevent unnecessary permission refetches
@@ -457,12 +467,30 @@ export const NavigationMenu = React.forwardRef<
457
467
  appId: undefined
458
468
  });
459
469
 
460
- // Only update stable scope when scope is resolved (not loading) AND values actually changed
470
+ // Build scope from resolvedScope if available, otherwise fall back to context values
471
+ // This handles the case where useResolvedScope errored initially but context is now ready
472
+ const effectiveScope = React.useMemo(() => {
473
+ if (!scopeLoading && resolvedScope?.organisationId) {
474
+ // Use resolved scope if available
475
+ return resolvedScope;
476
+ } else if (!scopeLoading && selectedOrganisation?.id) {
477
+ // Fall back to building scope from context if resolvedScope is null but context is ready
478
+ // This handles the case where useResolvedScope errored but context is now available
479
+ return {
480
+ organisationId: selectedOrganisation.id,
481
+ eventId: selectedEvent?.event_id || undefined,
482
+ appId: undefined // App ID will be resolved by usePermissions if needed
483
+ };
484
+ }
485
+ return null;
486
+ }, [scopeLoading, resolvedScope, selectedOrganisation?.id, selectedEvent?.event_id]);
487
+
488
+ // Only update stable scope when effective scope is available AND values actually changed
461
489
  // This prevents triggering permission refetches during scope transitions
462
- if (!scopeLoading && resolvedScope?.organisationId) {
463
- const newOrgId = resolvedScope.organisationId;
464
- const newEventId = resolvedScope.eventId;
465
- const newAppId = resolvedScope.appId;
490
+ if (effectiveScope?.organisationId) {
491
+ const newOrgId = effectiveScope.organisationId;
492
+ const newEventId = effectiveScope.eventId;
493
+ const newAppId = effectiveScope.appId;
466
494
 
467
495
  // Only update if values actually changed
468
496
  if (stableScopeRef.current.organisationId !== newOrgId ||
@@ -474,7 +502,7 @@ export const NavigationMenu = React.forwardRef<
474
502
  appId: newAppId
475
503
  };
476
504
  }
477
- } else if (!scopeLoading && !resolvedScope) {
505
+ } else if (!scopeLoading && !effectiveScope) {
478
506
  // Only reset if we had a previous value and scope is resolved - don't clear during loading
479
507
  if (stableScopeRef.current.organisationId !== '') {
480
508
  stableScopeRef.current = {
@@ -504,12 +532,36 @@ export const NavigationMenu = React.forwardRef<
504
532
  // Security: If filtering is enabled but we're missing required context or still loading, show NO items
505
533
  // This prevents security risk of showing items before permissions are verified
506
534
  if (filterByPermissions) {
507
- // During initial load or when scope is loading, show nothing
508
- if (!authContext || !rbacContext || scopeLoading || !resolvedScope?.organisationId) {
535
+ // CRITICAL: Wait for BOTH organisation AND event context to be ready before checking permissions
536
+ // This prevents the error "No organisation or event context available" when event context is still loading
537
+ const isOrgContextReady = orgContextReady && selectedOrganisation?.id;
538
+ // Event context is ready when not loading
539
+ // If eventLoadingRaw is undefined (tests without event provider), consider it ready
540
+ // Only wait for event context if we're actually loading events
541
+ const isEventContextReady = eventLoadingRaw === undefined ? true : !eventLoading;
542
+
543
+ // Check if we have valid context for permission checking
544
+ // Use actual context values, not just resolvedScope, because resolvedScope might be null
545
+ // if useResolvedScope errored initially but context is now ready
546
+ const hasValidContext = isOrgContextReady && isEventContextReady;
547
+
548
+ // If scope is still loading or we don't have valid context yet, show nothing
549
+ // BUT: If scope errored but context is now ready, retry (don't block forever)
550
+ const shouldWaitForScope = scopeLoading || (!hasValidContext);
551
+ const shouldRetryAfterError = scopeError && hasValidContext && !scopeLoading;
552
+
553
+ // During initial load or when scope/context is loading, show nothing
554
+ if (!authContext || !rbacContext || (shouldWaitForScope && !shouldRetryAfterError)) {
509
555
  // Still loading - show nothing to prevent security risk
556
+ // Note: We check both org and event context readiness to prevent premature permission checks
557
+ // Exception: If scope errored but context is now ready, we'll retry below
510
558
  return [];
511
559
  }
512
560
 
561
+ // If scope errored but context is now ready, we can proceed with permission checks
562
+ // The resolvedScope might be null, but we'll use the actual context values
563
+ // usePermissions will handle the scope resolution internally
564
+
513
565
  // During permission refetch (after initial load), preserve previous items if we have them
514
566
  // This prevents navigation from disappearing when switching events
515
567
  if (permissionsLoading) {
@@ -709,26 +761,35 @@ export const NavigationMenu = React.forwardRef<
709
761
  permissionMap,
710
762
  hasAnyPermission,
711
763
  scopeLoading,
764
+ scopeError,
712
765
  permissionsLoading,
713
766
  resolvedScope,
714
- auditLog
767
+ effectiveScope,
768
+ auditLog,
769
+ // Add event context state to dependencies so we re-check permissions when event context becomes available
770
+ eventLoadingRaw,
771
+ eventLoading,
772
+ selectedEvent,
773
+ orgContextReady,
774
+ selectedOrganisation?.id
715
775
  ]);
716
776
 
717
777
  // Log navigation access attempts for debugging
718
778
  React.useEffect(() => {
719
779
  if (auditLog && authContext) {
780
+ // Find the current navigation item to log its actual permissions
781
+ const currentItem = items?.find(item => item.href === currentPath || item.id === 'navigation-menu');
720
782
  logger.debug('NavigationMenu', 'Navigation access attempt:', {
721
- itemId: 'navigation-menu',
722
- label: 'Navigation Menu',
783
+ itemId: currentItem?.id || 'navigation-menu',
784
+ label: currentItem?.label || 'Navigation Menu',
723
785
  href: currentPath,
724
- // RBAC properties removed - use useRBAC() hook instead
725
- permissions: null,
726
- roles: null,
727
- accessLevel: null,
786
+ permissions: currentItem?.permissions || null,
787
+ roles: currentItem?.roles || null,
788
+ accessLevel: currentItem?.accessLevel || null,
728
789
  timestamp: new Date().toISOString()
729
790
  });
730
791
  }
731
- }, [auditLog, authContext, currentPath]);
792
+ }, [auditLog, authContext, currentPath, items]);
732
793
 
733
794
 
734
795
  // Handle keyboard navigation for hierarchical mode