@jmruthers/pace-core 0.5.108 → 0.5.109

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 (177) hide show
  1. package/CHANGELOG.md +75 -177
  2. package/dist/{AuthService-1D2ifNfa.d.ts → AuthService-DrHrvXNZ.d.ts} +8 -1
  3. package/dist/{DataTable-WFCHVWTY.js → DataTable-5HITILXS.js} +7 -7
  4. package/dist/{UnifiedAuthProvider-XU4BHFXZ.js → UnifiedAuthProvider-A7I23UCN.js} +3 -3
  5. package/dist/{api-KG4A2X7P.js → api-5I3E47G2.js} +2 -2
  6. package/dist/{chunk-DMNMZKWS.js → chunk-2W4WKJVF.js} +4 -4
  7. package/dist/{chunk-MOMYOQMC.js → chunk-3TKTL5AZ.js} +13 -13
  8. package/dist/{chunk-X4FRXJV6.js → chunk-AUXS7XSO.js} +57 -6
  9. package/dist/{chunk-X4FRXJV6.js.map → chunk-AUXS7XSO.js.map} +1 -1
  10. package/dist/{chunk-LT6RKRA7.js → chunk-D6MEKC27.js} +2 -2
  11. package/dist/{chunk-KBG34SVL.js → chunk-EYSXQ756.js} +2 -2
  12. package/dist/{chunk-ZXY5NTJB.js → chunk-EZ64QG2I.js} +2 -2
  13. package/dist/{chunk-S63MFSY6.js → chunk-F6TSYCKP.js} +4 -2
  14. package/dist/{chunk-S63MFSY6.js.map → chunk-F6TSYCKP.js.map} +1 -1
  15. package/dist/chunk-GZRXOUBE.js +176 -0
  16. package/dist/chunk-GZRXOUBE.js.map +1 -0
  17. package/dist/{chunk-B3QX32P5.js → chunk-P72NKAT5.js} +41 -24
  18. package/dist/chunk-P72NKAT5.js.map +1 -0
  19. package/dist/{chunk-VJ7MPS2K.js → chunk-S4D3Z723.js} +6 -6
  20. package/dist/{chunk-IMZGJ2X7.js → chunk-UW2DE6JX.js} +4 -4
  21. package/dist/{chunk-QDDUU625.js → chunk-WWNOVFDC.js} +4 -4
  22. package/dist/{chunk-GVRSXXAA.js → chunk-YFMENCR4.js} +3 -3
  23. package/dist/components.js +9 -9
  24. package/dist/{database-BXAfr2Y_.d.ts → database-C6jy7EOu.d.ts} +21 -9
  25. package/dist/{formatting-BiEv5oEk.d.ts → formatting-B1jSqgl-.d.ts} +16 -1
  26. package/dist/hooks.d.ts +2 -2
  27. package/dist/hooks.js +7 -7
  28. package/dist/index.d.ts +6 -6
  29. package/dist/index.js +16 -14
  30. package/dist/index.js.map +1 -1
  31. package/dist/providers.d.ts +4 -3
  32. package/dist/providers.js +2 -2
  33. package/dist/rbac/index.d.ts +1 -1
  34. package/dist/rbac/index.js +8 -8
  35. package/dist/types.d.ts +2 -2
  36. package/dist/{usePublicRouteParams-CnM-IK2I.d.ts → usePublicRouteParams-BdF8bZgs.d.ts} +1 -1
  37. package/dist/utils.d.ts +2 -15
  38. package/dist/utils.js +4 -145
  39. package/dist/utils.js.map +1 -1
  40. package/dist/validation.d.ts +1 -1
  41. package/docs/api/classes/ColumnFactory.md +1 -1
  42. package/docs/api/classes/ErrorBoundary.md +1 -1
  43. package/docs/api/classes/InvalidScopeError.md +1 -1
  44. package/docs/api/classes/MissingUserContextError.md +1 -1
  45. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  46. package/docs/api/classes/PermissionDeniedError.md +1 -1
  47. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  48. package/docs/api/classes/RBACAuditManager.md +1 -1
  49. package/docs/api/classes/RBACCache.md +1 -1
  50. package/docs/api/classes/RBACEngine.md +1 -1
  51. package/docs/api/classes/RBACError.md +1 -1
  52. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  53. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  54. package/docs/api/classes/StorageUtils.md +1 -1
  55. package/docs/api/enums/FileCategory.md +1 -1
  56. package/docs/api/interfaces/AggregateConfig.md +1 -1
  57. package/docs/api/interfaces/ButtonProps.md +1 -1
  58. package/docs/api/interfaces/CardProps.md +1 -1
  59. package/docs/api/interfaces/ColorPalette.md +1 -1
  60. package/docs/api/interfaces/ColorShade.md +1 -1
  61. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  62. package/docs/api/interfaces/DataRecord.md +1 -1
  63. package/docs/api/interfaces/DataTableAction.md +1 -1
  64. package/docs/api/interfaces/DataTableColumn.md +3 -3
  65. package/docs/api/interfaces/DataTableProps.md +1 -1
  66. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  67. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  68. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  69. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  70. package/docs/api/interfaces/FileMetadata.md +1 -1
  71. package/docs/api/interfaces/FileReference.md +1 -1
  72. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  73. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  74. package/docs/api/interfaces/FileUploadProps.md +1 -1
  75. package/docs/api/interfaces/FooterProps.md +1 -1
  76. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  77. package/docs/api/interfaces/InputProps.md +1 -1
  78. package/docs/api/interfaces/LabelProps.md +1 -1
  79. package/docs/api/interfaces/LoginFormProps.md +1 -1
  80. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  81. package/docs/api/interfaces/NavigationContextType.md +1 -1
  82. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  83. package/docs/api/interfaces/NavigationItem.md +1 -1
  84. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  85. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  86. package/docs/api/interfaces/Organisation.md +1 -1
  87. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  88. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  89. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  90. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  91. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  92. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  93. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  94. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  95. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  96. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  97. package/docs/api/interfaces/PaletteData.md +1 -1
  98. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  99. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  100. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  101. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  102. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  103. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  104. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  105. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  106. package/docs/api/interfaces/RBACConfig.md +1 -1
  107. package/docs/api/interfaces/RBACLogger.md +1 -1
  108. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  109. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  110. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  111. package/docs/api/interfaces/RouteConfig.md +1 -1
  112. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  113. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  114. package/docs/api/interfaces/StorageConfig.md +1 -1
  115. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  116. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  117. package/docs/api/interfaces/StorageListOptions.md +1 -1
  118. package/docs/api/interfaces/StorageListResult.md +1 -1
  119. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  120. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  121. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  122. package/docs/api/interfaces/StyleImport.md +1 -1
  123. package/docs/api/interfaces/SwitchProps.md +1 -1
  124. package/docs/api/interfaces/ToastActionElement.md +1 -1
  125. package/docs/api/interfaces/ToastProps.md +1 -1
  126. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  127. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  128. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  129. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  130. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  131. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  132. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  133. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  134. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  135. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  136. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  137. package/docs/api/interfaces/UserEventAccess.md +1 -1
  138. package/docs/api/interfaces/UserMenuProps.md +1 -1
  139. package/docs/api/interfaces/UserProfile.md +1 -1
  140. package/docs/api/modules.md +37 -3
  141. package/docs/api-reference/hooks.md +53 -0
  142. package/docs/api-reference/providers.md +60 -0
  143. package/docs/core-concepts/authentication.md +2 -0
  144. package/docs/implementation-guides/authentication.md +1 -0
  145. package/docs/security/README.md +59 -0
  146. package/package.json +1 -1
  147. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +2 -2
  148. package/src/components/PaceAppLayout/PaceAppLayout.tsx +48 -16
  149. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +2 -1
  150. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +9 -9
  151. package/src/index.ts +3 -0
  152. package/src/providers/services/AuthServiceProvider.tsx +4 -3
  153. package/src/providers/services/UnifiedAuthProvider.tsx +1 -1
  154. package/src/rbac/engine.ts +2 -0
  155. package/src/services/AuthService.ts +79 -1
  156. package/src/services/__tests__/AuthService.test.ts +184 -0
  157. package/src/types/database.ts +21 -9
  158. package/src/types/rbac-functions.ts +2 -1
  159. package/src/utils/__tests__/sessionTracking.unit.test.ts +6 -171
  160. package/src/utils/sessionTracking.ts +7 -81
  161. package/dist/chunk-B3QX32P5.js.map +0 -1
  162. package/dist/chunk-NFPV7MRN.js +0 -94
  163. package/dist/chunk-NFPV7MRN.js.map +0 -1
  164. package/src/providers/AuthProvider.simplified.tsx +0 -974
  165. package/dist/{DataTable-WFCHVWTY.js.map → DataTable-5HITILXS.js.map} +0 -0
  166. package/dist/{UnifiedAuthProvider-XU4BHFXZ.js.map → UnifiedAuthProvider-A7I23UCN.js.map} +0 -0
  167. package/dist/{api-KG4A2X7P.js.map → api-5I3E47G2.js.map} +0 -0
  168. package/dist/{chunk-DMNMZKWS.js.map → chunk-2W4WKJVF.js.map} +0 -0
  169. package/dist/{chunk-MOMYOQMC.js.map → chunk-3TKTL5AZ.js.map} +0 -0
  170. package/dist/{chunk-LT6RKRA7.js.map → chunk-D6MEKC27.js.map} +0 -0
  171. package/dist/{chunk-KBG34SVL.js.map → chunk-EYSXQ756.js.map} +0 -0
  172. package/dist/{chunk-ZXY5NTJB.js.map → chunk-EZ64QG2I.js.map} +0 -0
  173. package/dist/{chunk-VJ7MPS2K.js.map → chunk-S4D3Z723.js.map} +0 -0
  174. package/dist/{chunk-IMZGJ2X7.js.map → chunk-UW2DE6JX.js.map} +0 -0
  175. package/dist/{chunk-QDDUU625.js.map → chunk-WWNOVFDC.js.map} +0 -0
  176. package/dist/{chunk-GVRSXXAA.js.map → chunk-YFMENCR4.js.map} +0 -0
  177. package/dist/{validation-D8VcbTzC.d.ts → validation-DnhrNMju.d.ts} +2 -2
