@jmruthers/pace-core 0.5.108 → 0.5.110

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 (195) hide show
  1. package/CHANGELOG.md +93 -173
  2. package/dist/{AuthService-1D2ifNfa.d.ts → AuthService-DrHrvXNZ.d.ts} +8 -1
  3. package/dist/{DataTable-WFCHVWTY.js → DataTable-D3BK2FCN.js} +7 -7
  4. package/dist/{UnifiedAuthProvider-XU4BHFXZ.js → UnifiedAuthProvider-A7I23UCN.js} +3 -3
  5. package/dist/{api-KG4A2X7P.js → api-PIE4JRFS.js} +2 -2
  6. package/dist/{chunk-DMNMZKWS.js → chunk-2W4WKJVF.js} +4 -4
  7. package/dist/{chunk-B3QX32P5.js → chunk-3J5N2T2N.js} +85 -28
  8. package/dist/chunk-3J5N2T2N.js.map +1 -0
  9. package/dist/{chunk-MOMYOQMC.js → chunk-7GBEBJLR.js} +29 -37
  10. package/dist/chunk-7GBEBJLR.js.map +1 -0
  11. package/dist/{chunk-X4FRXJV6.js → chunk-AUXS7XSO.js} +57 -6
  12. package/dist/{chunk-X4FRXJV6.js.map → chunk-AUXS7XSO.js.map} +1 -1
  13. package/dist/{chunk-VJ7MPS2K.js → chunk-AWK2FAUN.js} +6 -6
  14. package/dist/{chunk-LT6RKRA7.js → chunk-D6MEKC27.js} +2 -2
  15. package/dist/{chunk-KBG34SVL.js → chunk-EYSXQ756.js} +2 -2
  16. package/dist/{chunk-ZXY5NTJB.js → chunk-EZ64QG2I.js} +2 -2
  17. package/dist/chunk-GZRXOUBE.js +176 -0
  18. package/dist/chunk-GZRXOUBE.js.map +1 -0
  19. package/dist/{chunk-QDDUU625.js → chunk-HADXAZT3.js} +4 -4
  20. package/dist/{chunk-IMZGJ2X7.js → chunk-HGZSO43Y.js} +4 -4
  21. package/dist/{chunk-S63MFSY6.js → chunk-XRSP3H52.js} +15 -8
  22. package/dist/chunk-XRSP3H52.js.map +1 -0
  23. package/dist/{chunk-GVRSXXAA.js → chunk-YFMENCR4.js} +3 -3
  24. package/dist/components.js +9 -9
  25. package/dist/{database-BXAfr2Y_.d.ts → database-C6jy7EOu.d.ts} +21 -9
  26. package/dist/{formatting-BiEv5oEk.d.ts → formatting-B1jSqgl-.d.ts} +16 -1
  27. package/dist/hooks.d.ts +2 -2
  28. package/dist/hooks.js +7 -7
  29. package/dist/index.d.ts +6 -6
  30. package/dist/index.js +16 -14
  31. package/dist/index.js.map +1 -1
  32. package/dist/providers.d.ts +4 -3
  33. package/dist/providers.js +2 -2
  34. package/dist/rbac/index.d.ts +35 -23
  35. package/dist/rbac/index.js +8 -8
  36. package/dist/types.d.ts +2 -2
  37. package/dist/{usePublicRouteParams-CnM-IK2I.d.ts → usePublicRouteParams-BdF8bZgs.d.ts} +1 -1
  38. package/dist/utils.d.ts +2 -15
  39. package/dist/utils.js +4 -145
  40. package/dist/utils.js.map +1 -1
  41. package/dist/validation.d.ts +1 -1
  42. package/docs/api/classes/ColumnFactory.md +1 -1
  43. package/docs/api/classes/ErrorBoundary.md +1 -1
  44. package/docs/api/classes/InvalidScopeError.md +1 -1
  45. package/docs/api/classes/MissingUserContextError.md +1 -1
  46. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  47. package/docs/api/classes/PermissionDeniedError.md +1 -1
  48. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  49. package/docs/api/classes/RBACAuditManager.md +1 -1
  50. package/docs/api/classes/RBACCache.md +1 -1
  51. package/docs/api/classes/RBACEngine.md +9 -8
  52. package/docs/api/classes/RBACError.md +1 -1
  53. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  54. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  55. package/docs/api/classes/StorageUtils.md +1 -1
  56. package/docs/api/enums/FileCategory.md +1 -1
  57. package/docs/api/interfaces/AggregateConfig.md +1 -1
  58. package/docs/api/interfaces/ButtonProps.md +1 -1
  59. package/docs/api/interfaces/CardProps.md +1 -1
  60. package/docs/api/interfaces/ColorPalette.md +1 -1
  61. package/docs/api/interfaces/ColorShade.md +1 -1
  62. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  63. package/docs/api/interfaces/DataRecord.md +1 -1
  64. package/docs/api/interfaces/DataTableAction.md +1 -1
  65. package/docs/api/interfaces/DataTableColumn.md +3 -3
  66. package/docs/api/interfaces/DataTableProps.md +1 -1
  67. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  68. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  69. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  70. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  71. package/docs/api/interfaces/FileMetadata.md +1 -1
  72. package/docs/api/interfaces/FileReference.md +1 -1
  73. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  74. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  75. package/docs/api/interfaces/FileUploadProps.md +1 -1
  76. package/docs/api/interfaces/FooterProps.md +1 -1
  77. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  78. package/docs/api/interfaces/InputProps.md +1 -1
  79. package/docs/api/interfaces/LabelProps.md +1 -1
  80. package/docs/api/interfaces/LoginFormProps.md +1 -1
  81. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  82. package/docs/api/interfaces/NavigationContextType.md +1 -1
  83. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  84. package/docs/api/interfaces/NavigationItem.md +1 -1
  85. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  86. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  87. package/docs/api/interfaces/Organisation.md +1 -1
  88. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  89. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  90. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  91. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  92. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  93. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  94. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  95. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  96. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  97. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  98. package/docs/api/interfaces/PaletteData.md +1 -1
  99. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  100. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  101. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  102. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  103. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  104. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  105. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  106. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  107. package/docs/api/interfaces/RBACConfig.md +19 -8
  108. package/docs/api/interfaces/RBACLogger.md +5 -5
  109. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  110. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  111. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  112. package/docs/api/interfaces/RouteConfig.md +1 -1
  113. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  114. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  115. package/docs/api/interfaces/StorageConfig.md +1 -1
  116. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  117. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  118. package/docs/api/interfaces/StorageListOptions.md +1 -1
  119. package/docs/api/interfaces/StorageListResult.md +1 -1
  120. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  121. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  122. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  123. package/docs/api/interfaces/StyleImport.md +1 -1
  124. package/docs/api/interfaces/SwitchProps.md +1 -1
  125. package/docs/api/interfaces/ToastActionElement.md +1 -1
  126. package/docs/api/interfaces/ToastProps.md +1 -1
  127. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  128. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  129. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  130. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  131. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  132. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  133. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  134. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  135. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  136. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  137. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  138. package/docs/api/interfaces/UserEventAccess.md +1 -1
  139. package/docs/api/interfaces/UserMenuProps.md +1 -1
  140. package/docs/api/interfaces/UserProfile.md +1 -1
  141. package/docs/api/modules.md +55 -20
  142. package/docs/api-reference/hooks.md +53 -0
  143. package/docs/api-reference/providers.md +60 -0
  144. package/docs/core-concepts/authentication.md +2 -0
  145. package/docs/documentation-index.md +0 -2
  146. package/docs/implementation-guides/authentication.md +1 -0
  147. package/docs/rbac/README.md +114 -38
  148. package/docs/rbac/api-reference.md +63 -16
  149. package/docs/rbac/getting-started.md +16 -16
  150. package/docs/rbac/quick-start.md +110 -35
  151. package/docs/rbac/troubleshooting.md +125 -2
  152. package/docs/security/README.md +59 -0
  153. package/package.json +1 -1
  154. package/src/components/NavigationMenu/NavigationMenu.test.tsx +38 -4
  155. package/src/components/NavigationMenu/NavigationMenu.tsx +71 -6
  156. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +2 -2
  157. package/src/components/PaceAppLayout/PaceAppLayout.tsx +48 -16
  158. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +2 -1
  159. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +9 -9
  160. package/src/index.ts +3 -0
  161. package/src/providers/services/AuthServiceProvider.tsx +4 -3
  162. package/src/providers/services/UnifiedAuthProvider.tsx +1 -1
  163. package/src/rbac/api.test.ts +2 -2
  164. package/src/rbac/api.ts +2 -1
  165. package/src/rbac/components/PagePermissionGuard.tsx +21 -38
  166. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +1 -1
  167. package/src/rbac/config.ts +2 -0
  168. package/src/rbac/engine.ts +17 -5
  169. package/src/rbac/security.ts +1 -1
  170. package/src/services/AuthService.ts +79 -1
  171. package/src/services/__tests__/AuthService.test.ts +184 -0
  172. package/src/types/database.ts +21 -9
  173. package/src/types/rbac-functions.ts +2 -1
  174. package/src/utils/__tests__/sessionTracking.unit.test.ts +6 -171
  175. package/src/utils/sessionTracking.ts +7 -81
  176. package/dist/chunk-B3QX32P5.js.map +0 -1
  177. package/dist/chunk-MOMYOQMC.js.map +0 -1
  178. package/dist/chunk-NFPV7MRN.js +0 -94
  179. package/dist/chunk-NFPV7MRN.js.map +0 -1
  180. package/dist/chunk-S63MFSY6.js.map +0 -1
  181. package/docs/rbac/breaking-changes-v3.md +0 -222
  182. package/docs/rbac/migration-guide.md +0 -260
  183. package/src/providers/AuthProvider.simplified.tsx +0 -974
  184. package/dist/{DataTable-WFCHVWTY.js.map → DataTable-D3BK2FCN.js.map} +0 -0
  185. package/dist/{UnifiedAuthProvider-XU4BHFXZ.js.map → UnifiedAuthProvider-A7I23UCN.js.map} +0 -0
  186. package/dist/{api-KG4A2X7P.js.map → api-PIE4JRFS.js.map} +0 -0
  187. package/dist/{chunk-DMNMZKWS.js.map → chunk-2W4WKJVF.js.map} +0 -0
  188. package/dist/{chunk-VJ7MPS2K.js.map → chunk-AWK2FAUN.js.map} +0 -0
  189. package/dist/{chunk-LT6RKRA7.js.map → chunk-D6MEKC27.js.map} +0 -0
  190. package/dist/{chunk-KBG34SVL.js.map → chunk-EYSXQ756.js.map} +0 -0
  191. package/dist/{chunk-ZXY5NTJB.js.map → chunk-EZ64QG2I.js.map} +0 -0
  192. package/dist/{chunk-QDDUU625.js.map → chunk-HADXAZT3.js.map} +0 -0
  193. package/dist/{chunk-IMZGJ2X7.js.map → chunk-HGZSO43Y.js.map} +0 -0
  194. package/dist/{chunk-GVRSXXAA.js.map → chunk-YFMENCR4.js.map} +0 -0
  195. package/dist/{validation-D8VcbTzC.d.ts → validation-DnhrNMju.d.ts} +2 -2
