@jmruthers/pace-core 0.5.145 → 0.5.147

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 (136) hide show
  1. package/dist/{DataTable-AKZ6GRWF.js → DataTable-VWAHYZAB.js} +3 -3
  2. package/dist/{chunk-NVVYDA5H.js → chunk-B6R63NR5.js} +2 -2
  3. package/dist/{chunk-E2LWA55X.js → chunk-GROECFVN.js} +3 -3
  4. package/dist/{chunk-WBK6ZKTF.js → chunk-M57AT6C2.js} +2 -2
  5. package/dist/{chunk-4LTN3DVN.js → chunk-MYLOSYK5.js} +42 -6
  6. package/dist/chunk-MYLOSYK5.js.map +1 -0
  7. package/dist/components.js +3 -3
  8. package/dist/index.js +4 -4
  9. package/dist/rbac/index.js +2 -2
  10. package/dist/utils.js +1 -1
  11. package/docs/api/classes/ColumnFactory.md +1 -1
  12. package/docs/api/classes/ErrorBoundary.md +1 -1
  13. package/docs/api/classes/InvalidScopeError.md +1 -1
  14. package/docs/api/classes/MissingUserContextError.md +1 -1
  15. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  16. package/docs/api/classes/PermissionDeniedError.md +1 -1
  17. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  18. package/docs/api/classes/RBACAuditManager.md +1 -1
  19. package/docs/api/classes/RBACCache.md +1 -1
  20. package/docs/api/classes/RBACEngine.md +1 -1
  21. package/docs/api/classes/RBACError.md +1 -1
  22. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  23. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  24. package/docs/api/classes/StorageUtils.md +1 -1
  25. package/docs/api/enums/FileCategory.md +1 -1
  26. package/docs/api/interfaces/AggregateConfig.md +1 -1
  27. package/docs/api/interfaces/BadgeProps.md +1 -1
  28. package/docs/api/interfaces/ButtonProps.md +1 -1
  29. package/docs/api/interfaces/CalendarProps.md +1 -1
  30. package/docs/api/interfaces/CardProps.md +1 -1
  31. package/docs/api/interfaces/ColorPalette.md +1 -1
  32. package/docs/api/interfaces/ColorShade.md +1 -1
  33. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  34. package/docs/api/interfaces/DataRecord.md +1 -1
  35. package/docs/api/interfaces/DataTableAction.md +1 -1
  36. package/docs/api/interfaces/DataTableColumn.md +1 -1
  37. package/docs/api/interfaces/DataTableProps.md +1 -1
  38. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  39. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  40. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  41. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  42. package/docs/api/interfaces/EventLogoProps.md +1 -1
  43. package/docs/api/interfaces/ExportColumn.md +1 -1
  44. package/docs/api/interfaces/ExportOptions.md +1 -1
  45. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  46. package/docs/api/interfaces/FileMetadata.md +1 -1
  47. package/docs/api/interfaces/FileReference.md +1 -1
  48. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  49. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  50. package/docs/api/interfaces/FileUploadProps.md +1 -1
  51. package/docs/api/interfaces/FooterProps.md +1 -1
  52. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  53. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  54. package/docs/api/interfaces/InputProps.md +1 -1
  55. package/docs/api/interfaces/LabelProps.md +1 -1
  56. package/docs/api/interfaces/LoginFormProps.md +1 -1
  57. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  58. package/docs/api/interfaces/NavigationContextType.md +1 -1
  59. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  60. package/docs/api/interfaces/NavigationItem.md +1 -1
  61. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  62. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  63. package/docs/api/interfaces/Organisation.md +1 -1
  64. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  65. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  66. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  67. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  68. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  69. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  70. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  71. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  72. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  73. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  74. package/docs/api/interfaces/PaletteData.md +1 -1
  75. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  76. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  77. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  78. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  79. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  80. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  81. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  82. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  83. package/docs/api/interfaces/RBACConfig.md +1 -1
  84. package/docs/api/interfaces/RBACLogger.md +1 -1
  85. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  86. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  87. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  88. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  89. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  90. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  91. package/docs/api/interfaces/RouteConfig.md +1 -1
  92. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  93. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  94. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  95. package/docs/api/interfaces/StorageConfig.md +1 -1
  96. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  97. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  98. package/docs/api/interfaces/StorageListOptions.md +1 -1
  99. package/docs/api/interfaces/StorageListResult.md +1 -1
  100. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  101. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  102. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  103. package/docs/api/interfaces/StyleImport.md +1 -1
  104. package/docs/api/interfaces/SwitchProps.md +1 -1
  105. package/docs/api/interfaces/TabsContentProps.md +1 -1
  106. package/docs/api/interfaces/TabsListProps.md +1 -1
  107. package/docs/api/interfaces/TabsProps.md +1 -1
  108. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  109. package/docs/api/interfaces/TextareaProps.md +1 -1
  110. package/docs/api/interfaces/ToastActionElement.md +1 -1
  111. package/docs/api/interfaces/ToastProps.md +1 -1
  112. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  113. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  114. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  115. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  116. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  117. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  118. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  119. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  120. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  121. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  122. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  123. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  124. package/docs/api/interfaces/UserEventAccess.md +1 -1
  125. package/docs/api/interfaces/UserMenuProps.md +1 -1
  126. package/docs/api/interfaces/UserProfile.md +1 -1
  127. package/docs/api/modules.md +2 -2
  128. package/docs/rbac/RBAC_EVENT_CONTEXT_LOADING.md +222 -0
  129. package/docs/rbac/RBAC_V0.5.147_FIX.md +117 -0
  130. package/package.json +1 -1
  131. package/src/rbac/hooks/useRBAC.ts +51 -5
  132. package/dist/chunk-4LTN3DVN.js.map +0 -1
  133. /package/dist/{DataTable-AKZ6GRWF.js.map → DataTable-VWAHYZAB.js.map} +0 -0
  134. /package/dist/{chunk-NVVYDA5H.js.map → chunk-B6R63NR5.js.map} +0 -0
  135. /package/dist/{chunk-E2LWA55X.js.map → chunk-GROECFVN.js.map} +0 -0
  136. /package/dist/{chunk-WBK6ZKTF.js.map → chunk-M57AT6C2.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UsePublicEventOptions
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UsePublicEventOptions
2
2
 
3
3
  # Interface: UsePublicEventOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UsePublicEventReturn
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UsePublicEventReturn
2
2
 
3
3
  # Interface: UsePublicEventReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UsePublicFileDisplayOptions
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UsePublicFileDisplayOptions
2
2
 
3
3
  # Interface: UsePublicFileDisplayOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UsePublicFileDisplayReturn
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UsePublicFileDisplayReturn
2
2
 
3
3
  # Interface: UsePublicFileDisplayReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UsePublicRouteParamsReturn
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UsePublicRouteParamsReturn
2
2
 
3
3
  # Interface: UsePublicRouteParamsReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UseResolvedScopeOptions
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UseResolvedScopeOptions
2
2
 
3
3
  # Interface: UseResolvedScopeOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UseResolvedScopeReturn
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UseResolvedScopeReturn
2
2
 
3
3
  # Interface: UseResolvedScopeReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UseResourcePermissionsOptions
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UseResourcePermissionsOptions
2
2
 
3
3
  # Interface: UseResourcePermissionsOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UserEventAccess
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UserEventAccess
2
2
 
3
3
  # Interface: UserEventAccess
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UserMenuProps
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UserMenuProps
2
2
 
3
3
  # Interface: UserMenuProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.145](../README.md) / [Exports](../modules.md) / UserProfile
1
+ [@jmruthers/pace-core - v0.5.147](../README.md) / [Exports](../modules.md) / UserProfile
2
2
 
3
3
  # Interface: UserProfile
4
4
 
@@ -1,6 +1,6 @@
1
- [@jmruthers/pace-core - v0.5.145](README.md) / Exports
1
+ [@jmruthers/pace-core - v0.5.147](README.md) / Exports
2
2
 
3
- # @jmruthers/pace-core - v0.5.145
3
+ # @jmruthers/pace-core - v0.5.147
4
4
 
5
5
  **`File`**
6
6
 
@@ -0,0 +1,222 @@
1
+ # RBAC Event Context Loading - How It Works
2
+
3
+ ## Overview
4
+
5
+ For event-based apps (`requires_event: true`), RBAC waits for event context to be ready before loading permissions. This document explains how this works and answers common questions.
6
+
7
+ ## How RBAC Detects Event Context Availability
8
+
9
+ ### Automatic Detection via React Hooks
10
+
11
+ RBAC uses React's dependency system to automatically detect when event context becomes available:
12
+
13
+ 1. **`useRBAC` hook watches event state**:
14
+ - `eventLoading` - boolean indicating if events are loading
15
+ - `selectedEvent` - the currently selected event object (or null)
16
+
17
+ 2. **`loadRBACContext` callback depends on event state**:
18
+ ```typescript
19
+ const loadRBACContext = useCallback(async () => {
20
+ // ... loading logic
21
+ }, [selectedEvent, eventLoading, ...other dependencies]);
22
+ ```
23
+
24
+ 3. **`useEffect` automatically re-runs when callback changes**:
25
+ ```typescript
26
+ useEffect(() => {
27
+ loadRBACContext();
28
+ }, [loadRBACContext]);
29
+ ```
30
+
31
+ ### Flow Diagram
32
+
33
+ ```
34
+ 1. Component mounts → useRBAC called
35
+ 2. loadRBACContext created (depends on eventLoading, selectedEvent)
36
+ 3. useEffect runs → calls loadRBACContext()
37
+ 4. If eventLoading=true OR selectedEvent=null:
38
+ → Log: "Waiting for event context"
39
+ → Set isLoading=true
40
+ → Return early (don't load RBAC)
41
+ 5. When eventLoading changes to false AND selectedEvent becomes available:
42
+ → loadRBACContext callback is recreated (dependency changed)
43
+ → useEffect detects callback changed → re-runs
44
+ → loadRBACContext() called again
45
+ → This time: eventLoading=false AND selectedEvent exists
46
+ → Proceeds to load RBAC context
47
+ → Log: "Loading RBAC context"
48
+ → Log: "RBAC context loaded successfully"
49
+ ```
50
+
51
+ ## Should You See the "Waiting for Event Context" Log?
52
+
53
+ **Yes, you should see this log** when:
54
+ - App has `requires_event: true`
55
+ - Event context is loading (`eventLoading: true`) OR no event selected (`selectedEvent: null`)
56
+
57
+ **Log level**: `INFO` (should be visible in console)
58
+
59
+ **Log message**:
60
+ ```
61
+ [useRBAC] Waiting for event context before loading RBAC context
62
+ ```
63
+
64
+ **If you don't see this log**, it might mean:
65
+ 1. App doesn't have `requires_event: true` configured
66
+ 2. Event context loads too quickly (race condition)
67
+ 3. Log level is set too high (unlikely, as it's INFO level)
68
+
69
+ ## Is RBAC Loading Automatic?
70
+
71
+ **Yes, RBAC loading is completely automatic**. You don't need to call anything explicitly.
72
+
73
+ ### How It Works Automatically
74
+
75
+ 1. **`useRBAC` hook is called automatically** when:
76
+ - Component using RBAC mounts (e.g., `NavigationMenu`, `PagePermissionGuard`)
77
+ - Or when you explicitly call `useRBAC()` in a component
78
+
79
+ 2. **React's dependency system triggers re-runs**:
80
+ - When `eventLoading` changes from `true` → `false`
81
+ - When `selectedEvent` changes from `null` → object
82
+ - The `loadRBACContext` callback is recreated
83
+ - The `useEffect` detects the change and re-runs
84
+ - RBAC context loads automatically
85
+
86
+ ### What You Need to Do
87
+
88
+ **Nothing!** Just ensure:
89
+ - ✅ `setupRBAC(supabase)` is called in your app initialization
90
+ - ✅ `UnifiedAuthProvider` has `appConfig={{ requires_event: true }}` for event-based apps
91
+ - ✅ `EventProvider` is wrapping your app (for event-based apps)
92
+ - ✅ Event context is loading correctly
93
+
94
+ ## How to Manually Trigger RBAC Loading (For Testing)
95
+
96
+ ### Option 1: Force Re-render
97
+
98
+ If you need to manually trigger RBAC loading for testing:
99
+
100
+ ```typescript
101
+ import { useRBAC } from '@jmruthers/pace-core/rbac';
102
+
103
+ function TestComponent() {
104
+ const { isLoading, error, permissionMap } = useRBAC();
105
+ const [forceReload, setForceReload] = useState(0);
106
+
107
+ const manualReload = () => {
108
+ setForceReload(prev => prev + 1);
109
+ // This will cause useRBAC to re-run
110
+ };
111
+
112
+ return (
113
+ <div>
114
+ <button onClick={manualReload}>Reload RBAC</button>
115
+ <div>Loading: {isLoading ? 'Yes' : 'No'}</div>
116
+ <div>Permissions: {Object.keys(permissionMap).length}</div>
117
+ </div>
118
+ );
119
+ }
120
+ ```
121
+
122
+ ### Option 2: Call RPC Directly (Advanced)
123
+
124
+ For debugging, you can call the RPC function directly:
125
+
126
+ ```typescript
127
+ import { getEngine } from '@jmruthers/pace-core/rbac';
128
+
129
+ async function testRBAC() {
130
+ const engine = getEngine();
131
+
132
+ // Test app resolution
133
+ const appContext = await engine.resolveAppContext({
134
+ userId: 'your-user-id',
135
+ appName: 'TRAC'
136
+ });
137
+ console.log('App context:', appContext);
138
+
139
+ // Test permission map
140
+ const permissionMap = await engine.getPermissionMap({
141
+ userId: 'your-user-id',
142
+ scope: {
143
+ organisationId: 'your-org-id',
144
+ eventId: 'your-event-id',
145
+ appId: appContext?.appId
146
+ }
147
+ });
148
+ console.log('Permission map:', permissionMap);
149
+ }
150
+ ```
151
+
152
+ ### Option 3: Check Console Logs
153
+
154
+ The fix includes detailed logging:
155
+
156
+ 1. **When waiting**: `[useRBAC] Waiting for event context before loading RBAC context`
157
+ 2. **When loading**: `[useRBAC] Loading RBAC context`
158
+ 3. **When successful**: `[useRBAC] RBAC context loaded successfully` (with permission count)
159
+
160
+ ## Troubleshooting
161
+
162
+ ### RBAC Not Loading After Event Context Ready
163
+
164
+ **Symptoms**:
165
+ - Event context loads (`eventLoading: false`, `selectedEvent` set)
166
+ - No RBAC loading logs appear
167
+ - Permission map remains empty
168
+
169
+ **Check**:
170
+ 1. ✅ Verify `appConfig={{ requires_event: true }}` in `UnifiedAuthProvider`
171
+ 2. ✅ Verify database has `requires_event: true` for your app
172
+ 3. ✅ Check console for "Waiting for event context" log (should appear first)
173
+ 4. ✅ Check console for "Loading RBAC context" log (should appear after event ready)
174
+ 5. ✅ Verify `selectedEvent` is actually set (not null)
175
+ 6. ✅ Verify `eventLoading` is actually `false` (not `true`)
176
+
177
+ **If still not working**:
178
+ - Check browser console for any errors
179
+ - Verify `setupRBAC(supabase)` was called
180
+ - Check that `useRBAC` hook is being called somewhere (NavigationMenu calls it automatically)
181
+
182
+ ### Logs Not Appearing
183
+
184
+ **If you don't see any logs**:
185
+ 1. Check log level - logs are `INFO` level, should be visible
186
+ 2. Check browser console filter settings
187
+ 3. Verify RBAC logger is configured correctly
188
+
189
+ ### Permission Map Still Empty
190
+
191
+ **If permission map is empty after RBAC loads**:
192
+ 1. Check "RBAC context loaded successfully" log - what's the `permissionCount`?
193
+ 2. If `permissionCount: 0`, check:
194
+ - User has event-app role assigned
195
+ - Permissions exist for that role in database
196
+ - Event ID matches the selected event
197
+ - Organisation ID matches user's organisation
198
+
199
+ ## Expected Console Log Sequence
200
+
201
+ For event-based apps, you should see this sequence:
202
+
203
+ ```
204
+ 1. [RBAC INFO] RBAC system initialized successfully
205
+ 2. [useRBAC] Waiting for event context before loading RBAC context
206
+ { eventLoading: true, hasSelectedEvent: false, appName: "TRAC" }
207
+ 3. [useRBAC] Loading RBAC context
208
+ { appName: "TRAC", requiresEvent: true, hasSelectedEvent: true, ... }
209
+ 4. [useRBAC] RBAC context loaded successfully
210
+ { appName: "TRAC", permissionCount: 32, ... }
211
+ ```
212
+
213
+ ## Summary
214
+
215
+ - ✅ **RBAC detection is automatic** - React hooks handle it
216
+ - ✅ **You should see "Waiting" log** - when event is loading
217
+ - ✅ **RBAC loads automatically** - when event context becomes ready
218
+ - ✅ **No manual triggering needed** - but you can force re-render for testing
219
+ - ✅ **Detailed logs included** - to help debug issues
220
+
221
+ The fix ensures RBAC waits for event context before loading, preventing NetworkError and ensuring permissions load correctly for event-based apps.
222
+
@@ -0,0 +1,117 @@
1
+ # RBAC v0.5.147 Fix - Event Context Loading
2
+
3
+ ## Problem
4
+
5
+ RBAC wasn't loading for event-based apps because:
6
+ 1. **Logger filtering**: Critical logs were using `logger.info()` but RBAC logger defaults to `logLevel: 'warn'`, so logs were filtered out
7
+ 2. **Missing dependencies**: `appConfig` wasn't in `loadRBACContext` dependencies, so callback wasn't recreated when appConfig changed
8
+ 3. **No visibility**: No way to verify if `useRBAC` hook was being called
9
+
10
+ ## Fixes Applied
11
+
12
+ ### 1. Changed Log Levels to `warn`
13
+
14
+ All critical logs now use `logger.warn()` instead of `logger.info()` so they're always visible:
15
+
16
+ - `[useRBAC] Hook initialized` - Shows when hook is called
17
+ - `[useRBAC] Waiting for event context before loading RBAC context` - Shows when waiting
18
+ - `[useRBAC] Loading RBAC context` - Shows when loading starts
19
+ - `[useRBAC] RBAC context loaded successfully` - Shows when loading completes
20
+
21
+ ### 2. Added Direct Console Logging
22
+
23
+ Added direct `console.warn()` at hook initialization as a fallback to ensure visibility:
24
+
25
+ ```typescript
26
+ console.warn('[useRBAC] Hook initialized (direct log)', hookInitLog);
27
+ ```
28
+
29
+ This ensures logs are visible even if logger configuration is incorrect.
30
+
31
+ ### 3. Added `appConfig` to Dependencies
32
+
33
+ Added `appConfig` to `loadRBACContext` callback dependencies so it recreates when appConfig changes:
34
+
35
+ ```typescript
36
+ }, [appName, logger, resetState, selectedEvent, selectedEvent?.event_id, selectedOrganisation?.id, session, user, requiresEvent, eventLoading, appConfig]);
37
+ ```
38
+
39
+ ### 4. Improved `requiresEvent` Logic
40
+
41
+ Changed default behavior when `appConfig` is `null`:
42
+
43
+ ```typescript
44
+ // If appConfig is null initially, default to true (safer for event-based apps)
45
+ const requiresEvent = appConfig?.requires_event ?? (appConfig === null ? true : false);
46
+ ```
47
+
48
+ This prevents premature loading when appConfig hasn't loaded yet.
49
+
50
+ ### 5. Added useEffect Logging
51
+
52
+ Added logging in `useEffect` to track when it runs:
53
+
54
+ ```typescript
55
+ useEffect(() => {
56
+ logger.warn('[useRBAC] useEffect triggered - calling loadRBACContext', { ... });
57
+ loadRBACContext();
58
+ }, [loadRBACContext, appName, requiresEvent, eventLoading, selectedEvent, user, session]);
59
+ ```
60
+
61
+ ### 6. Added Explicit useEffect Dependencies
62
+
63
+ Added explicit dependencies to `useEffect` so it re-runs when event context changes:
64
+
65
+ ```typescript
66
+ }, [loadRBACContext, appName, requiresEvent, eventLoading, selectedEvent, user, session]);
67
+ ```
68
+
69
+ ## Expected Console Logs
70
+
71
+ After this fix, you should see this sequence:
72
+
73
+ ```
74
+ 1. [useRBAC] Hook initialized (direct log)
75
+ { appName: "TRAC", requiresEvent: true, ... }
76
+
77
+ 2. [useRBAC] useEffect triggered - calling loadRBACContext
78
+ { appName: "TRAC", requiresEvent: true, eventLoading: true, ... }
79
+
80
+ 3. [useRBAC] Waiting for event context before loading RBAC context
81
+ { eventLoading: true, hasSelectedEvent: false, appName: "TRAC" }
82
+
83
+ 4. [useRBAC] useEffect triggered - calling loadRBACContext
84
+ { appName: "TRAC", requiresEvent: true, eventLoading: false, hasSelectedEvent: true, ... }
85
+
86
+ 5. [useRBAC] Loading RBAC context
87
+ { appName: "TRAC", requiresEvent: true, hasSelectedEvent: true, ... }
88
+
89
+ 6. [useRBAC] RBAC context loaded successfully
90
+ { appName: "TRAC", permissionCount: 32, ... }
91
+ ```
92
+
93
+ ## Debugging Steps
94
+
95
+ If you still don't see logs:
96
+
97
+ 1. **Check if hook is called**: Look for `[useRBAC] Hook initialized (direct log)` - this uses direct `console.warn()` so it should always appear
98
+ 2. **Check if effect runs**: Look for `[useRBAC] useEffect triggered` - this shows when the effect runs
99
+ 3. **Check event context**: Verify `eventLoading: false` and `hasSelectedEvent: true` in logs
100
+ 4. **Check appConfig**: Verify `appConfig` is not `null` and `requiresEvent: true` in logs
101
+
102
+ ## Testing
103
+
104
+ To test the fix:
105
+
106
+ 1. Clear browser cache
107
+ 2. Restart dev server
108
+ 3. Open browser console
109
+ 4. Navigate to app
110
+ 5. Look for the log sequence above
111
+
112
+ ## Related Issues
113
+
114
+ - Fixes: RBAC not loading for event-based apps
115
+ - Related: NavigationMenu empty when `filterNavigationByPermissions={true}`
116
+ - Related: RBAC logs not appearing
117
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmruthers/pace-core",
3
- "version": "0.5.145",
3
+ "version": "0.5.147",
4
4
  "description": "Clean, modern React component library with Tailwind v4 styling and native utilities",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -64,7 +64,25 @@ export function useRBAC(pageId?: string): UserRBACContext {
64
64
  }
65
65
 
66
66
  // Check if app requires event context
67
- const requiresEvent = appConfig?.requires_event ?? false;
67
+ // IMPORTANT: If appConfig is null initially, default to true (safer for event-based apps)
68
+ // This prevents premature loading when appConfig hasn't loaded yet
69
+ const requiresEvent = appConfig?.requires_event ?? (appConfig === null ? true : false);
70
+
71
+ // Log hook initialization for debugging (use warn level so it's always visible)
72
+ // Also use direct console.log as fallback to ensure visibility
73
+ const hookInitLog = {
74
+ appName,
75
+ requiresEvent,
76
+ appConfig: appConfig ? JSON.stringify(appConfig) : 'null',
77
+ hasUser: !!user,
78
+ hasSession: !!session,
79
+ hasSelectedEvent: !!selectedEvent,
80
+ eventLoading,
81
+ selectedEventId: selectedEvent?.event_id
82
+ };
83
+ logger.warn('[useRBAC] Hook initialized', hookInitLog);
84
+ // Direct console.log as fallback to ensure we can see if hook is called
85
+ console.warn('[useRBAC] Hook initialized (direct log)', hookInitLog);
68
86
 
69
87
  const [globalRole, setGlobalRole] = useState<GlobalRole | null>(null);
70
88
  const [organisationRole, setOrganisationRole] = useState<OrganisationRole | null>(null);
@@ -94,10 +112,13 @@ export function useRBAC(pageId?: string): UserRBACContext {
94
112
  if (eventLoading || !selectedEvent) {
95
113
  // Event context not ready yet - don't load RBAC yet
96
114
  // This prevents premature RPC calls that can cause NetworkError
97
- logger.debug('[useRBAC] Waiting for event context before loading RBAC context', {
115
+ // Set loading state so React knows we're waiting
116
+ setIsLoading(true);
117
+ logger.warn('[useRBAC] Waiting for event context before loading RBAC context', {
98
118
  eventLoading,
99
119
  hasSelectedEvent: !!selectedEvent,
100
- appName
120
+ appName,
121
+ selectedEventId: selectedEvent?.event_id
101
122
  });
102
123
  return;
103
124
  }
@@ -106,6 +127,14 @@ export function useRBAC(pageId?: string): UserRBACContext {
106
127
  setIsLoading(true);
107
128
  setError(null);
108
129
 
130
+ logger.warn('[useRBAC] Loading RBAC context', {
131
+ appName,
132
+ requiresEvent,
133
+ hasSelectedEvent: !!selectedEvent,
134
+ selectedEventId: selectedEvent?.event_id,
135
+ organisationId: selectedOrganisation?.id
136
+ });
137
+
109
138
  try {
110
139
  let appId: UUID | undefined;
111
140
  if (appName) {
@@ -152,6 +181,14 @@ export function useRBAC(pageId?: string): UserRBACContext {
152
181
  setGlobalRole(roleContext.globalRole);
153
182
  setOrganisationRole(roleContext.organisationRole);
154
183
  setEventAppRole(roleContext.eventAppRole || mapAccessLevelToEventRole(accessLevel));
184
+
185
+ logger.warn('[useRBAC] RBAC context loaded successfully', {
186
+ appName,
187
+ permissionCount: Object.keys(map).length,
188
+ globalRole: roleContext.globalRole,
189
+ organisationRole: roleContext.organisationRole,
190
+ eventAppRole: roleContext.eventAppRole || mapAccessLevelToEventRole(accessLevel)
191
+ });
155
192
  } catch (err) {
156
193
  const handledError = err instanceof Error ? err : new Error('Failed to load RBAC context');
157
194
  logger.error('[useRBAC] Error loading RBAC context:', handledError);
@@ -160,7 +197,7 @@ export function useRBAC(pageId?: string): UserRBACContext {
160
197
  } finally {
161
198
  setIsLoading(false);
162
199
  }
163
- }, [appName, logger, resetState, selectedEvent?.event_id, selectedOrganisation?.id, session, user, requiresEvent, eventLoading]);
200
+ }, [appName, logger, resetState, selectedEvent, selectedEvent?.event_id, selectedOrganisation?.id, session, user, requiresEvent, eventLoading, appConfig]);
164
201
 
165
202
  const hasGlobalPermission = useCallback(
166
203
  (permission: string): boolean => {
@@ -188,8 +225,17 @@ export function useRBAC(pageId?: string): UserRBACContext {
188
225
  const canManageEvent = useMemo(() => isSuperAdmin || eventAppRole === 'event_admin', [isSuperAdmin, eventAppRole]);
189
226
 
190
227
  useEffect(() => {
228
+ // Log when effect runs to help debug
229
+ logger.warn('[useRBAC] useEffect triggered - calling loadRBACContext', {
230
+ appName,
231
+ requiresEvent,
232
+ eventLoading,
233
+ hasSelectedEvent: !!selectedEvent,
234
+ hasUser: !!user,
235
+ hasSession: !!session
236
+ });
191
237
  loadRBACContext();
192
- }, [loadRBACContext]);
238
+ }, [loadRBACContext, appName, requiresEvent, eventLoading, selectedEvent, user, session]);
193
239
 
194
240
  return {
195
241
  user,