package/CHANGELOG.md CHANGED
@@ -7,206 +7,104 @@ 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.109] - 2025-11-03
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 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.
14
+ - **Login History Database Schema**: Added `app_id` column to `rbac_user_login_history` table for application-specific tracking
15
+ - **Performance Indexes**: Added indexes on `login_timestamp` and `(user_id, login_timestamp)` for efficient login history queries
16
+ - **Session Tracking Integration**: `AuthService` now automatically calls `rbac_session_track` on login/logout events, which records both session data and login history
17
+ - **Comprehensive Session Tracking Tests**: Added unit tests for automatic session tracking functionality
44
18
 
45
19
  ### 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
20
+ - **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.
21
+ - **Database Function Enhancement**: Modified `rbac_session_track` RPC function to automatically insert into `rbac_user_login_history` table when `session_type = 'login'`
22
+ - **RBAC Permission String Format**: Updated permission string format to `"operation:page.pageId"` (e.g., `"read:page.suppliers"`) for consistent permission checking
23
+ - **Navigation Filtering Optimization**: Optimized `PaceAppLayout` navigation filtering to use `getPermissionMap` for batch permission fetching, preventing rate limit exceeded errors
48
24
 
49
- ### Fixed
50
- - **Actions Prop Implementation**: Verified and confirmed that the `actions` prop is fully implemented and working correctly in DataTable component
25
+ ### Removed
26
+ - **AuthProvider.simplified.tsx**: Removed unused experimental auth provider file (tech debt cleanup)
27
+ - **useSessionTracking Methods**: Removed `trackLogin()` and `trackLogout()` methods - these are now automatically handled
51
28
 