package/CHANGELOG.md CHANGED
@@ -7,206 +7,126 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ### Changed - RBAC Refactoring
11
- - **Breaking**: Renamed provider hook `useRBAC()` to `useRBACContext()` to avoid naming collision
12
- - **Removed**: Non-functional `usePermissionCheck` hook
13
- - **Deprecated**: `RBACService`, `useRBACService` - use new RBAC system instead
14
- - Consolidated permission checking logic into single source of truth
15
- - Established consistent fail-secure error handling across RBAC components
16
- - Removed 100+ lines of duplicate code
10
+ ## [0.5.110] - 2025-01-27
17
11
 
18
12
  ### Added
19
- - **DataTable Initial Page Size**: Added `initialPageSize` prop to DataTable component for customizing the initial page size
20
- - **Page Size Validation**: Automatic validation of initial page size against available options with fallback to closest valid option
21
- - **Console Warnings**: Helpful warnings when invalid page sizes are provided
22
- - **DataTable Expand/Collapse All**: Added expand/collapse all button in hierarchical DataTable headers for quick parent row management
23
- - **Smart State Detection**: Button automatically updates icon (▶️/🔽) based on current expansion state
24
- - **Accessibility Support**: Full ARIA labels and keyboard navigation for expand/collapse all functionality
25
- - **DataTable Column Ordering**: Added `columnOrder` prop to DataTable component for custom column positioning
26
- - **Selection Column Positioning**: Selection column can now be positioned anywhere in the column order
27
- - **Actions Column Positioning**: Actions column can now be positioned anywhere in the column order
28
- - **Default Behavior**: When `columnOrder` doesn't include 'select', selection column defaults to first position
29
-
30
- ### Fixed
31
- - **DataTable Infinite Loop Prevention**: Fixed infinite re-rendering loops when using complex data processing with `useMemo` hooks
32
- - **Data Reference Stability**: Improved data reference stability to prevent unnecessary re-renders
33
- - **Memory Optimization**: Added safeguards against infinite loops with render counting and data comparison
34
- - **Performance**: Optimized table configuration memoization to prevent unnecessary re-creation
35
- - **RBAC Race Condition**: Fixed "Access Denied" errors for users with valid permissions caused by race condition in permission checking
36
- - **Permission Loading State**: Improved loading state handling during scope resolution to prevent premature access denied errors
37
-
38
- ### Improved
39
- - **Data Processing Documentation**: Added comprehensive best practices for data processing with DataTable
40
- - **Error Handling**: Added infinite loop detection and prevention mechanisms
41
- - **Type Safety**: Improved TypeScript type handling for complex data scenarios
42
-
43
- ## [0.3.52] - 2024-12-19
13
+ - **Automatic Page Permission Checking in NavigationMenu**: Navigation items with `href` but no explicit permissions/roles/accessLevel now automatically check for `read:page.{pageId}` permission, making navigation filtering more intuitive
14
+ - **RBAC Security Configuration Support**: `RBACEngine` and `createRBACEngine` now accept an optional `securityConfig` parameter, allowing customization of rate limits and security settings per instance
44
15
 
