@jmruthers/pace-core 0.5.35 → 0.5.36

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 (117) hide show
  1. package/dist/{DataTable-7H63EFYM.js → DataTable-BC4UXGIK.js} +2 -2
  2. package/dist/{chunk-Q4U5PCOY.js → chunk-6Z3XT4BB.js} +22 -182
  3. package/dist/chunk-6Z3XT4BB.js.map +1 -0
  4. package/dist/{chunk-BRWHKGV2.js → chunk-GEJMGKZW.js} +2 -81
  5. package/dist/chunk-GEJMGKZW.js.map +1 -0
  6. package/dist/{chunk-MC5E4ILK.js → chunk-KXXVMXZ7.js} +2 -2
  7. package/dist/components.js +2 -2
  8. package/dist/index.js +3 -3
  9. package/dist/rbac/index.d.ts +1 -1
  10. package/dist/rbac/index.js +1 -1
  11. package/dist/utils.js +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/interfaces/AggregateConfig.md +1 -1
  25. package/docs/api/interfaces/ButtonProps.md +1 -1
  26. package/docs/api/interfaces/CardProps.md +1 -1
  27. package/docs/api/interfaces/ColorPalette.md +1 -1
  28. package/docs/api/interfaces/ColorShade.md +1 -1
  29. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  30. package/docs/api/interfaces/DataTableAction.md +1 -1
  31. package/docs/api/interfaces/DataTableColumn.md +1 -1
  32. package/docs/api/interfaces/DataTableProps.md +1 -1
  33. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  34. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  35. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  36. package/docs/api/interfaces/EventContextType.md +1 -1
  37. package/docs/api/interfaces/EventLogoProps.md +1 -1
  38. package/docs/api/interfaces/EventProviderProps.md +1 -1
  39. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  40. package/docs/api/interfaces/FileUploadProps.md +1 -1
  41. package/docs/api/interfaces/FooterProps.md +1 -1
  42. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  43. package/docs/api/interfaces/InputProps.md +1 -1
  44. package/docs/api/interfaces/LabelProps.md +1 -1
  45. package/docs/api/interfaces/LoginFormProps.md +1 -1
  46. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  47. package/docs/api/interfaces/NavigationContextType.md +1 -1
  48. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  49. package/docs/api/interfaces/NavigationItem.md +1 -1
  50. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  51. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  52. package/docs/api/interfaces/Organisation.md +1 -1
  53. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  54. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  55. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  56. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  57. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  58. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  59. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  60. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  61. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  62. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  63. package/docs/api/interfaces/PaletteData.md +1 -1
  64. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  65. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  66. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  67. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  68. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  69. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  70. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  71. package/docs/api/interfaces/RBACConfig.md +1 -1
  72. package/docs/api/interfaces/RBACContextType.md +1 -1
  73. package/docs/api/interfaces/RBACLogger.md +1 -1
  74. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  75. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  76. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  77. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  78. package/docs/api/interfaces/RouteConfig.md +1 -1
  79. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  80. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  81. package/docs/api/interfaces/StorageConfig.md +1 -1
  82. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  83. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  84. package/docs/api/interfaces/StorageListOptions.md +1 -1
  85. package/docs/api/interfaces/StorageListResult.md +1 -1
  86. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  87. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  88. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  89. package/docs/api/interfaces/StyleImport.md +1 -1
  90. package/docs/api/interfaces/ToastActionElement.md +1 -1
  91. package/docs/api/interfaces/ToastProps.md +1 -1
  92. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  93. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  94. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  95. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  96. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  97. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  98. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  99. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  100. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  101. package/docs/api/interfaces/UserEventAccess.md +1 -1
  102. package/docs/api/interfaces/UserMenuProps.md +1 -1
  103. package/docs/api/interfaces/UserProfile.md +1 -1
  104. package/docs/api/modules.md +5 -5
  105. package/package.json +1 -1
  106. package/src/components/DataTable/components/DataTableCore.tsx +21 -106
  107. package/src/rbac/components/PagePermissionGuard.tsx +6 -190
  108. package/dist/chunk-BRWHKGV2.js.map +0 -1
  109. package/dist/chunk-Q4U5PCOY.js.map +0 -1
  110. package/docs/troubleshooting/cake-infinite-rerender-debugging.md +0 -284
  111. package/docs/troubleshooting/cake-infinite-rerender-summary.md +0 -117
  112. package/docs/troubleshooting/cake-rerender-diagnostic.js +0 -162
  113. package/docs/troubleshooting/page-permission-guard-diagnostic.js +0 -129
  114. package/docs/troubleshooting/page-permission-guard-ui-debugging.md +0 -353
  115. package/docs/troubleshooting/rbac-critical-fixes-summary.md +0 -260
  116. /package/dist/{DataTable-7H63EFYM.js.map → DataTable-BC4UXGIK.js.map} +0 -0
  117. /package/dist/{chunk-MC5E4ILK.js.map → chunk-KXXVMXZ7.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / StorageFileMetadata
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / StorageFileMetadata
2
2
 
3
3
  # Interface: StorageFileMetadata
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / StorageListOptions
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / StorageListOptions
2
2
 
3
3
  # Interface: StorageListOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / StorageListResult
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / StorageListResult
2
2
 
3
3
  # Interface: StorageListResult
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / StorageUploadOptions
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / StorageUploadOptions
2
2
 
3
3
  # Interface: StorageUploadOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / StorageUploadResult
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / StorageUploadResult
2
2
 
3
3
  # Interface: StorageUploadResult
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / StorageUrlOptions
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / StorageUrlOptions
2
2
 
3
3
  # Interface: StorageUrlOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / StyleImport
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / StyleImport
2
2
 
3
3
  # Interface: StyleImport
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / ToastActionElement
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / ToastActionElement
2
2
 
3
3
  # Interface: ToastActionElement
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / ToastProps
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / ToastProps
2
2
 
3
3
  # Interface: ToastProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UnifiedAuthContextType
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UnifiedAuthContextType
2
2
 
3
3
  # Interface: UnifiedAuthContextType
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UnifiedAuthProviderProps
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UnifiedAuthProviderProps
2
2
 
3
3
  # Interface: UnifiedAuthProviderProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UseInactivityTrackerOptions
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UseInactivityTrackerOptions
2
2
 
3
3
  # Interface: UseInactivityTrackerOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UseInactivityTrackerReturn
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UseInactivityTrackerReturn
2
2
 
3
3
  # Interface: UseInactivityTrackerReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UsePublicEventLogoOptions
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UsePublicEventLogoOptions
2
2
 
3
3
  # Interface: UsePublicEventLogoOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UsePublicEventLogoReturn
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UsePublicEventLogoReturn
2
2
 
3
3
  # Interface: UsePublicEventLogoReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UsePublicEventOptions
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UsePublicEventOptions
2
2
 
3
3
  # Interface: UsePublicEventOptions
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UsePublicEventReturn
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UsePublicEventReturn
2
2
 
3
3
  # Interface: UsePublicEventReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UsePublicRouteParamsReturn
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UsePublicRouteParamsReturn
2
2
 
3
3
  # Interface: UsePublicRouteParamsReturn
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UserEventAccess
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UserEventAccess
2
2
 
3
3
  # Interface: UserEventAccess
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UserMenuProps
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UserMenuProps
2
2
 
3
3
  # Interface: UserMenuProps
4
4
 
@@ -1,4 +1,4 @@
1
- [@jmruthers/pace-core - v0.5.35](../README.md) / [Exports](../modules.md) / UserProfile
1
+ [@jmruthers/pace-core - v0.5.36](../README.md) / [Exports](../modules.md) / UserProfile
2
2
 
3
3
  # Interface: UserProfile
4
4
 
@@ -1,6 +1,6 @@
1
- [@jmruthers/pace-core - v0.5.35](README.md) / Exports
1
+ [@jmruthers/pace-core - v0.5.36](README.md) / Exports
2
2
 
3
- # @jmruthers/pace-core - v0.5.35
3
+ # @jmruthers/pace-core - v0.5.36
4
4
 
5
5
  **`File`**
6
6
 
@@ -5036,7 +5036,7 @@ ___
5036
5036
 
5037
5037
  ### PagePermissionGuard
5038
5038
 
5039
- ▸ **PagePermissionGuard**(`props`): `Element`
5039
+ ▸ **PagePermissionGuard**(`props`): ``null`` \| `string` \| `number` \| `boolean` \| `Iterable`\<`ReactNode`, `any`, `any`\> \| `Element`
5040
5040
 
5041
5041
  PagePermissionGuard - Enforces page-level permissions
5042
5042
 
@@ -5052,13 +5052,13 @@ prevent apps from bypassing permission checks.
5052
5052
 
5053
5053
  #### Returns
5054
5054
 
5055
- `Element`
5055
+ ``null`` \| `string` \| `number` \| `boolean` \| `Iterable`\<`ReactNode`, `any`, `any`\> \| `Element`
5056
5056
 
5057
5057
  React element with permission enforcement
5058
5058
 
5059
5059
  #### Defined in
5060
5060
 
5061
- [packages/core/src/rbac/components/PagePermissionGuard.tsx:673](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/rbac/components/PagePermissionGuard.tsx#L673)
5061
+ [packages/core/src/rbac/components/PagePermissionGuard.tsx:489](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/rbac/components/PagePermissionGuard.tsx#L489)
5062
5062
 
5063
5063
  ___
5064
5064
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmruthers/pace-core",
3
- "version": "0.5.35",
3
+ "version": "0.5.36",
4
4
  "description": "Clean, modern React component library with Tailwind v4 styling and native utilities",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -333,13 +333,6 @@ function DataTableInternal<TData extends DataRecord>({
333
333
  // Get scope from useUnifiedAuth hook instead of user metadata
334
334
  const { selectedOrganisationId, selectedEventId, supabase } = useUnifiedAuth();
335
335
 
336
- // DEBUG: Log what we get from useUnifiedAuth
337
- console.log('[DataTable] useUnifiedAuth values:', {
338
- selectedOrganisationId,
339
- selectedEventId,
340
- hasUser: !!user,
341
- userId: user?.id
342
- });
343
336
 
344
337
  // Create scope the same way as PagePermissionGuard - with event-based resolution
345
338
  const [resolvedScope, setResolvedScope] = useState<Scope | null>(null);
@@ -385,42 +378,35 @@ function DataTableInternal<TData extends DataRecord>({
385
378
  if (supabase) {
386
379
  const appName = getCurrentAppName();
387
380
  if (appName) {
388
- try {
389
- console.log('[DataTable] Resolving app name to ID:', appName);
390
- const { data: app, error } = await supabase
381
+ try {
382
+ const { data: app, error } = await supabase
383
+ .from('rbac_apps')
384
+ .select('id, name, is_active')
385
+ .eq('name', appName)
386
+ .eq('is_active', true)
387
+ .single() as { data: { id: string; name: string; is_active: boolean } | null; error: any };
388
+
389
+ if (error) {
390
+ // Check if app exists but is inactive
391
+ const { data: inactiveApp } = await supabase
391
392
  .from('rbac_apps')
392
393
  .select('id, name, is_active')
393
394
  .eq('name', appName)
394
- .eq('is_active', true)
395
- .single() as { data: { id: string; name: string; is_active: boolean } | null; error: any };
395
+ .single() as { data: { id: string; name: string; is_active: boolean } | null };
396
396
 
397
- if (error) {
398
- console.error('[DataTable] Database error resolving app ID:', error);
399
- // Check if app exists but is inactive
400
- const { data: inactiveApp } = await supabase
401
- .from('rbac_apps')
402
- .select('id, name, is_active')
403
- .eq('name', appName)
404
- .single() as { data: { id: string; name: string; is_active: boolean } | null };
405
-
406
- if (inactiveApp) {
407
- console.error(`[DataTable] App "${appName}" exists but is inactive (is_active: ${inactiveApp.is_active})`);
408
- } else {
409
- console.error(`[DataTable] App "${appName}" not found in rbac_apps table`);
410
- }
411
- } else if (app) {
412
- appId = app.id;
413
- console.log('[DataTable] Successfully resolved app ID:', app.id);
397
+ if (inactiveApp) {
398
+ console.error(`[DataTable] App "${appName}" exists but is inactive (is_active: ${inactiveApp.is_active})`);
414
399
  } else {
415
- console.error('[DataTable] No app data returned for:', appName);
400
+ console.error(`[DataTable] App "${appName}" not found in rbac_apps table`);
416
401
  }
417
- } catch (error) {
418
- console.error('[DataTable] Unexpected error resolving app ID:', error);
402
+ } else if (app) {
403
+ appId = app.id;
419
404
  }
420
- } else {
421
- console.warn('[DataTable] No app name available for resolution');
405
+ } catch (error) {
406
+ console.error('[DataTable] Unexpected error resolving app ID:', error);
422
407
  }
423
408
  }
409
+ }
424
410
 
425
411
  // If we have both organisation and event, use them directly
426
412
  if (selectedOrganisationId && selectedEventId) {
@@ -472,39 +458,11 @@ function DataTableInternal<TData extends DataRecord>({
472
458
  resolveScope();
473
459
  }, [selectedOrganisationId, selectedEventId, supabase]);
474
460
 
475
- // DEBUG: Log the exact parameters being passed to useCan
476
- console.log('[DataTable] useCan parameters:', {
477
- userId: user?.id || '',
478
- stableScope,
479
- permission: `read:page.${effectivePageId}`,
480
- effectivePageId,
481
- useCache: true,
482
- hasValidScope: !!(stableScope && stableScope.organisationId)
483
- });
484
-
485
- // DEBUG: Log stableScope details separately to avoid console collapsing
486
- console.log('[DataTable] stableScope details:');
487
- console.log(' organisationId:', stableScope?.organisationId);
488
- console.log(' eventId:', stableScope?.eventId);
489
- console.log(' appId:', stableScope?.appId);
490
- console.log(' stableScope type:', typeof stableScope);
491
- console.log(' stableScope keys:', stableScope ? Object.keys(stableScope) : 'null');
492
-
493
461
  // Always call useCan hooks (React rules), but use a fallback scope if needed
494
462
  const fallbackScope = { organisationId: '', eventId: undefined, appId: undefined };
495
463
  const effectiveScope = stableScope && stableScope.organisationId ? stableScope : fallbackScope;
496
464
 
497
- // TEMPORARY TEST: Bypass useCan to see if the issue is with the hook itself
498
- const testBypass = false; // Set to true to test bypassing useCan
499
-
500
- const permissions = testBypass ? {
501
- canRead: { can: true, isLoading: false, error: null, refetch: async () => {} },
502
- canCreate: { can: true, isLoading: false, error: null, refetch: async () => {} },
503
- canUpdate: { can: true, isLoading: false, error: null, refetch: async () => {} },
504
- canDelete: { can: true, isLoading: false, error: null, refetch: async () => {} },
505
- canExport: { can: true, isLoading: false, error: null, refetch: async () => {} },
506
- canImport: { can: true, isLoading: false, error: null, refetch: async () => {} },
507
- } : {
465
+ const permissions = {
508
466
  canRead: useCan(user?.id || '', effectiveScope, `read:page.${effectivePageId}` as any, effectivePageId, true),
509
467
  canCreate: useCan(user?.id || '', effectiveScope, `create:page.${effectivePageId}` as any, effectivePageId, true),
510
468
  canUpdate: useCan(user?.id || '', effectiveScope, `update:page.${effectivePageId}` as any, effectivePageId, true),
@@ -512,10 +470,6 @@ function DataTableInternal<TData extends DataRecord>({
512
470
  canExport: useCan(user?.id || '', effectiveScope, `manage:page.${effectivePageId}` as any, effectivePageId, true), // Using manage for export/import
513
471
  canImport: useCan(user?.id || '', effectiveScope, `manage:page.${effectivePageId}` as any, effectivePageId, true), // Using manage for export/import
514
472
  };
515
-
516
- if (testBypass) {
517
- console.log('[DataTable] TEST BYPASS: Using hardcoded can: true for all permissions');
518
- }
519
473
 
520
474
  // ============================================================================
521
475
  // CONFIGURATION RESOLUTION - ALWAYS call these hooks
@@ -949,50 +903,11 @@ function DataTableInternal<TData extends DataRecord>({
949
903
  throw new Error('DataTable requires authenticated user for RBAC');
950
904
  }
951
905
 
952
- const scope = {
953
- organisationId: user?.user_metadata?.organisationId || user?.app_metadata?.organisationId,
954
- eventId: user?.user_metadata?.eventId || user?.app_metadata?.eventId,
955
- appId: user?.user_metadata?.appId || user?.app_metadata?.appId,
956
- };
957
906
 
958
907
  // MANDATORY: No data access without read permission
959
- console.log('[DataTable] RBAC DEBUG - Basic Info:', {
960
- effectivePageId,
961
- pageId,
962
- pageName,
963
- userId: user?.id,
964
- permission: `read:page.${effectivePageId}`
965
- });
966
-
967
- console.log('[DataTable] RBAC DEBUG - CanRead Details:');
968
- console.log(' can:', permissions.canRead.can);
969
- console.log(' isLoading:', permissions.canRead.isLoading);
970
- console.log(' error:', permissions.canRead.error);
971
- console.log(' refetch type:', typeof permissions.canRead.refetch);
972
-
973
- console.log('[DataTable] RBAC DEBUG - Scope (FIXED):');
974
- console.log(' resolvedScope:', resolvedScope);
975
- console.log(' stableScope:', stableScope);
976
- console.log(' organisationId:', stableScope?.organisationId);
977
- console.log(' eventId:', stableScope?.eventId);
978
- console.log(' appId:', stableScope?.appId);
979
-
980
908
  if (!permissions.canRead.can) {
981
- console.error('[DataTable] ACCESS DENIED - DataTable RBAC failing!');
982
- console.error(' effectivePageId:', effectivePageId);
983
- console.error(' canRead.can:', permissions.canRead.can);
984
- console.error(' canRead.isLoading:', permissions.canRead.isLoading);
985
- console.error(' canRead.error:', permissions.canRead.error);
986
- console.error(' permission:', `read:page.${effectivePageId}`);
987
- console.error(' Full canRead object:', permissions.canRead);
988
909
  return <AccessDeniedPage resource={effectivePageId || 'unknown-page'} operation="read" />;
989
910
  }
990
-
991
- console.log('[DataTable] ACCESS GRANTED - DataTable RBAC working!');
992
- console.log(' effectivePageId:', effectivePageId);
993
- console.log(' canRead.can:', permissions.canRead.can);
994
- console.log(' canRead.isLoading:', permissions.canRead.isLoading);
995
- console.log(' canRead.error:', permissions.canRead.error);
996
911
 
997
912
  // ============================================================================
998
913
  // RENDER
@@ -135,28 +135,10 @@ const PagePermissionGuardComponent = ({
135
135
  const renderCountRef = useRef(0);
136
136
  renderCountRef.current += 1;
137
137
 
138
- console.log(`[PagePermissionGuard] RENDER #${renderCountRef.current} for ${pageName}:${operation}`, {
139
- instanceId,
140
- timestamp: new Date().toISOString()
141
- });
142
138
 
143
- // Track component lifecycle
144
- useEffect(() => {
145
- console.log(`[PagePermissionGuard] MOUNTED: ${pageName}:${operation}`, { instanceId });
146
- return () => {
147
- console.log(`[PagePermissionGuard] UNMOUNTED: ${pageName}:${operation}`, { instanceId });
148
- };
149
- }, [pageName, operation, instanceId]);
150
139
 
151
140
  const { user, selectedOrganisationId, selectedEventId, supabase } = useUnifiedAuth();
152
141
 
153
- // DEBUG: Log what we get from useUnifiedAuth
154
- console.log('[PagePermissionGuard] useUnifiedAuth values:', {
155
- selectedOrganisationId,
156
- selectedEventId,
157
- hasUser: !!user,
158
- userId: user?.id
159
- });
160
142
  const [hasChecked, setHasChecked] = useState(false);
161
143
  const [checkError, setCheckError] = useState<Error | null>(null);
162
144
  const [resolvedScope, setResolvedScope] = useState<Scope | null>(null);
@@ -216,7 +198,6 @@ const PagePermissionGuardComponent = ({
216
198
  const appName = getCurrentAppName();
217
199
  if (appName) {
218
200
  try {
219
- console.log('[PagePermissionGuard] Resolving app name to ID:', appName);
220
201
  const { data: app, error } = await supabaseRef.current
221
202
  .from('rbac_apps')
222
203
  .select('id, name, is_active')
@@ -240,7 +221,6 @@ const PagePermissionGuardComponent = ({
240
221
  }
241
222
  } else if (app) {
242
223
  appId = app.id;
243
- console.log('[PagePermissionGuard] Successfully resolved app ID:', app.id);
244
224
  } else {
245
225
  console.error('[PagePermissionGuard] No app data returned for:', appName);
246
226
  }
@@ -281,7 +261,6 @@ const PagePermissionGuardComponent = ({
281
261
  eventId: selectedEventId,
282
262
  appId: appId
283
263
  };
284
- console.log('[PagePermissionGuard] Setting resolved scope:', resolvedScope);
285
264
  setResolvedScope(resolvedScope);
286
265
  setCheckError(null); // Clear any previous errors
287
266
  return;
@@ -316,7 +295,6 @@ const PagePermissionGuardComponent = ({
316
295
  eventId: selectedEventId || undefined,
317
296
  appId: appId
318
297
  };
319
- console.log('[PagePermissionGuard] Setting resolved scope (org only):', resolvedScope);
320
298
  setResolvedScope(resolvedScope);
321
299
  setCheckError(null); // Clear any previous errors
322
300
  return;
@@ -373,22 +351,6 @@ const PagePermissionGuardComponent = ({
373
351
  return `${operation}:page.${pageName}` as Permission;
374
352
  }, [operation, pageName]);
375
353
 
376
- // DEBUG: Log the exact parameters being passed to useCan
377
- console.log('[PagePermissionGuard] useCan parameters:', {
378
- userId: user?.id || '',
379
- stableScope,
380
- permission,
381
- effectivePageId,
382
- useCache: true
383
- });
384
-
385
- // DEBUG: Log stableScope details separately to avoid console collapsing
386
- console.log('[PagePermissionGuard] stableScope details:');
387
- console.log(' organisationId:', stableScope?.organisationId);
388
- console.log(' eventId:', stableScope?.eventId);
389
- console.log(' appId:', stableScope?.appId);
390
- console.log(' stableScope type:', typeof stableScope);
391
- console.log(' stableScope keys:', stableScope ? Object.keys(stableScope) : 'null');
392
354
 
393
355
  // Check if user has permission - only call useCan when we have a resolved scope
394
356
  // If resolvedScope is null, we're still resolving, so show loading state
@@ -400,17 +362,6 @@ const PagePermissionGuardComponent = ({
400
362
  true // Use cache
401
363
  );
402
364
 
403
- // Debug useCan results
404
- console.log(`[PagePermissionGuard] useCan result for ${pageName}:${operation}`, {
405
- instanceId,
406
- can,
407
- canIsLoading,
408
- canError: !!canError,
409
- userId: user?.id,
410
- stableScope,
411
- permission,
412
- effectivePageId
413
- });
414
365
 
415
366
  // Combine loading states - we're loading if either scope is resolving OR permission check is loading
416
367
  const isLoading = !resolvedScope || canIsLoading;
@@ -445,6 +396,7 @@ const PagePermissionGuardComponent = ({
445
396
  }
446
397
  }, [auditLog, hasChecked, isLoading, pageName, operation, user?.id, resolvedScope, can]);
447
398
 
399
+
448
400
  // Handle strict mode violations
449
401
  useEffect(() => {
450
402
  if (strictMode && hasChecked && !isLoading && !can) {
@@ -471,166 +423,30 @@ const PagePermissionGuardComponent = ({
471
423
  const scopeKey = resolvedScope ? `${resolvedScope.organisationId}-${resolvedScope.eventId}-${resolvedScope.appId}` : 'no-scope';
472
424
  const permissionKey = `${scopeKey}-${can}-${isLoading}-${!!checkError}-${hasChecked}`;
473
425
 
474
- // Debug logging for state transitions
475
- useEffect(() => {
476
- console.log('[PagePermissionGuard] State transition:', {
477
- instanceId,
478
- isLoading,
479
- hasChecked,
480
- resolvedScope: !!resolvedScope,
481
- checkError: !!checkError,
482
- can,
483
- shouldShowAccessDenied,
484
- shouldShowContent,
485
- permissionKey
486
- });
487
- }, [isLoading, hasChecked, resolvedScope, checkError, can, shouldShowAccessDenied, shouldShowContent, permissionKey, instanceId]);
488
-
489
- // CRITICAL DEBUG: Log every render decision with full context
490
- const renderDecision = {
491
- instanceId,
492
- timestamp: new Date().toISOString(),
493
- renderCount: renderCountRef.current,
494
- // State values
495
- isLoading,
496
- hasValidScope,
497
- hasValidUser,
498
- hasChecked,
499
- checkError: !!checkError,
500
- can,
501
- // Calculated values
502
- shouldShowAccessDenied,
503
- shouldShowContent,
504
- // Render conditions
505
- willShowLoading: isLoading || !hasValidScope || !hasValidUser || !hasChecked,
506
- willShowError: checkError && !can,
507
- willShowDenied: shouldShowAccessDenied,
508
- willShowContent: shouldShowContent,
509
- // Raw data for debugging
510
- resolvedScope: resolvedScope ? {
511
- organisationId: resolvedScope.organisationId,
512
- eventId: resolvedScope.eventId,
513
- appId: resolvedScope.appId
514
- } : null,
515
- user: user ? { id: user.id, email: user.email } : null
516
- };
517
-
518
- console.log('[PagePermissionGuard] RENDER DECISION:', renderDecision);
519
426
 
520
- // CRITICAL: If we have permission but shouldShowContent is false, this is the bug!
521
- if (can && !shouldShowContent) {
522
- console.error('[PagePermissionGuard] CRITICAL BUG DETECTED: Has permission but shouldShowContent is false!', {
523
- ...renderDecision,
524
- bug: 'PERMISSION_GRANTED_BUT_CONTENT_NOT_SHOWING'
525
- });
526
- }
527
-
528
- // CRITICAL: If shouldShowContent is true but we're not rendering content, this is the bug!
529
- if (shouldShowContent && !(isLoading || !hasValidScope || !hasValidUser || !hasChecked) && !(checkError && !can) && !shouldShowAccessDenied) {
530
- console.log('[PagePermissionGuard] SHOULD RENDER CONTENT - This is the correct path!', {
531
- ...renderDecision,
532
- status: 'CONTENT_SHOULD_BE_RENDERED'
533
- });
534
- }
535
427
 
536
428
  // Show loading state - if we're still loading or don't have valid state
537
429
  if (isLoading || !hasValidScope || !hasValidUser || !hasChecked) {
538
- console.log('[PagePermissionGuard] RENDERING: LOADING STATE');
539
- return (
540
- <div key={`loading-${permissionKey}`} style={{ border: '3px solid orange', padding: '5px', backgroundColor: 'lightyellow' }}>
541
- <div style={{ color: 'orange', fontWeight: 'bold' }}>🔄 LOADING STATE</div>
542
- {loading}
543
- </div>
544
- );
430
+ return loading || <div>Checking permissions...</div>;
545
431
  }
546
432
 
547
433
  // Show error state - only if we have an error AND no permission
548
434
  if (checkError && !can) {
549
- console.log('[PagePermissionGuard] RENDERING: ERROR STATE');
550
- return (
551
- <div key={`error-${permissionKey}`} style={{ border: '3px solid red', padding: '5px', backgroundColor: 'lightcoral' }}>
552
- <div style={{ color: 'red', fontWeight: 'bold' }}>❌ ERROR STATE</div>
553
- {fallback}
554
- </div>
555
- );
435
+ return fallback;
556
436
  }
557
437
 
558
438
  // Show access denied - if permission check is complete and user doesn't have permission
559
439
  if (shouldShowAccessDenied) {
560
- console.log('[PagePermissionGuard] RENDERING: ACCESS DENIED STATE');
561
- return (
562
- <div key={`denied-${permissionKey}`} style={{ border: '3px solid red', padding: '5px', backgroundColor: 'lightcoral' }}>
563
- <div style={{ color: 'red', fontWeight: 'bold' }}>🚫 ACCESS DENIED STATE</div>
564
- {fallback}
565
- </div>
566
- );
440
+ return fallback;
567
441
  }
568
442
 
569
443
  // Show protected content - if permission check is complete and user has permission
570
444
  if (shouldShowContent) {
571
- console.log('[PagePermissionGuard] RENDERING: CONTENT STATE - SHOWING CHILDREN');
572
- console.log('[PagePermissionGuard] CONTENT RENDER SUCCESS - This should fix the Access Denied issue!');
573
-
574
- // FORCE RENDER: Create a very obvious visual indicator that cannot be missed
575
- const forceRenderContent = (
576
- <div
577
- key={`content-${permissionKey}`}
578
- style={{
579
- border: '5px solid red',
580
- padding: '10px',
581
- margin: '10px',
582
- backgroundColor: 'yellow',
583
- position: 'relative',
584
- zIndex: 9999
585
- }}
586
- >
587
- <div style={{
588
- background: 'red',
589
- color: 'white',
590
- padding: '10px',
591
- fontSize: '16px',
592
- fontWeight: 'bold',
593
- marginBottom: '10px',
594
- textAlign: 'center'
595
- }}>
596
- 🚨 FORCE RENDER: PagePermissionGuard Content is ACTUALLY RENDERING! 🚨
597
- </div>
598
- <div style={{
599
- background: 'lightgreen',
600
- padding: '5px',
601
- fontSize: '14px',
602
- marginBottom: '10px',
603
- border: '2px solid green'
604
- }}>
605
- ✅ This proves the PagePermissionGuard is working correctly!
606
- </div>
607
- <div style={{ border: '2px solid blue', padding: '5px' }}>
608
- <strong>Original Children:</strong>
609
- {children}
610
- </div>
611
- </div>
612
- );
613
-
614
- console.log('[PagePermissionGuard] RETURNING FORCE RENDER CONTENT');
615
- return forceRenderContent;
445
+ return <>{children}</>;
616
446
  }
617
447
 
618
448
  // Fallback: This should never happen, but just in case
619
- // If we get here, something went wrong with our state logic
620
- console.error('[PagePermissionGuard] CRITICAL: UNEXPECTED STATE - FALLING BACK TO LOADING', {
621
- instanceId,
622
- isLoading,
623
- hasValidScope,
624
- hasValidUser,
625
- hasChecked,
626
- checkError: !!checkError,
627
- can,
628
- shouldShowAccessDenied,
629
- shouldShowContent,
630
- resolvedScope,
631
- user: user ? { id: user.id, email: user.email } : null
632
- });
633
- return <div key={`fallback-${permissionKey}`}>{loading}</div>;
449
+ return fallback;
634
450
  }
635
451
 
636
452
  /**