52
29
  ### 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
63
-
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
88
-
89
- ### 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
30
+ - **SQL Ambiguity in util_app_resolve**: Fixed ambiguous column reference `"is_active"` by using explicit table aliases
31
+ - **Case Sensitivity in App Resolution**: Fixed `util_app_resolve` to use case-insensitive app name matching
32
+ - **Function Return Type Mismatch**: Fixed `util_app_resolve` return type mismatch between function signature and `RETURN QUERY` statement
33
+ - **rbac_permissions_get Function Overloading**: Consolidated two overloaded versions of `rbac_permissions_get` into a single unified function, resolving PostgREST ambiguity issues
34
+ - **Navigation Filtering Permission Format**: Fixed incorrect permission string construction in `PaceAppLayout` navigation filtering (now correctly formats as `"operation:page.pageId"`)
35
+ - **Rate Limit Exceeded Errors**: Fixed navigation filtering causing excessive API calls by implementing batch permission fetching
36
+ - **RLS Policy Permissiveness**: Removed overly permissive RLS policy on `rbac_user_login_history` that allowed system-level inserts without proper context
94
37
 
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
38
+ ---
99
39
 
100
- ### 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
40
+ ## Migration Guide
104
41
 
105
- ## [0.1.101] - Previous Release
42
+ ### Upgrading from 0.5.108 to 0.5.109
106
43
 
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
44
+ This guide covers upgrading from version **0.5.108** to **0.5.109**.
149
45
 
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
46
+ #### Automatic Login History Tracking
165
47
 