45
16
  ### Changed
46
- - **Row Actions Simplification**: Removed incomplete `features.rowActions` implementation and kept robust `actions` prop as the single method for custom row actions
47
- - **Documentation Update**: Updated all documentation to reflect single row actions approach using `actions` prop
17
+ - **RBAC Rate Limit Increase**: Increased default `maxPermissionChecksPerMinute` from 100 to 1000 to accommodate normal application usage patterns
18
+ - **NavigationMenu Filtering Improvements**: Enhanced recursive filtering of navigation items with proper parent/child handling - parents without accessible children are now properly hidden
19
+ - **RBAC Documentation Updates**: Improved RBAC documentation with better examples, troubleshooting guides, and API references
20
+ - **PagePermissionGuard Scope Handling**: Replaced ref-based scope tracking with `useMemo` for better React compatibility and performance, with improved handling of undefined `appId` values
48
21
 
49
22
  ### Fixed
50
- - **Actions Prop Implementation**: Verified and confirmed that the `actions` prop is fully implemented and working correctly in DataTable component
23
+ - **PagePermissionGuard Infinite Loop Prevention**: Fixed potential infinite loops by improving scope stability and ensuring `useCan` only runs with valid scopes
24
+ - **PagePermissionGuard Error Logging**: Enhanced error logging with more context (permission strings, page IDs, scope validation status)
25
+ - **NavigationMenu Test Mocks**: Updated test mocks to default to permissive permissions (super admin access) for better test isolation and clearer test intent
26
+ - **RBAC API Test Assertions**: Fixed test assertions to correctly match `createRBACEngine` function signature with optional parameters
51
27
 
52
- ### Fixed
53
- - **CRITICAL**: Fixed timing issue in OrganisationProvider where database organisation context was not set before other components tried to use it
54
- - **CRITICAL**: Fixed race condition that caused RLS policies to fail on first load
55
- - **CRITICAL**: Fixed super admin permissions returning false for all operations due to missing organisation context
56
- - **CRITICAL**: Fixed Tailwind v4 theme file with missing semantic colors and circular @apply references
57
- - **CRITICAL**: Fixed component classes (.pace-button, .pace-input, .pace-card) to be self-contained
58
- - **CRITICAL**: Fixed missing basic colors (white, black, transparent, current) in Tailwind v4 theme file
59
- - **CRITICAL**: Fixed semantic color mappings to match demo app appearance (blue-tinted theme instead of neutral gray)
60
- - **CRITICAL**: Fixed header layout by adding missing CSS variables (--app-width, --color-main-*, --color-sec-*, --color-acc-*)
61
- - **CRITICAL**: Added comprehensive CSS variable coverage for all components (fonts, design tokens, event colors, Radix UI variables)
62
- - **CRITICAL**: Added comprehensive troubleshooting guide for "unrecognized configuration parameter" database errors
28
+ ### Removed
29
+ - **pace-core-devtools Package**: Removed the entire `pace-core-devtools` package and all related devtools functionality (AuditInspector, PerformanceMonitor, PermissionDebugger, RoleSimulator, etc.)
30
+ - **Outdated RBAC Documentation**: Removed deprecated `breaking-changes-v3.md` and `migration-guide.md` files that are no longer relevant
63
31
 
64
- ### Added
65
- - Comprehensive JSDoc documentation for all public components
66
- - Enhanced API documentation with examples and TypeScript types
67
- - Complete testing guide with utilities and patterns
68
- - Quick start examples and troubleshooting guides
69
- - Performance optimization recommendations
70
- - Migration guides from Auth0 and Firebase
71
- - Interactive CodeSandbox and StackBlitz examples
72
- - Context readiness state to ensure database context is set before rendering children
73
-
74
- ### Enhanced
75
- - Button component with full JSDoc documentation and examples
76
- - README with 3-minute quick start guide
77
- - Error handling documentation with common solutions
78
- - Component documentation with accessibility guidelines
79
- - OrganisationProvider with proper async context setting and loading states
80
-
81
- ### Improved
82
- - Developer experience with better onboarding materials
83
- - Documentation structure for easier navigation
84
- - Code examples with TypeScript types and best practices
85
- - Organisation context reliability and timing
86
-
87
- ## [0.1.102] - 2025-05-26
32
+ ## [0.5.109] - 2025-11-03
88
33
 
89
34
  ### Added
90
- - Enhanced package structure for better modularity
91
- - Granular exports in package.json for better tree-shaking
92
- - Improved boundary validation scripts
93
- - CHANGELOG.md for tracking package versions
94
-
95
- ### Fixed
96
- - Resolved duplicate exports of EventSelectorProps
97
- - Clean separation between test utilities and production code
98
- - Enhanced demo discoverability with improved index page
35
+ - **Automatic Login History Tracking**: Login and logout events are now automatically tracked when using `UnifiedAuthProvider`. No manual intervention required - tracking happens automatically on `SIGNED_IN` and `SIGNED_OUT` events.
36
+ - **Login History Database Schema**: Added `app_id` column to `rbac_user_login_history` table for application-specific tracking
37
+ - **Performance Indexes**: Added indexes on `login_timestamp` and `(user_id, login_timestamp)` for efficient login history queries
38
+ - **Session Tracking Integration**: `AuthService` now automatically calls `rbac_session_track` on login/logout events, which records both session data and login history
39
+ - **Comprehensive Session Tracking Tests**: Added unit tests for automatic session tracking functionality
99
40
 
100
41
  ### Changed
101
- - Optimized main index.ts exports to avoid conflicts
102
- - Strengthened validation scripts with circular dependency checks
103
- - Improved package.json exports for better modularity
42
+ - **Session Tracking Hook API**: Removed `trackLogin()` and `trackLogout()` methods from `useSessionTracking` hook. These are now automatically handled by `UnifiedAuthProvider`. The hook now only provides `trackEventSwitch()` and `trackSessionExpired()` for manual tracking scenarios.
43
+ - **Database Function Enhancement**: Modified `rbac_session_track` RPC function to automatically insert into `rbac_user_login_history` table when `session_type = 'login'`
44
+ - **RBAC Permission String Format**: Updated permission string format to `"operation:page.pageId"` (e.g., `"read:page.suppliers"`) for consistent permission checking
45
+ - **Navigation Filtering Optimization**: Optimized `PaceAppLayout` navigation filtering to use `getPermissionMap` for batch permission fetching, preventing rate limit exceeded errors
104
46
 
105
- ## [0.1.101] - Previous Release
47
+ ### Removed
48
+ - **AuthProvider.simplified.tsx**: Removed unused experimental auth provider file (tech debt cleanup)
49
+ - **useSessionTracking Methods**: Removed `trackLogin()` and `trackLogout()` methods - these are now automatically handled
106
50
 