166
- ---
48
+ **No code changes required!** Login history tracking is now fully automatic when using `UnifiedAuthProvider`.
167
49
 
168
- ## Migration Guide
50
+ **In 0.5.108:**
51
+ ```tsx
52
+ // Manual tracking was required
53
+ import { useSessionTracking } from '@jmruthers/pace-core';
169
54
 
170
- ### Upgrading from 0.1.101 to 0.1.102
55
+ function MyComponent() {
56
+ const { trackLogin, trackLogout } = useSessionTracking(supabase, 'MY_APP');
57
+
58
+ useEffect(() => {
59
+ // Manual tracking calls
60
+ trackLogin();
61
+ }, []);
62
+ }
63
+ ```
171
64
 
172
- No breaking changes. This release focuses on improved documentation and developer experience.
65
+ **In 0.5.109:**
66
+ ```tsx
67
+ // Automatic tracking - no code changes needed!
68
+ <UnifiedAuthProvider
69
+ supabaseClient={supabase}
70
+ appName="MY_APP" // This enables automatic tracking
71
+ >
72
+ <App />
73
+ </UnifiedAuthProvider>
74
+ ```
173
75
 
174
- ### Upgrading to Future Versions
76
+ **Migration Steps:**
77
+ 1. ✅ **Remove manual tracking calls** - If you are using `useSessionTracking.trackLogin()` or `trackLogout()`, remove those calls (they're now automatic)
78
+ 2. ✅ **Keep event switch tracking** - If you use `trackEventSwitch()` or `trackSessionExpired()`, those methods are still available
79
+ 3. ✅ **Apply database migrations** - Run the following migrations on your Supabase database:
80
+ - `20251103151742_add_app_id_to_login_history.sql`
81
+ - `20251103151802_modify_session_track_for_login_history.sql`
175
82
 
176
- Check this changelog for breaking changes and migration instructions for each version.
83
+ #### useSessionTracking Hook Changes
177
84
 
178
- ## Security Updates
85
+ **Breaking Change**: The `useSessionTracking` hook no longer provides `trackLogin()` and `trackLogout()` methods in version 0.5.109.
179
86
 
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
87
+ **In 0.5.108:**
88
+ ```tsx
89
+ const { trackLogin, trackLogout, trackEventSwitch } = useSessionTracking(supabase, 'MY_APP');
90
+ ```
185
91
 
186
- ## Deprecation Notices
92
+ **In 0.5.109:**
93
+ ```tsx
94
+ // Only event switch and session expiration are available
95
+ const { trackEventSwitch, trackSessionExpired } = useSessionTracking(supabase, 'MY_APP');
96
+ ```
187
97
 
188
- Features planned for deprecation will be announced here with:
189
- - Deprecation version
190
- - Removal timeline
191
- - Migration instructions
192
- - Alternative solutions
98
+ **If you are using `trackLogin()` or `trackLogout()`:**
99
+ - Remove those calls - they're now automatic
100
+ - No replacement needed - `UnifiedAuthProvider` handles it automatically
193
101
 
194
- ## Roadmap
102
+ #### Navigation Permission String Format
195
103
 
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
104
+ **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
105
 
202
- ### v0.3.0 (Planned)
203
- - React Server Components support
204
- - Advanced RBAC features
205
- - Internationalization support
206
- - Theme customization system
106
+ **Migration Steps:**
107
+ 1. ✅ **No consumer code changes needed** - This is completely internal to `PaceAppLayout`
108
+ 2. ✅ **Navigation filtering now works correctly** - If you're using `filterNavigationByPermissions`, it will now properly hide unauthorized pages
109
+ 3. ✅ **No action required** - `PaceAppLayout` handles all permission checking for navigation automatically
207
110
 
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-UW2DE6JX.js";
58
+ import "./chunk-WWNOVFDC.js";
59
+ import "./chunk-F6TSYCKP.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-5HITILXS.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-F6TSYCKP.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-5I3E47G2.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
@@ -2,22 +2,22 @@ import {
2
2
  createScopeFromEvent,
3
3
  useAccessLevel,
4
4
  useCan
5
- } from "./chunk-QDDUU625.js";
5
+ } from "./chunk-WWNOVFDC.js";
6
6
  import {
7
7
  OrganisationContextRequiredError,
8
8
  RBACCache,
9
9
  getRBACLogger,
10
10
  rbacCache
11
- } from "./chunk-S63MFSY6.js";
11
+ } from "./chunk-F6TSYCKP.js";
12
12
  import {
13
13
  useSecureDataAccess
14
- } from "./chunk-GVRSXXAA.js";
14
+ } from "./chunk-YFMENCR4.js";
15
15
  import {
16
16
  init_UnifiedAuthProvider
17
- } from "./chunk-KBG34SVL.js";
17
+ } from "./chunk-EYSXQ756.js";
18
18
  import {
19
19
  useUnifiedAuth
20
- } from "./chunk-X4FRXJV6.js";
20
+ } from "./chunk-AUXS7XSO.js";
21
21
  import {
22
22
  getCurrentAppName
23
23
  } from "./chunk-JCQZ6LA7.js";
@@ -1539,7 +1539,7 @@ function withPermissionGuard(config, handler) {
1539
1539
  if (!userId || !organisationId) {
1540
1540
  throw new Error("User context required for permission check");
1541
1541
  }
1542
- const { isPermitted: isPermitted2 } = await import("./api-KG4A2X7P.js");
1542
+ const { isPermitted: isPermitted2 } = await import("./api-5I3E47G2.js");
1543
1543
  const hasPermission2 = await isPermitted2({
1544
1544
  userId,
1545
1545
  scope: { organisationId, eventId, appId },
@@ -1562,7 +1562,7 @@ function withAccessLevelGuard(minLevel, handler) {
1562
1562
  if (!userId || !organisationId) {
1563
1563
  throw new Error("User context required for access level check");
1564
1564
  }
1565
- const { getAccessLevel: getAccessLevel2 } = await import("./api-KG4A2X7P.js");
1565
+ const { getAccessLevel: getAccessLevel2 } = await import("./api-5I3E47G2.js");
1566
1566
  const accessLevel = await getAccessLevel2({
1567
1567
  userId,
1568
1568
  scope: { organisationId, eventId, appId }
@@ -1587,7 +1587,7 @@ function withRoleGuard(config, handler) {
1587
1587
  throw new Error("User context required for role check");
1588
1588
  }
1589
1589
  if (config.globalRoles && config.globalRoles.length > 0) {
1590
- const { isSuperAdmin } = await import("./api-KG4A2X7P.js");
1590
+ const { isSuperAdmin } = await import("./api-5I3E47G2.js");
1591
1591
  const isSuper = await isSuperAdmin(userId);
1592
1592
  if (isSuper) {
1593
1593
  if (organisationId) {
@@ -1613,14 +1613,14 @@ function withRoleGuard(config, handler) {
1613
1613
  }
1614
1614
  }
1615
1615
  if (config.organisationRoles && config.organisationRoles.length > 0) {
1616
- const { isOrganisationAdmin } = await import("./api-KG4A2X7P.js");
1616
+ const { isOrganisationAdmin } = await import("./api-5I3E47G2.js");
1617
1617
  const isOrgAdmin = await isOrganisationAdmin(userId, organisationId);
1618
1618
  if (!isOrgAdmin && config.requireAll !== false) {
1619
1619
  throw new Error(`Organisation admin role required`);
1620
1620
  }
1621
1621
  }
1622
1622
  if (config.eventAppRoles && config.eventAppRoles.length > 0 && eventId && appId) {
1623
- const { isEventAdmin } = await import("./api-KG4A2X7P.js");
1623
+ const { isEventAdmin } = await import("./api-5I3E47G2.js");
1624
1624
  const isEventAdminUser = await isEventAdmin(userId, { organisationId, eventId, appId });
1625
1625
  if (!isEventAdminUser && config.requireAll !== false) {
1626
1626
  throw new Error(`Event admin role required`);
@@ -1660,7 +1660,7 @@ function createRBACMiddleware(config) {
1660
1660
  );
1661
1661
  if (protectedRoute) {
1662
1662
  try {
1663
- const { isPermitted: isPermitted2 } = await import("./api-KG4A2X7P.js");
1663
+ const { isPermitted: isPermitted2 } = await import("./api-5I3E47G2.js");
1664
1664
  const hasPermission2 = await isPermitted2({
1665
1665
  userId,
1666
1666
  scope: { organisationId },
@@ -1687,7 +1687,7 @@ function createRBACExpressMiddleware(config) {
1687
1687
  return res.status(401).json({ error: "User context required" });
1688
1688
  }
1689
1689
  try {
1690
- const { isPermitted: isPermitted2 } = await import("./api-KG4A2X7P.js");
1690
+ const { isPermitted: isPermitted2 } = await import("./api-5I3E47G2.js");
1691
1691
  const hasPermission2 = await isPermitted2({
1692
1692
  userId,
1693
1693
  scope: { organisationId, eventId, appId },
@@ -1860,4 +1860,4 @@ export {
1860
1860
  getPermissionsForRole,
1861
1861
  ALL_PERMISSIONS
1862
1862
  };
1863
- //# sourceMappingURL=chunk-MOMYOQMC.js.map
1863
+ //# sourceMappingURL=chunk-3TKTL5AZ.js.map
@@ -93,7 +93,7 @@ var init_AuthService = __esm({
93
93
  "use strict";
94
94
  init_BaseService();
95
95
  AuthService = class extends BaseService {
96
- constructor(supabaseClient) {
96
+ constructor(supabaseClient, appName) {
97
97
  super();
98
98
  this.user = null;
99
99
  this.session = null;
@@ -109,7 +109,9 @@ var init_AuthService = __esm({
109
109
  this.restorationTimeoutId = null;
110
110
  this.restorationTimeoutMs = 5e3;
111
111
  this.restorationStartTime = null;
112
+ this.appName = void 0;
112
113
  this.supabaseClient = supabaseClient;
114
+ this.appName = appName;
113
115
  }
114
116
  // Auth state getters
115
117
  getUser() {
@@ -399,12 +401,22 @@ var init_AuthService = __esm({
399
401
  this.session = null;
400
402
  this.user = null;
401
403
  this.authError = null;
404
+ if (session?.user) {
405
+ this.trackSession("logout", session).catch((err) => {
406
+ console.warn("[AuthService] Failed to track logout session:", err);
407
+ });
408
+ }
402
409
  } else if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED") {
403
410
  this.session = session;
404
411
  this.user = session?.user ?? null;
405
412
  if (session) {
406
413
  this.authError = null;
407
414
  }
415
+ if (event === "SIGNED_IN" && session?.user) {
416
+ this.trackSession("login", session).catch((err) => {
417
+ console.warn("[AuthService] Failed to track login session:", err);
418
+ });
419
+ }
408
420
  } else if (event === "INITIAL_SESSION") {
409
421
  if (session) {
410
422
  this.session = session;
@@ -489,6 +501,45 @@ var init_AuthService = __esm({
489
501
  this.finishSessionRestoration(restorationError);
490
502
  }
491
503
  }
504
+ /**
505
+ * Automatically track user session using rbac_session_track
506
+ * This method is called automatically on SIGNED_IN and SIGNED_OUT events.
507
+ * It's non-blocking and failures are logged as warnings.
508
+ */
509
+ async trackSession(sessionType, session) {
510
+ if (!this.supabaseClient || !session?.user) {
511
+ return;
512
+ }
513
+ try {
514
+ let appId = void 0;
515
+ if (this.appName) {
516
+ const { data, error: error2 } = await this.supabaseClient.from("rbac_apps").select("id").eq("name", this.appName).eq("is_active", true).single();
517
+ if (!error2 && data) {
518
+ appId = data.id;
519
+ }
520
+ }
521
+ const ipAddress = void 0;
522
+ const userAgent = typeof navigator !== "undefined" ? navigator.userAgent : void 0;
523
+ const deviceFingerprint = void 0;
524
+ const { error } = await this.supabaseClient.rpc("rbac_session_track", {
525
+ p_user_id: session.user.id,
526
+ p_session_type: sessionType,
527
+ p_event_id: null,
528
+ // Event ID should come from context, not auth service
529
+ p_app_id: appId,
530
+ p_ip_address: ipAddress,
531
+ p_user_agent: userAgent,
532
+ p_device_fingerprint: deviceFingerprint
533
+ });
534
+ if (error) {
535
+ console.warn(`[AuthService] Failed to track ${sessionType} session:`, error);
536
+ } else {
537
+ console.debug(`[AuthService] Successfully tracked ${sessionType} session`);
538
+ }
539
+ } catch (error) {
540
+ console.warn(`[AuthService] Error tracking ${sessionType} session:`, error);
541
+ }
542
+ }
492
543
  setupErrorHandlers() {
493
544
  if (typeof window === "undefined") return;
494
545
  const handleError = (event) => {
@@ -518,10 +569,10 @@ var init_AuthService = __esm({
518
569
  // src/providers/services/AuthServiceProvider.tsx
519
570
  import { createContext, useContext, useMemo, useEffect, useState } from "react";
520
571
  import { jsx } from "react/jsx-runtime";
521
- function AuthServiceProvider({ children, supabaseClient }) {
572
+ function AuthServiceProvider({ children, supabaseClient, appName }) {
522
573
  const authService = useMemo(
523
- () => new AuthService(supabaseClient),
524
- [supabaseClient]
574
+ () => new AuthService(supabaseClient, appName),
575
+ [supabaseClient, appName]
525
576
  );
526
577
  const [sessionRestoration, setSessionRestoration] = useState(
527
578
  () => authService.getSessionRestorationState()
@@ -2281,7 +2332,7 @@ function UnifiedAuthProvider({
2281
2332
  renderInactivityWarning,
2282
2333
  dangerouslyDisableInactivity = false
2283
2334
  }) {
2284
- return /* @__PURE__ */ jsx5(AuthServiceProvider, { supabaseClient, children: /* @__PURE__ */ jsx5(
2335
+ return /* @__PURE__ */ jsx5(AuthServiceProvider, { supabaseClient, appName, children: /* @__PURE__ */ jsx5(
2285
2336
  ServiceAwareProviders,
2286
2337
  {
2287
2338
  supabaseClient,
@@ -2355,4 +2406,4 @@ export {
2355
2406
  UnifiedAuthProvider,
2356
2407
  init_UnifiedAuthProvider
2357
2408
  };
2358
- //# sourceMappingURL=chunk-X4FRXJV6.js.map
2409
+ //# sourceMappingURL=chunk-AUXS7XSO.js.map