107
- ### Added
108
- - Core component library with Button, Card, Input, DataTable
109
- - Authentication module with Supabase integration
110
- - RBAC system with permission guards and hooks
111
- - Event management with dynamic theming
112
- - Form validation with Zod schemas
113
- - Comprehensive test utilities and mock providers
114
-
115
- ### Features
116
- - TypeScript support with strict typing
117
- - Tree-shakeable exports
118
- - Tailwind CSS styling
119
- - shadcn/ui component integration
120
- - Accessibility support
121
- - Comprehensive documentation
122
-
123
- ### Components
124
- - **UI Components**: Button, Card, Input, Alert, Avatar, Progress
125
- - **Form Components**: Form, FormField, Input validation
126
- - **Layout Components**: Header, Footer, NavigationMenu
127
- - **Data Components**: DataTable with sorting, filtering, pagination
128
- - **Authentication**: LoginForm, UserMenu, AuthProvider
129
- - **RBAC**: PermissionGuard, RBACProvider
130
-
131
- ### Hooks
132
- - **Authentication**: useAuth, useAutoLogout, useSecureAuth
133
- - **Permissions**: useHasPermission, usePermissionCheck, usePermissions
134
- - **UI**: useToast, useIsMobile, useFocusManagement
135
- - **Forms**: useZodForm, form validation hooks
136
-
137
- ### Utilities
138
- - **Validation**: Email, password, form schemas
139
- - **Security**: Encryption, rate limiting, audit logging
140
- - **Formatting**: Date, currency, percentage formatters
141
- - **Performance**: Debouncing, throttling, memoization
142
-
143
- ### Types
144
- - **Core Types**: User, Session, AuthError, PermissionString
145
- - **Component Types**: ButtonProps, FormProps, DataTableProps
146
- - **Utility Types**: AccessLevel, ValidationError, SecurityLevel
147
-
148
- ## [0.1.0] - Initial Release
149
-
150
- ### Added
151
- - Initial package structure
152
- - Basic component library foundation
153
- - Authentication provider setup
154
- - RBAC permission system
155
- - Form validation utilities
156
- - TypeScript configuration
157
- - Build and test infrastructure
158
-
159
- ### Infrastructure
160
- - Vite build system
161
- - Vitest testing framework
162
- - ESLint and Prettier configuration
163
- - GitHub Actions CI/CD
164
- - NPM publishing workflow
51
+ ### Fixed
52
+ - **SQL Ambiguity in util_app_resolve**: Fixed ambiguous column reference `"is_active"` by using explicit table aliases
53
+ - **Case Sensitivity in App Resolution**: Fixed `util_app_resolve` to use case-insensitive app name matching
54
+ - **Function Return Type Mismatch**: Fixed `util_app_resolve` return type mismatch between function signature and `RETURN QUERY` statement
55
+ - **rbac_permissions_get Function Overloading**: Consolidated two overloaded versions of `rbac_permissions_get` into a single unified function, resolving PostgREST ambiguity issues
56
+ - **Navigation Filtering Permission Format**: Fixed incorrect permission string construction in `PaceAppLayout` navigation filtering (now correctly formats as `"operation:page.pageId"`)
57
+ - **Rate Limit Exceeded Errors**: Fixed navigation filtering causing excessive API calls by implementing batch permission fetching
58
+ - **RLS Policy Permissiveness**: Removed overly permissive RLS policy on `rbac_user_login_history` that allowed system-level inserts without proper context
165
59
 
166
60
  ---
167
61
 
168
62
  ## Migration Guide
169
63
 
170
- ### Upgrading from 0.1.101 to 0.1.102
64
+ ### Upgrading from 0.5.108 to 0.5.109
65
+
66
+ This guide covers upgrading from version **0.5.108** to **0.5.109**.
67
+
68
+ #### Automatic Login History Tracking
69
+
70
+ **No code changes required!** Login history tracking is now fully automatic when using `UnifiedAuthProvider`.
71
+
72
+ **In 0.5.108:**
73
+ ```tsx
74
+ // Manual tracking was required
75
+ import { useSessionTracking } from '@jmruthers/pace-core';
76
+
77
+ function MyComponent() {
78
+ const { trackLogin, trackLogout } = useSessionTracking(supabase, 'MY_APP');
79
+
80
+ useEffect(() => {
81
+ // Manual tracking calls
82
+ trackLogin();
83
+ }, []);
84
+ }
85
+ ```
171
86
 
172
- No breaking changes. This release focuses on improved documentation and developer experience.
87
+ **In 0.5.109:**
88
+ ```tsx
89
+ // Automatic tracking - no code changes needed!
90
+ <UnifiedAuthProvider
91
+ supabaseClient={supabase}
92
+ appName="MY_APP" // This enables automatic tracking
93
+ >
94
+ <App />
95
+ </UnifiedAuthProvider>
96
+ ```
173
97
 
174
- ### Upgrading to Future Versions
98
+ **Migration Steps:**
99
+ 1. ✅ **Remove manual tracking calls** - If you are using `useSessionTracking.trackLogin()` or `trackLogout()`, remove those calls (they're now automatic)
100
+ 2. ✅ **Keep event switch tracking** - If you use `trackEventSwitch()` or `trackSessionExpired()`, those methods are still available
101
+ 3. ✅ **Apply database migrations** - Run the following migrations on your Supabase database:
102
+ - `20251103151742_add_app_id_to_login_history.sql`
103
+ - `20251103151802_modify_session_track_for_login_history.sql`
175
104
 
176
- Check this changelog for breaking changes and migration instructions for each version.
105
+ #### useSessionTracking Hook Changes
177
106
 
178
- ## Security Updates
107
+ **Breaking Change**: The `useSessionTracking` hook no longer provides `trackLogin()` and `trackLogout()` methods in version 0.5.109.
179
108
 
180
- Security fixes will be documented here with details about:
181
- - CVE numbers (if applicable)
182
- - Affected versions
183
- - Recommended upgrade paths
184
- - Workarounds for immediate fixes
109
+ **In 0.5.108:**
110
+ ```tsx
111
+ const { trackLogin, trackLogout, trackEventSwitch } = useSessionTracking(supabase, 'MY_APP');
112
+ ```
185
113
 
186
- ## Deprecation Notices
114
+ **In 0.5.109:**
115
+ ```tsx
116
+ // Only event switch and session expiration are available
117
+ const { trackEventSwitch, trackSessionExpired } = useSessionTracking(supabase, 'MY_APP');
118
+ ```
187
119
 
188
- Features planned for deprecation will be announced here with:
189
- - Deprecation version
190
- - Removal timeline
191
- - Migration instructions
192
- - Alternative solutions
120
+ **If you are using `trackLogin()` or `trackLogout()`:**
121
+ - Remove those calls - they're now automatic
122
+ - No replacement needed - `UnifiedAuthProvider` handles it automatically
193
123
 
194
- ## Roadmap
124
+ #### Navigation Permission String Format
195
125
 
196
- ### v0.2.0 (Planned)
197
- - Enhanced DataTable with virtual scrolling
198
- - Advanced form components (date pickers, file uploads)
199
- - Improved accessibility features
200
- - Performance optimizations
126
+ **Internal Change**: Permission strings in navigation filtering now use the format `"operation:page.pageId"` instead of separate operation and pageId parameters. This fix affects `PaceAppLayout` navigation filtering internally.
201
127
 
202
- ### v0.3.0 (Planned)
203
- - React Server Components support
204
- - Advanced RBAC features
205
- - Internationalization support
206
- - Theme customization system
128
+ **Migration Steps:**
129
+ 1. ✅ **No consumer code changes needed** - This is completely internal to `PaceAppLayout`
130
+ 2. ✅ **Navigation filtering now works correctly** - If you're using `filterNavigationByPermissions`, it will now properly hide unauthorized pages
131
+ 3. ✅ **No action required** - `PaceAppLayout` handles all permission checking for navigation automatically
207
132
 
208
- ### v1.0.0 (Planned)
209
- - Stable API with semantic versioning guarantees
210
- - Complete documentation coverage
211
- - Comprehensive test suite
212
- - Production-ready performance optimizations
@@ -408,7 +408,8 @@ declare class AuthService extends BaseService implements IAuthService {
408
408
  private restorationTimeoutId;
409
409
  private readonly restorationTimeoutMs;
410
410
  private restorationStartTime;
411
- constructor(supabaseClient: SupabaseClient);
411
+ private appName;
412
+ constructor(supabaseClient: SupabaseClient, appName?: string);
412
413
  getUser(): User | null;
413
414
  getSession(): Session | null;
414
415
  isAuthenticated(): boolean;
@@ -431,6 +432,12 @@ declare class AuthService extends BaseService implements IAuthService {
431
432
  private clearRestorationTimeout;
432
433
  private setupAuthStateListener;
433
434
  private restoreSession;
435
+ /**
436
+ * Automatically track user session using rbac_session_track
437
+ * This method is called automatically on SIGNED_IN and SIGNED_OUT events.
438
+ * It's non-blocking and failures are logged as warnings.
439
+ */
440
+ private trackSession;
434
441
  private setupErrorHandlers;
435
442
  private removeErrorHandlers;
436
443
  }
@@ -54,9 +54,9 @@ import {
54
54
  sortHierarchicalDataWithSorting,
55
55
  validateHierarchicalData,
56
56
  validatePaginationConfig
57
- } from "./chunk-IMZGJ2X7.js";
58
- import "./chunk-QDDUU625.js";
59
- import "./chunk-S63MFSY6.js";
57
+ } from "./chunk-HGZSO43Y.js";
58
+ import "./chunk-HADXAZT3.js";
59
+ import "./chunk-XRSP3H52.js";
60
60
  import "./chunk-Q7APDV6H.js";
61
61
  import {
62
62
  CircuitBreaker,
@@ -76,9 +76,9 @@ import {
76
76
  throttle,
77
77
  useDataTablePerformance
78
78
  } from "./chunk-4OX5PXHX.js";
79
- import "./chunk-ZXY5NTJB.js";
80
- import "./chunk-KBG34SVL.js";
81
- import "./chunk-X4FRXJV6.js";
79
+ import "./chunk-EZ64QG2I.js";
80
+ import "./chunk-EYSXQ756.js";
81
+ import "./chunk-AUXS7XSO.js";
82
82
  import "./chunk-PYUXFQJ3.js";
83
83
  import "./chunk-JCQZ6LA7.js";
84
84
  import "./chunk-BDZUMRBD.js";
@@ -157,4 +157,4 @@ export {
157
157
  validateHierarchicalData,
158
158
  validatePaginationConfig
159
159
  };
160
- //# sourceMappingURL=DataTable-WFCHVWTY.js.map
160
+ //# sourceMappingURL=DataTable-D3BK2FCN.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  init_UnifiedAuthProvider
3
- } from "./chunk-KBG34SVL.js";
3
+ } from "./chunk-EYSXQ756.js";
4
4
  import {
5
5
  UnifiedAuthProvider,
6
6
  useUnifiedAuth
7
- } from "./chunk-X4FRXJV6.js";
7
+ } from "./chunk-AUXS7XSO.js";
8
8
  import "./chunk-BDZUMRBD.js";
9
9
  import "./chunk-SMJZMKYN.js";
10
10
  import "./chunk-PLDDJCW6.js";
@@ -13,4 +13,4 @@ export {
13
13
  UnifiedAuthProvider,
14
14
  useUnifiedAuth
15
15
  };
16
- //# sourceMappingURL=UnifiedAuthProvider-XU4BHFXZ.js.map
16
+ //# sourceMappingURL=UnifiedAuthProvider-A7I23UCN.js.map
@@ -19,7 +19,7 @@ import {
19
19
  isSuperAdmin,
20
20
  resolveAppContext,
21
21
  setupRBAC
22
- } from "./chunk-S63MFSY6.js";
22
+ } from "./chunk-XRSP3H52.js";
23
23
  import "./chunk-Q7APDV6H.js";
24
24
  import "./chunk-PLDDJCW6.js";
25
25
  export {
@@ -44,4 +44,4 @@ export {
44
44
  resolveAppContext,
45
45
  setupRBAC
46
46
  };
47
- //# sourceMappingURL=api-KG4A2X7P.js.map
47
+ //# sourceMappingURL=api-PIE4JRFS.js.map
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  init_useOrganisations,
3
3
  useOrganisations
4
- } from "./chunk-ZXY5NTJB.js";
4
+ } from "./chunk-EZ64QG2I.js";
5
5
  import {
6
6
  init_UnifiedAuthProvider
7
- } from "./chunk-KBG34SVL.js";
7
+ } from "./chunk-EYSXQ756.js";
8
8
  import {
9
9
  OrganisationServiceContext,
10
10
  OrganisationServiceProvider,
11
11
  init_OrganisationServiceProvider,
12
12
  useOrganisationService,
13
13
  useUnifiedAuth
14
- } from "./chunk-X4FRXJV6.js";
14
+ } from "./chunk-AUXS7XSO.js";
15
15
  import {
16
16
  init_organisationContext,
17
17
  setOrganisationContext
@@ -1537,4 +1537,4 @@ export {
1537
1537
  clearFileDisplayCache,
1538
1538
  getFileDisplayCacheStats
1539
1539
  };
1540
- //# sourceMappingURL=chunk-DMNMZKWS.js.map
1540
+ //# sourceMappingURL=chunk-2W4WKJVF.js.map
@@ -25,16 +25,16 @@ import {
25
25
  SelectSeparator,
26
26
  SelectTrigger,
27
27
  SelectValue
28
- } from "./chunk-IMZGJ2X7.js";
28
+ } from "./chunk-HGZSO43Y.js";
29
29
  import {
30
30
  usePermissions,
31
31
  useRBAC,
32
32
  useResolvedScope
33
- } from "./chunk-QDDUU625.js";
33
+ } from "./chunk-HADXAZT3.js";
34
34
  import {
35
35
  isPermitted,
36
36
  isSuperAdmin
37
- } from "./chunk-S63MFSY6.js";
37
+ } from "./chunk-XRSP3H52.js";
38
38
  import {
39
39
  OrganisationProvider_exports,
40
40
  PublicErrorBoundary,
@@ -49,18 +49,18 @@ import {
49
49
  useIsPublicPage,
50
50
  usePublicFileDisplay,
51
51
  usePublicPageContext
52
- } from "./chunk-DMNMZKWS.js";
52
+ } from "./chunk-2W4WKJVF.js";
53
53
  import {
54
54
  useToast
55
55
  } from "./chunk-4OX5PXHX.js";
56
56
  import {
57
57
  useEvents,
58
58
  useOrganisations
59
- } from "./chunk-ZXY5NTJB.js";
59
+ } from "./chunk-EZ64QG2I.js";
60
60
  import {
61
61
  UnifiedAuthProvider_exports,
62
62
  init_UnifiedAuthProvider as init_UnifiedAuthProvider2
63
- } from "./chunk-KBG34SVL.js";
63
+ } from "./chunk-EYSXQ756.js";
64
64
  import {
65
65
  EventServiceContext,
66
66
  EventServiceProvider,
@@ -70,7 +70,7 @@ import {
70
70
  useEventService,
71
71
  useSessionRestoration,
72
72
  useUnifiedAuth
73
- } from "./chunk-X4FRXJV6.js";
73
+ } from "./chunk-AUXS7XSO.js";
74
74
  import {
75
75
  LoadingSpinner
76
76
  } from "./chunk-CDQ3PX7L.js";
@@ -929,8 +929,12 @@ var NavigationMenu = React9.forwardRef(({
929
929
  if (!filterByPermissions || !authContext || !rbacContext || scopeLoading || permissionsLoading || !resolvedScope?.organisationId) {
930
930
  return (items || []).filter((item) => !item.meta?.hidden);
931
931
  }
932
- return (items || []).filter((item) => {
933
- if (item.meta?.hidden) return false;
932
+ const getPageIdFromHref = (href) => {
933
+ if (!href) return null;
934
+ const path = href.split("?")[0].split("#")[0].replace(/^\//, "");
935
+ return path || "home";
936
+ };
937
+ const hasItemPermission = (item) => {
934
938
  if (item.permissions && item.permissions.length > 0) {
935
939
  const permissions = item.permissions.filter((p) => typeof p === "string").map((p) => p);
936
940
  if (permissions.length > 0) {
@@ -986,8 +990,43 @@ var NavigationMenu = React9.forwardRef(({
986
990
  }
987
991
  }
988
992
  }
993
+ if (item.href && !item.permissions && !item.roles && !item.accessLevel) {
994
+ const pageId = item.pageId || getPageIdFromHref(item.href);
995
+ if (pageId) {
996
+ const pagePermission = `read:page.${pageId}`;
997
+ const hasPagePermission = permissionMap["*"] === true || permissionMap[pagePermission] === true;
998
+ if (!hasPagePermission) {
999
+ if (auditLog) {
1000
+ console.log(`[NavigationMenu] Filtering out navigation item "${item.label}" - no page permission:`, {
1001
+ itemId: item.id,
1002
+ href: item.href,
1003
+ pageId,
1004
+ permission: pagePermission,
1005
+ hasPermission: hasPagePermission
1006
+ });
1007
+ }
1008
+ return false;
1009
+ }
1010
+ }
1011
+ }
989
1012
  return true;
990
- });
1013
+ };
1014
+ const filterItem = (item) => {
1015
+ if (item.meta?.hidden) return null;
1016
+ if (!hasItemPermission(item)) return null;
1017
+ let filteredChildren;
1018
+ if (item.children && item.children.length > 0) {
1019
+ filteredChildren = item.children.map((child) => filterItem(child)).filter((child) => child !== null);
1020
+ if (filteredChildren.length === 0 && !item.href) {
1021
+ return null;
1022
+ }
1023
+ }
1024
+ return {
1025
+ ...item,
1026
+ children: filteredChildren
1027
+ };
1028
+ };
1029
+ return (items || []).map((item) => filterItem(item)).filter((item) => item !== null);
991
1030
  }, [
992
1031
  items,
993
1032
  filterByPermissions,
@@ -997,7 +1036,8 @@ var NavigationMenu = React9.forwardRef(({
997
1036
  hasAnyPermission,
998
1037
  scopeLoading,
999
1038
  permissionsLoading,
1000
- resolvedScope
1039
+ resolvedScope,
1040
+ auditLog
1001
1041
  ]);
1002
1042
  React9.useEffect(() => {
1003
1043
  if (auditLog && authContext) {
@@ -1379,7 +1419,7 @@ function PaceAppLayout({
1379
1419
  appId: user.user_metadata?.appId || user.app_metadata?.appId
1380
1420
  };
1381
1421
  try {
1382
- const { isSuperAdmin: isSuperAdmin2 } = await import("./api-KG4A2X7P.js");
1422
+ const { isSuperAdmin: isSuperAdmin2 } = await import("./api-PIE4JRFS.js");
1383
1423
  const isSuper = await isSuperAdmin2(user.id);
1384
1424
  if (isSuper) {
1385
1425
  return true;
@@ -1394,10 +1434,11 @@ function PaceAppLayout({
1394
1434
  console.warn("No organisation context available for permission check, denying access");
1395
1435
  return false;
1396
1436
  }
1437
+ const fullPermission = permission.includes(":") ? permission : pageId ? `${permission}:page.${pageId}` : permission;
1397
1438
  return await isPermitted({
1398
1439
  userId: user.id,
1399
1440
  scope,
1400
- permission,
1441
+ permission: fullPermission,
1401
1442
  pageId
1402
1443
  });
1403
1444
  } catch (error) {
@@ -1498,7 +1539,7 @@ function PaceAppLayout({
1498
1539
  appId: user.user_metadata?.appId || user.app_metadata?.appId
1499
1540
  };
1500
1541
  try {
1501
- const { isSuperAdmin: isSuperAdmin2 } = await import("./api-KG4A2X7P.js");
1542
+ const { isSuperAdmin: isSuperAdmin2 } = await import("./api-PIE4JRFS.js");
1502
1543
  const isSuper = await isSuperAdmin2(user.id);
1503
1544
  if (isSuper) {
1504
1545
  if (isMounted) {
@@ -1518,22 +1559,38 @@ function PaceAppLayout({
1518
1559
  }
1519
1560
  return;
1520
1561
  }
1521
- const filtered = await Promise.all(
1522
- baseMenuItems.map(async (item) => {
1562
+ try {
1563
+ const { getPermissionMap } = await import("./api-PIE4JRFS.js");
1564
+ const permissionMap = await getPermissionMap({
1565
+ userId: user.id,
1566
+ scope
1567
+ });
1568
+ const filtered = baseMenuItems.map((item) => {
1523
1569
  if (!item.href) return { item, hasAccess: true };
1524
1570
  const pageId = pageIdMapping[item.href] || item.href.slice(1) || "home";
1525
1571
  const permission = routePermissions[item.href] || defaultPermission;
1526
- try {
1527
- const hasAccess = await checkPermission(permission, pageId);
1528
- return { item, hasAccess };
1529
- } catch {
1530
- return { item, hasAccess: false };
1572
+ const fullPermission = permission.includes(":") ? permission : pageId ? `${permission}:page.${pageId}` : permission;
1573
+ const hasAccess = permissionMap["*"] === true || permissionMap[fullPermission] === true;
1574
+ if (auditLog) {
1575
+ console.log(`[PaceAppLayout] Navigation filtering:`, {
1576
+ item: item.label,
1577
+ href: item.href,
1578
+ pageId,
1579
+ permission: fullPermission,
1580
+ hasAccess
1581
+ });
1531
1582
  }
1532
- })
1533
- );
1534
- if (!isMounted) return;
1535
- const accessibleItems = filtered.filter(({ hasAccess }) => hasAccess).map(({ item }) => item);
1536
- setFilteredMenuItems(accessibleItems);
1583
+ return { item, hasAccess };
1584
+ });
1585
+ if (!isMounted) return;
1586
+ const accessibleItems = filtered.filter(({ hasAccess }) => hasAccess).map(({ item }) => item);
1587
+ setFilteredMenuItems(accessibleItems);
1588
+ } catch (error) {
1589
+ console.error("[PaceAppLayout] Failed to load permission map for navigation filtering:", error);
1590
+ if (isMounted) {
1591
+ setFilteredMenuItems(baseMenuItems);
1592
+ }
1593
+ }
1537
1594
  };
1538
1595
  filterItems();
1539
1596
  return () => {
@@ -1572,7 +1629,7 @@ function PaceAppLayout({
1572
1629
  }
1573
1630
  }
1574
1631
  if (hasAccess && currentRoute.roles && currentRoute.roles.length > 0 && user?.id) {
1575
- const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-XU4BHFXZ.js");
1632
+ const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-A7I23UCN.js");
1576
1633
  hasAccess = true;
1577
1634
  }
1578
1635
  if (!isMounted) return;
@@ -4396,4 +4453,4 @@ export {
4396
4453
  PublicPageDiagnostic,
4397
4454
  PublicPageContextChecker
4398
4455
  };
4399
- //# sourceMappingURL=chunk-B3QX32P5.js.map
4456
+ //# sourceMappingURL=chunk-3J5N2T2N.js.map