@jmruthers/pace-core 0.5.76 → 0.5.78

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 (447) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{RBACService-C4udt_Zp.d.ts → AuthService-Df3IozMG.d.ts} +10 -118
  3. package/dist/{DataTable-ntgmhO2W.d.ts → DataTable-BE0OXZKQ.d.ts} +9 -2
  4. package/dist/{DataTable-4GAVPIEG.js → DataTable-ETGVF4Y5.js} +50 -13
  5. package/dist/{PublicLoadingSpinner-BiNER8F5.d.ts → PublicLoadingSpinner-CnUaz0vG.d.ts} +5 -2
  6. package/dist/{UnifiedAuthProvider-Bj6YCf7c.d.ts → UnifiedAuthProvider-B391Aqum.d.ts} +42 -45
  7. package/dist/{UnifiedAuthProvider-3NKDOSOK.js → UnifiedAuthProvider-P5SOJAQ6.js} +4 -5
  8. package/dist/{api-DDMUKIUD.js → api-KG4A2X7P.js} +9 -3
  9. package/dist/{audit-6TOCAMKO.js → audit-65VNHEV2.js} +2 -2
  10. package/dist/{chunk-K34IM5CT.js → chunk-2OGV6IRV.js} +196 -626
  11. package/dist/chunk-2OGV6IRV.js.map +1 -0
  12. package/dist/{chunk-NTNILOBC.js → chunk-5BO3MI5Y.js} +4 -4
  13. package/dist/{chunk-XLZ7U46Z.js → chunk-CVMVPYAL.js} +9 -60
  14. package/dist/chunk-CVMVPYAL.js.map +1 -0
  15. package/dist/{chunk-URUTVZ7N.js → chunk-FL4ZCQLD.js} +2 -2
  16. package/dist/{chunk-LW7MMEAQ.js → chunk-FT2M4R4F.js} +2 -2
  17. package/dist/{chunk-5BSLGBYI.js → chunk-JCQZ6LA7.js} +2 -8
  18. package/dist/{chunk-5BSLGBYI.js.map → chunk-JCQZ6LA7.js.map} +1 -1
  19. package/dist/{chunk-KHJS6VIA.js → chunk-LRQ6RBJC.js} +157 -112
  20. package/dist/chunk-LRQ6RBJC.js.map +1 -0
  21. package/dist/{chunk-WN6XJWOS.js → chunk-MNJXXD6C.js} +274 -743
  22. package/dist/chunk-MNJXXD6C.js.map +1 -0
  23. package/dist/{chunk-KK73ZB4E.js → chunk-PTR5PMPE.js} +153 -132
  24. package/dist/chunk-PTR5PMPE.js.map +1 -0
  25. package/dist/{chunk-B2WTCLCV.js → chunk-Q7APDV6H.js} +18 -8
  26. package/dist/chunk-Q7APDV6H.js.map +1 -0
  27. package/dist/{chunk-A4FUBC7B.js → chunk-QGVSOUJ2.js} +2 -4
  28. package/dist/{chunk-A4FUBC7B.js.map → chunk-QGVSOUJ2.js.map} +1 -1
  29. package/dist/{chunk-FGMFQSHX.js → chunk-S63MFSY6.js} +500 -551
  30. package/dist/chunk-S63MFSY6.js.map +1 -0
  31. package/dist/{chunk-AFGTSUAD.js → chunk-VSOKOFRF.js} +4 -4
  32. package/dist/chunk-WUXCWRL6.js +20 -0
  33. package/dist/chunk-WUXCWRL6.js.map +1 -0
  34. package/dist/{chunk-Y6TXWPJO.js → chunk-YVVGHRGI.js} +105 -31
  35. package/dist/chunk-YVVGHRGI.js.map +1 -0
  36. package/dist/{chunk-M5IWZRBT.js → chunk-ZMNXIJP4.js} +2187 -981
  37. package/dist/chunk-ZMNXIJP4.js.map +1 -0
  38. package/dist/components.d.ts +6 -6
  39. package/dist/components.js +14 -18
  40. package/dist/components.js.map +1 -1
  41. package/dist/{database-C3Szpi5J.d.ts → database-BXAfr2Y_.d.ts} +18 -0
  42. package/dist/hooks.d.ts +5 -5
  43. package/dist/hooks.js +8 -9
  44. package/dist/hooks.js.map +1 -1
  45. package/dist/index.d.ts +19 -27
  46. package/dist/index.js +21 -29
  47. package/dist/index.js.map +1 -1
  48. package/dist/{organisation-BtshODVF.d.ts → organisation-D6qRDtbF.d.ts} +1 -1
  49. package/dist/providers.d.ts +7 -21
  50. package/dist/providers.js +3 -10
  51. package/dist/rbac/index.d.ts +71 -221
  52. package/dist/rbac/index.js +15 -16
  53. package/dist/{types-CGX9Vyf5.d.ts → types-BDg1mAGG.d.ts} +36 -6
  54. package/dist/types.d.ts +3 -3
  55. package/dist/types.js +61 -18
  56. package/dist/types.js.map +1 -1
  57. package/dist/{unified-CM7T0aTK.d.ts → unified-DQ4VcT7H.d.ts} +1 -1
  58. package/dist/{usePublicRouteParams-B-CumWRc.d.ts → usePublicRouteParams-BlgwXweB.d.ts} +3 -3
  59. package/dist/utils.d.ts +2 -2
  60. package/dist/utils.js +52 -9
  61. package/dist/utils.js.map +1 -1
  62. package/docs/CONTENT_AUDIT_REPORT.md +253 -0
  63. package/docs/DOCUMENTATION_AUDIT.md +172 -0
  64. package/docs/README.md +142 -147
  65. package/docs/STYLE_GUIDE.md +37 -0
  66. package/docs/api/classes/ColumnFactory.md +17 -17
  67. package/docs/api/classes/ErrorBoundary.md +1 -1
  68. package/docs/api/classes/InvalidScopeError.md +4 -4
  69. package/docs/api/classes/MissingUserContextError.md +4 -4
  70. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  71. package/docs/api/classes/PermissionDeniedError.md +5 -5
  72. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  73. package/docs/api/classes/RBACAuditManager.md +8 -8
  74. package/docs/api/classes/RBACCache.md +35 -5
  75. package/docs/api/classes/RBACEngine.md +49 -20
  76. package/docs/api/classes/RBACError.md +4 -4
  77. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  78. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  79. package/docs/api/classes/StorageUtils.md +1 -1
  80. package/docs/api/enums/FileCategory.md +1 -1
  81. package/docs/api/interfaces/AggregateConfig.md +4 -4
  82. package/docs/api/interfaces/ButtonProps.md +1 -1
  83. package/docs/api/interfaces/CardProps.md +1 -1
  84. package/docs/api/interfaces/ColorPalette.md +1 -1
  85. package/docs/api/interfaces/ColorShade.md +1 -1
  86. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  87. package/docs/api/interfaces/DataRecord.md +11 -0
  88. package/docs/api/interfaces/DataTableAction.md +65 -29
  89. package/docs/api/interfaces/DataTableColumn.md +36 -23
  90. package/docs/api/interfaces/DataTableProps.md +80 -38
  91. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  92. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  93. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  94. package/docs/api/interfaces/EventLogoProps.md +1 -1
  95. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  96. package/docs/api/interfaces/FileMetadata.md +1 -1
  97. package/docs/api/interfaces/FileReference.md +1 -1
  98. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  99. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  100. package/docs/api/interfaces/FileUploadProps.md +1 -1
  101. package/docs/api/interfaces/FooterProps.md +1 -1
  102. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  103. package/docs/api/interfaces/InputProps.md +1 -1
  104. package/docs/api/interfaces/LabelProps.md +1 -1
  105. package/docs/api/interfaces/LoginFormProps.md +1 -1
  106. package/docs/api/interfaces/NavigationAccessRecord.md +11 -11
  107. package/docs/api/interfaces/NavigationContextType.md +9 -9
  108. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  109. package/docs/api/interfaces/NavigationItem.md +1 -1
  110. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  111. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  112. package/docs/api/interfaces/Organisation.md +1 -1
  113. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  114. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  115. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  116. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  117. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  118. package/docs/api/interfaces/PaceLoginPageProps.md +16 -3
  119. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  120. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  121. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  122. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  123. package/docs/api/interfaces/PaletteData.md +1 -1
  124. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  128. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  131. package/docs/api/interfaces/RBACConfig.md +1 -1
  132. package/docs/api/interfaces/RBACLogger.md +1 -1
  133. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  134. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  135. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  136. package/docs/api/interfaces/RouteConfig.md +2 -2
  137. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  138. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  139. package/docs/api/interfaces/StorageConfig.md +1 -1
  140. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  141. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  142. package/docs/api/interfaces/StorageListOptions.md +1 -1
  143. package/docs/api/interfaces/StorageListResult.md +1 -1
  144. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  145. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  146. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  147. package/docs/api/interfaces/StyleImport.md +1 -1
  148. package/docs/api/interfaces/SwitchProps.md +1 -1
  149. package/docs/api/interfaces/ToastActionElement.md +1 -1
  150. package/docs/api/interfaces/ToastProps.md +1 -1
  151. package/docs/api/interfaces/UnifiedAuthContextType.md +94 -521
  152. package/docs/api/interfaces/UnifiedAuthProviderProps.md +16 -16
  153. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  154. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  155. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  156. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  157. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  158. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  159. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  160. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  161. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  162. package/docs/api/interfaces/UserEventAccess.md +11 -11
  163. package/docs/api/interfaces/UserMenuProps.md +1 -1
  164. package/docs/api/interfaces/UserProfile.md +1 -1
  165. package/docs/api/modules.md +251 -269
  166. package/docs/api-reference/components.md +193 -0
  167. package/docs/api-reference/hooks.md +265 -0
  168. package/docs/api-reference/providers.md +6 -0
  169. package/docs/api-reference/types.md +6 -0
  170. package/docs/api-reference/utilities.md +207 -0
  171. package/docs/architecture/README.md +6 -0
  172. package/docs/{database-schema-requirements.md → architecture/database-schema-requirements.md} +6 -0
  173. package/docs/architecture/rbac-security-architecture.md +258 -0
  174. package/docs/architecture/services.md +9 -1
  175. package/docs/best-practices/README.md +6 -0
  176. package/docs/best-practices/accessibility.md +6 -0
  177. package/docs/{common-patterns.md → best-practices/common-patterns.md} +6 -0
  178. package/docs/best-practices/deployment.md +6 -0
  179. package/docs/best-practices/performance.md +475 -2
  180. package/docs/best-practices/security.md +6 -0
  181. package/docs/best-practices/testing.md +6 -0
  182. package/docs/core-concepts/authentication.md +6 -0
  183. package/docs/core-concepts/events.md +6 -0
  184. package/docs/core-concepts/organisations.md +6 -0
  185. package/docs/core-concepts/permissions.md +6 -0
  186. package/docs/core-concepts/rbac-system.md +8 -0
  187. package/docs/documentation-index.md +121 -182
  188. package/docs/{consuming-app-vite-config.md → getting-started/consuming-app-vite-config.md} +6 -0
  189. package/docs/getting-started/documentation-index.md +40 -0
  190. package/docs/getting-started/examples/README.md +878 -35
  191. package/docs/{faq.md → getting-started/faq.md} +7 -1
  192. package/docs/getting-started/installation-guide.md +6 -0
  193. package/docs/{quick-reference.md → getting-started/quick-reference.md} +6 -0
  194. package/docs/implementation-guides/app-layout.md +6 -0
  195. package/docs/implementation-guides/authentication.md +1021 -0
  196. package/docs/implementation-guides/component-styling.md +6 -0
  197. package/docs/implementation-guides/data-tables.md +1264 -2076
  198. package/docs/implementation-guides/dynamic-colors.md +6 -0
  199. package/docs/implementation-guides/event-theming-summary.md +6 -0
  200. package/docs/{file-reference-system.md → implementation-guides/file-reference-system.md} +6 -0
  201. package/docs/implementation-guides/file-upload-storage.md +6 -0
  202. package/docs/implementation-guides/forms.md +6 -0
  203. package/docs/implementation-guides/inactivity-tracking.md +6 -0
  204. package/docs/implementation-guides/navigation.md +6 -0
  205. package/docs/implementation-guides/organisation-security.md +6 -0
  206. package/docs/implementation-guides/permission-enforcement.md +6 -0
  207. package/docs/implementation-guides/public-pages-advanced.md +6 -0
  208. package/docs/implementation-guides/public-pages.md +6 -0
  209. package/docs/migration/MIGRATION_GUIDE.md +827 -351
  210. package/docs/migration/README.md +7 -1
  211. package/docs/migration/organisation-context-timing-fix.md +6 -0
  212. package/docs/migration/rbac-migration.md +44 -1
  213. package/docs/migration/service-architecture.md +6 -0
  214. package/docs/migration/v0.4.15-tailwind-scanning.md +6 -0
  215. package/docs/migration/v0.4.16-css-first-approach.md +6 -0
  216. package/docs/migration/v0.4.17-source-path-fix.md +6 -0
  217. package/docs/rbac/README-rbac-rls-integration.md +6 -0
  218. package/docs/rbac/README.md +6 -0
  219. package/docs/rbac/advanced-patterns.md +6 -0
  220. package/docs/rbac/api-reference.md +7 -1
  221. package/docs/rbac/breaking-changes-v3.md +222 -0
  222. package/docs/rbac/examples/rbac-rls-integration-example.md +6 -0
  223. package/docs/rbac/examples.md +6 -0
  224. package/docs/rbac/getting-started.md +6 -0
  225. package/docs/rbac/migration-guide.md +260 -0
  226. package/docs/rbac/quick-start.md +70 -13
  227. package/docs/rbac/rbac-rls-integration.md +6 -0
  228. package/docs/rbac/super-admin-guide.md +6 -0
  229. package/docs/rbac/troubleshooting.md +6 -0
  230. package/docs/security/README.md +6 -0
  231. package/docs/security/checklist.md +6 -0
  232. package/docs/styles/README.md +7 -1
  233. package/docs/{usage.md → styles/usage.md} +6 -0
  234. package/docs/testing/README.md +6 -0
  235. package/docs/{visual-testing.md → testing/visual-testing.md} +6 -0
  236. package/docs/troubleshooting/README.md +387 -5
  237. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +6 -0
  238. package/docs/troubleshooting/common-issues.md +6 -0
  239. package/docs/troubleshooting/database-view-compatibility.md +6 -0
  240. package/docs/troubleshooting/organisation-context-setup.md +6 -0
  241. package/docs/troubleshooting/react-hooks-issue-analysis.md +6 -0
  242. package/docs/troubleshooting/styling-issues.md +6 -0
  243. package/docs/troubleshooting/tailwind-content-scanning.md +6 -0
  244. package/package.json +1 -1
  245. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -1
  246. package/src/__tests__/helpers/test-providers.tsx +3 -53
  247. package/src/components/DataTable/DataTable.test.tsx +319 -0
  248. package/src/components/DataTable/DataTable.tsx +32 -11
  249. package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx.skip} +6 -4
  250. package/src/components/DataTable/__tests__/{DataTable.test.tsx → DataTable.test.tsx.skip} +6 -4
  251. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +31 -9
  252. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +601 -0
  253. package/src/components/DataTable/__tests__/keyboard.test.tsx +615 -0
  254. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +639 -0
  255. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx.skip +330 -0
  256. package/src/components/DataTable/components/AccessDeniedPage.tsx +2 -2
  257. package/src/components/DataTable/components/ActionButtons.tsx +88 -104
  258. package/src/components/DataTable/components/DataTableCore.tsx +309 -337
  259. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +4 -2
  260. package/src/components/DataTable/components/DataTableModals.tsx +22 -1
  261. package/src/components/DataTable/components/EditableRow.tsx +69 -84
  262. package/src/components/DataTable/components/EmptyState.tsx +5 -1
  263. package/src/components/DataTable/components/ImportModal.tsx +65 -36
  264. package/src/components/DataTable/components/PaginationControls.tsx +40 -100
  265. package/src/components/DataTable/components/UnifiedTableBody.tsx +125 -148
  266. package/src/components/DataTable/context/DataTableContext.tsx +1 -1
  267. package/src/components/DataTable/core/ColumnFactory.ts +5 -0
  268. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +12 -10
  269. package/src/components/DataTable/examples/HierarchicalExample.tsx +1 -1
  270. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +1 -0
  271. package/src/components/DataTable/examples/PerformanceExample.tsx +1 -0
  272. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +1 -5
  273. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +167 -0
  274. package/src/components/DataTable/hooks/index.ts +7 -0
  275. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +32 -15
  276. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +102 -0
  277. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +89 -0
  278. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +117 -0
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +71 -27
  280. package/src/components/DataTable/hooks/useDataTableState.ts +39 -11
  281. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +33 -0
  282. package/src/components/DataTable/hooks/useHierarchicalState.ts +15 -1
  283. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +447 -0
  284. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +94 -0
  285. package/src/components/DataTable/hooks/useTableColumns.ts +10 -7
  286. package/src/components/DataTable/hooks/useTableHandlers.ts +174 -0
  287. package/src/components/DataTable/index.ts +12 -3
  288. package/src/components/DataTable/types.ts +129 -9
  289. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +159 -22
  290. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +111 -0
  291. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +15 -29
  292. package/src/components/DataTable/utils/a11yUtils.ts +244 -0
  293. package/src/components/DataTable/utils/debugTools.ts +609 -0
  294. package/src/components/DataTable/utils/exportUtils.ts +114 -16
  295. package/src/components/DataTable/utils/flexibleImport.ts +202 -32
  296. package/src/components/DataTable/utils/hierarchicalUtils.ts +1 -1
  297. package/src/components/DataTable/utils/index.ts +2 -0
  298. package/src/components/DataTable/utils/paginationUtils.ts +350 -0
  299. package/src/components/DataTable/utils/rowUtils.ts +6 -5
  300. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -24
  301. package/src/components/NavigationMenu/NavigationMenu.tsx +19 -8
  302. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +1 -23
  303. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +56 -6
  304. package/src/components/PaceLoginPage/PaceLoginPage.tsx +137 -13
  305. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +1 -1
  306. package/src/components/Select/Select.tsx +1 -0
  307. package/src/components/examples/PermissionExample.tsx +173 -0
  308. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  309. package/src/examples/PublicEventPage.tsx +274 -0
  310. package/src/examples/PublicPageApp.tsx +308 -0
  311. package/src/examples/PublicPageUsageExample.tsx +216 -0
  312. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +12 -1
  313. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +129 -17
  314. package/src/hooks/__tests__/useRBAC.unit.test.ts +151 -846
  315. package/src/hooks/useOrganisationPermissions.test.ts +42 -18
  316. package/src/hooks/useOrganisationPermissions.ts +12 -6
  317. package/src/hooks/useOrganisationSecurity.test.ts +138 -85
  318. package/src/hooks/useOrganisationSecurity.ts +41 -10
  319. package/src/index.ts +0 -1
  320. package/src/providers/AuthProvider.simplified.tsx +880 -0
  321. package/src/providers/UnifiedAuthProvider.test.simple.tsx +8 -8
  322. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +29 -19
  323. package/src/providers/index.ts +0 -1
  324. package/src/providers/services/EventServiceProvider.tsx +19 -15
  325. package/src/providers/services/InactivityServiceProvider.tsx +19 -15
  326. package/src/providers/services/OrganisationServiceProvider.tsx +19 -15
  327. package/src/providers/services/UnifiedAuthProvider.tsx +156 -127
  328. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +1 -1
  329. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -3
  330. package/src/rbac/README.md +1 -1
  331. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +25 -27
  332. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +313 -0
  333. package/src/rbac/__tests__/engine.comprehensive.test.ts +114 -348
  334. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +28 -110
  335. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +33 -85
  336. package/src/rbac/__tests__/scenarios.user-role.test.tsx +2 -2
  337. package/src/rbac/adapters.tsx +26 -69
  338. package/src/rbac/api.test.ts +90 -27
  339. package/src/rbac/api.ts +61 -10
  340. package/src/rbac/audit.test.ts +33 -38
  341. package/src/rbac/audit.ts +21 -6
  342. package/src/rbac/cache.ts +33 -1
  343. package/src/rbac/components/NavigationGuard.tsx +11 -11
  344. package/src/rbac/components/NavigationProvider.test.tsx +11 -5
  345. package/src/rbac/components/NavigationProvider.tsx +37 -13
  346. package/src/rbac/components/PagePermissionGuard.tsx +111 -50
  347. package/src/rbac/components/PagePermissionProvider.tsx +5 -5
  348. package/src/rbac/components/PermissionEnforcer.tsx +11 -11
  349. package/src/rbac/components/RoleBasedRouter.tsx +5 -5
  350. package/src/rbac/components/SecureDataProvider.tsx +5 -5
  351. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +8 -8
  352. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +14 -14
  353. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +12 -12
  354. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +6 -6
  355. package/src/rbac/engine.test.simple.ts +19 -13
  356. package/src/rbac/engine.test.ts +1 -0
  357. package/src/rbac/engine.ts +330 -766
  358. package/src/rbac/errors.ts +156 -0
  359. package/src/rbac/hooks/usePermissions.ts +32 -10
  360. package/src/rbac/hooks/useRBAC.test.ts +126 -512
  361. package/src/rbac/hooks/useRBAC.ts +147 -193
  362. package/src/rbac/hooks/useResolvedScope.ts +12 -0
  363. package/src/rbac/index.ts +7 -4
  364. package/src/rbac/security.ts +109 -18
  365. package/src/rbac/types.ts +12 -1
  366. package/src/services/AuthService.ts +2 -15
  367. package/src/services/EventService.ts +43 -46
  368. package/src/services/OrganisationService.ts +51 -31
  369. package/src/services/__tests__/AuthService.test.ts +1 -1
  370. package/src/services/__tests__/EventService.test.ts +1 -1
  371. package/src/services/__tests__/OrganisationService.test.ts +1 -1
  372. package/src/services/base/BaseService.ts +8 -0
  373. package/src/styles/base.css +208 -0
  374. package/src/styles/semantic.css +24 -0
  375. package/src/types/database.generated.ts +7347 -0
  376. package/src/types/database.ts +20 -0
  377. package/src/utils/logger.ts +179 -0
  378. package/src/utils/organisationContext.ts +11 -4
  379. package/src/utils/storage/__tests__/helpers.unit.test.ts +6 -2
  380. package/dist/appNameResolver-UURKN7NF.js +0 -22
  381. package/dist/audit-6TOCAMKO.js.map +0 -1
  382. package/dist/chunk-B2WTCLCV.js.map +0 -1
  383. package/dist/chunk-FGMFQSHX.js.map +0 -1
  384. package/dist/chunk-K34IM5CT.js.map +0 -1
  385. package/dist/chunk-KHJS6VIA.js.map +0 -1
  386. package/dist/chunk-KK73ZB4E.js.map +0 -1
  387. package/dist/chunk-M5IWZRBT.js.map +0 -1
  388. package/dist/chunk-ULBI5JGB.js +0 -109
  389. package/dist/chunk-ULBI5JGB.js.map +0 -1
  390. package/dist/chunk-WN6XJWOS.js.map +0 -1
  391. package/dist/chunk-XLZ7U46Z.js.map +0 -1
  392. package/dist/chunk-Y6TXWPJO.js.map +0 -1
  393. package/docs/DOCUMENTATION_CHECKLIST.md +0 -281
  394. package/docs/TERMINOLOGY.md +0 -231
  395. package/docs/api/interfaces/RBACContextType.md +0 -468
  396. package/docs/api/interfaces/RBACProviderProps.md +0 -107
  397. package/docs/best-practices/performance-expansion.md +0 -473
  398. package/docs/breaking-changes.md +0 -179
  399. package/docs/consuming-app-example.md +0 -290
  400. package/docs/documentation-templates.md +0 -539
  401. package/docs/examples/navigation-menu-auth-fix.md +0 -344
  402. package/docs/getting-started/examples/basic-auth-app.md +0 -520
  403. package/docs/getting-started/examples/full-featured-app.md +0 -616
  404. package/docs/getting-started/quick-start.md +0 -376
  405. package/docs/implementation-guides/datatable-filtering.md +0 -313
  406. package/docs/implementation-guides/datatable-rbac-usage.md +0 -317
  407. package/docs/implementation-guides/hierarchical-datatable.md +0 -850
  408. package/docs/implementation-guides/large-datasets.md +0 -281
  409. package/docs/implementation-guides/performance.md +0 -403
  410. package/docs/migration/quick-migration-guide.md +0 -320
  411. package/docs/migration-guide.md +0 -193
  412. package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +0 -226
  413. package/docs/performance/README.md +0 -551
  414. package/docs/style-guide.md +0 -964
  415. package/docs/troubleshooting/authentication-issues.md +0 -334
  416. package/docs/troubleshooting/debugging.md +0 -1117
  417. package/docs/troubleshooting/migration.md +0 -918
  418. package/src/__tests__/hooks/usePermissions.test.ts +0 -261
  419. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +0 -574
  420. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -613
  421. package/src/hooks/services/__tests__/useServiceHooks.test.tsx +0 -137
  422. package/src/hooks/services/usePermissions.ts +0 -70
  423. package/src/hooks/services/useRBACService.ts +0 -30
  424. package/src/hooks/usePermissionCheck.ts +0 -150
  425. package/src/providers/__tests__/ServiceProviders.test.tsx +0 -477
  426. package/src/providers/services/RBACServiceProvider.tsx +0 -79
  427. package/src/rbac/__tests__/integration.authflow.test.tsx +0 -119
  428. package/src/rbac/__tests__/integration.navigation.test.tsx +0 -69
  429. package/src/rbac/__tests__/integration.securedata.test.tsx +0 -92
  430. package/src/rbac/__tests__/integration.smoke.test.tsx +0 -73
  431. package/src/rbac/providers/RBACProvider.tsx +0 -645
  432. package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +0 -688
  433. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +0 -1186
  434. package/src/rbac/providers/index.ts +0 -11
  435. package/src/services/RBACService.ts +0 -522
  436. package/src/services/__tests__/RBACService.test.ts +0 -492
  437. package/src/services/interfaces/IRBACService.ts +0 -62
  438. package/src/utils/appNameResolver.test 2.ts +0 -494
  439. /package/dist/{DataTable-4GAVPIEG.js.map → DataTable-ETGVF4Y5.js.map} +0 -0
  440. /package/dist/{UnifiedAuthProvider-3NKDOSOK.js.map → UnifiedAuthProvider-P5SOJAQ6.js.map} +0 -0
  441. /package/dist/{api-DDMUKIUD.js.map → api-KG4A2X7P.js.map} +0 -0
  442. /package/dist/{appNameResolver-UURKN7NF.js.map → audit-65VNHEV2.js.map} +0 -0
  443. /package/dist/{chunk-NTNILOBC.js.map → chunk-5BO3MI5Y.js.map} +0 -0
  444. /package/dist/{chunk-URUTVZ7N.js.map → chunk-FL4ZCQLD.js.map} +0 -0
  445. /package/dist/{chunk-LW7MMEAQ.js.map → chunk-FT2M4R4F.js.map} +0 -0
  446. /package/dist/{chunk-AFGTSUAD.js.map → chunk-VSOKOFRF.js.map} +0 -0
  447. /package/docs/{app.css.example → styles/app.css.example} +0 -0
@@ -0,0 +1,1021 @@
1
+ ---
2
+ lastUpdated: 2025-10-29T22:43:00+11:00
3
+ version: 0.5.76
4
+ reviewedBy: content-audit
5
+ ---
6
+
7
+ # Authentication Implementation Guide
8
+
9
+ > **📚 Complete Authentication Guide** | [← Back to Documentation](../README.md) | [Installation Guide](../getting-started/installation-guide.md)
10
+
11
+ This comprehensive guide covers implementing authentication with PACE Core's UnifiedAuthProvider, including setup, configuration, troubleshooting, and best practices.
12
+
13
+ > **📚 API Reference**: See [useUnifiedAuth Hook](../api-reference/hooks.md#useunifiedauth) for complete hook documentation.
14
+
15
+ ## Overview
16
+
17
+ PACE Core provides a comprehensive authentication system built on Supabase that includes:
18
+
19
+ - **🔐 Unified Authentication** - Single provider for auth, RBAC, and event management
20
+ - **⏰ Inactivity Management** - Automatic session timeout with warnings
21
+ - **🏢 Organisation Context** - Multi-tenant support with organisation switching
22
+ - **📱 Event Management** - Event-based access control
23
+ - **🔒 Session Persistence** - Secure session management with auto-refresh
24
+ - **🎯 Permission Integration** - Built-in RBAC integration
25
+ - **📊 Debug Support** - Comprehensive debugging and monitoring
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Project Setup
30
+
31
+ ```bash
32
+ # Install PACE Core and dependencies
33
+ npm install @jmruthers/pace-core @supabase/supabase-js react-router-dom
34
+
35
+ # Install Tailwind CSS v4 (required)
36
+ npm install -D @tailwindcss/vite tailwindcss@^4.0.0
37
+ ```
38
+
39
+ ### 2. Environment Configuration
40
+
41
+ Create `.env.local`:
42
+
43
+ ```bash
44
+ # Supabase Configuration
45
+ REACT_APP_SUPABASE_URL=https://your-project.supabase.co
46
+ REACT_APP_SUPABASE_ANON_KEY=your-anon-key-here
47
+
48
+ # ⚠️ CRITICAL: Use anon key, NOT service role key
49
+ # The anon key starts with: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
50
+ # The service role key has different permissions and can cause RPC timeouts
51
+ ```
52
+
53
+ ### 3. Supabase Client Setup
54
+
55
+ ```typescript
56
+ // src/lib/supabase.ts
57
+ import { createClient } from '@supabase/supabase-js'
58
+
59
+ const supabaseUrl = process.env.REACT_APP_SUPABASE_URL!
60
+ const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY!
61
+
62
+ if (!supabaseUrl || !supabaseAnonKey) {
63
+ throw new Error('Missing Supabase environment variables')
64
+ }
65
+
66
+ export const supabase = createClient(supabaseUrl, supabaseAnonKey)
67
+ ```
68
+
69
+ ### 4. App Setup with Authentication
70
+
71
+ **CRITICAL**: UnifiedAuthProvider now requires inactivity timeout configuration:
72
+
73
+ ```tsx
74
+ // src/main.tsx
75
+ import React from 'react'
76
+ import ReactDOM from 'react-dom/client'
77
+ import { BrowserRouter } from 'react-router-dom'
78
+ import {
79
+ UnifiedAuthProvider
80
+ } from '@jmruthers/pace-core'
81
+ import { supabase } from './lib/supabase'
82
+ import App from './App.tsx'
83
+
84
+ // CRITICAL: Import the CSS system - includes everything you need
85
+ import '@jmruthers/pace-core/src/styles/core.css'
86
+
87
+ ReactDOM.createRoot(document.getElementById('root')!).render(
88
+ <React.StrictMode>
89
+ <BrowserRouter>
90
+ <UnifiedAuthProvider
91
+ supabaseClient={supabase}
92
+ appName="my-app"
93
+ enableRBAC={true}
94
+ requireOrganisationContext={true}
95
+ idleTimeoutMs={30 * 60 * 1000} // 30 minutes - REQUIRED
96
+ warnBeforeMs={60 * 1000} // 60 seconds - REQUIRED
97
+ onIdleLogout={() => window.location.href = '/login'} // REQUIRED
98
+ >
99
+ <App />
100
+ </UnifiedAuthProvider>
101
+ </BrowserRouter>
102
+ </React.StrictMode>,
103
+ )
104
+ ```
105
+
106
+ ### 5. Basic Login Page
107
+
108
+ ```tsx
109
+ // src/pages/LoginPage.tsx
110
+ import { LoginForm } from '@jmruthers/pace-core';
111
+ import { useNavigate } from 'react-router-dom';
112
+
113
+ export function LoginPage() {
114
+ const navigate = useNavigate();
115
+
116
+ const handleLoginSuccess = () => {
117
+ navigate('/');
118
+ };
119
+
120
+ return (
121
+ <div className="min-h-screen flex items-center justify-center bg-sec-50">
122
+ <div className="max-w-md w-full space-y-8">
123
+ <div>
124
+ <h2 className="mt-6 text-center text-3xl font-extrabold text-sec-900">
125
+ Sign in to My App
126
+ </h2>
127
+ </div>
128
+ <LoginForm onLoginSuccess={handleLoginSuccess} />
129
+ </div>
130
+ </div>
131
+ );
132
+ }
133
+ ```
134
+
135
+ ### 6. Protected Routes
136
+
137
+ ```tsx
138
+ // src/components/ProtectedRoute.tsx
139
+ import { useUnifiedAuth, Navigate } from '@jmruthers/pace-core';
140
+
141
+ function ProtectedRoute({ children }: { children: React.ReactNode }) {
142
+ const { user, loading } = useUnifiedAuth();
143
+
144
+ if (loading) return <div>Loading...</div>;
145
+ if (!user) return <Navigate to="/login" />;
146
+
147
+ return <>{children}</>;
148
+ }
149
+
150
+ // Usage in App.tsx
151
+ function App() {
152
+ return (
153
+ <Routes>
154
+ <Route path="/login" element={<LoginPage />} />
155
+ <Route path="/" element={
156
+ <ProtectedRoute>
157
+ <DashboardPage />
158
+ </ProtectedRoute>
159
+ } />
160
+ </Routes>
161
+ );
162
+ }
163
+ ```
164
+
165
+ ## Configuration Options
166
+
167
+ ### UnifiedAuthProvider Props
168
+
169
+ ```typescript
170
+ interface UnifiedAuthProviderProps {
171
+ // Required props
172
+ supabaseClient: SupabaseClient;
173
+ appName: string;
174
+ idleTimeoutMs: number; // Session timeout in milliseconds
175
+ warnBeforeMs: number; // Warning time before timeout
176
+ onIdleLogout: () => void; // Callback when session times out
177
+
178
+ // Optional props
179
+ enableRBAC?: boolean; // Enable RBAC integration (default: true)
180
+ requireOrganisationContext?: boolean; // Require organisation selection (default: false)
181
+ debug?: boolean; // Enable debug logging (default: false)
182
+ children: React.ReactNode;
183
+ }
184
+ ```
185
+
186
+ ### Complete Configuration Example
187
+
188
+ ```tsx
189
+ <UnifiedAuthProvider
190
+ supabaseClient={supabase}
191
+ appName="meal-manager"
192
+ enableRBAC={true}
193
+ requireOrganisationContext={true}
194
+ debug={process.env.NODE_ENV === 'development'}
195
+ idleTimeoutMs={30 * 60 * 1000} // 30 minutes
196
+ warnBeforeMs={5 * 60 * 1000} // 5 minutes warning
197
+ onIdleLogout={() => {
198
+ // Custom logout logic
199
+ console.log('Session expired');
200
+ window.location.href = '/login';
201
+ }}
202
+ >
203
+ <YourApp />
204
+ </UnifiedAuthProvider>
205
+ ```
206
+
207
+ ## useUnifiedAuth Hook
208
+
209
+ ### Basic Usage
210
+
211
+ ```tsx
212
+ import { useUnifiedAuth } from '@jmruthers/pace-core';
213
+
214
+ function UserDashboard() {
215
+ const {
216
+ user, // Current user object
217
+ loading, // Loading state
218
+ error, // Error state
219
+ session, // Current session
220
+ signIn, // Sign in function
221
+ signOut, // Sign out function
222
+ signUp, // Sign up function
223
+ resetPassword, // Password reset function
224
+ selectedEvent, // Currently selected event
225
+ setSelectedEvent, // Set selected event
226
+ hasEventAccess, // Check event access
227
+ } = useUnifiedAuth();
228
+
229
+ if (loading) return <div>Loading...</div>;
230
+ if (error) return <div>Error: {error.message}</div>;
231
+ if (!user) return <div>Please log in</div>;
232
+
233
+ return (
234
+ <div>
235
+ <h1>Welcome, {user.email}</h1>
236
+ <button onClick={signOut}>Sign Out</button>
237
+ </div>
238
+ );
239
+ }
240
+ ```
241
+
242
+ ### Authentication Methods
243
+
244
+ #### Sign In
245
+
246
+ ```tsx
247
+ const { signIn } = useUnifiedAuth();
248
+
249
+ // Email/password login
250
+ const handleLogin = async (email: string, password: string) => {
251
+ try {
252
+ await signIn({ email, password });
253
+ // User is now logged in
254
+ } catch (error) {
255
+ console.error('Login failed:', error);
256
+ }
257
+ };
258
+
259
+ // OAuth login (if configured)
260
+ const handleGoogleLogin = async () => {
261
+ try {
262
+ await signIn({ provider: 'google' });
263
+ } catch (error) {
264
+ console.error('Google login failed:', error);
265
+ }
266
+ };
267
+ ```
268
+
269
+ #### Sign Up
270
+
271
+ ```tsx
272
+ const { signUp } = useUnifiedAuth();
273
+
274
+ const handleSignUp = async (email: string, password: string) => {
275
+ try {
276
+ await signUp({ email, password });
277
+ // User created, may need email confirmation
278
+ } catch (error) {
279
+ console.error('Sign up failed:', error);
280
+ }
281
+ };
282
+ ```
283
+
284
+ #### Password Reset
285
+
286
+ ```tsx
287
+ const { resetPassword } = useUnifiedAuth();
288
+
289
+ const handlePasswordReset = async (email: string) => {
290
+ try {
291
+ await resetPassword(email);
292
+ // Password reset email sent
293
+ } catch (error) {
294
+ console.error('Password reset failed:', error);
295
+ }
296
+ };
297
+ ```
298
+
299
+ #### Sign Out
300
+
301
+ ```tsx
302
+ const { signOut } = useUnifiedAuth();
303
+
304
+ const handleSignOut = async () => {
305
+ try {
306
+ await signOut();
307
+ // User is now logged out
308
+ } catch (error) {
309
+ console.error('Sign out failed:', error);
310
+ }
311
+ };
312
+ ```
313
+
314
+ ## Event Management Integration
315
+
316
+ ### Event Selection
317
+
318
+ ```tsx
319
+ function EventSelector() {
320
+ const { selectedEvent, setSelectedEvent, hasEventAccess } = useUnifiedAuth();
321
+
322
+ const handleEventChange = (eventId: string) => {
323
+ if (hasEventAccess(eventId)) {
324
+ setSelectedEvent(eventId);
325
+ }
326
+ };
327
+
328
+ return (
329
+ <select value={selectedEvent?.id || ''} onChange={(e) => handleEventChange(e.target.value)}>
330
+ <option value="">Select an event</option>
331
+ {/* Event options */}
332
+ </select>
333
+ );
334
+ }
335
+ ```
336
+
337
+ ### Event Access Control
338
+
339
+ ```tsx
340
+ function EventContent() {
341
+ const { selectedEvent, hasEventAccess } = useUnifiedAuth();
342
+
343
+ if (!selectedEvent) {
344
+ return <div>Please select an event</div>;
345
+ }
346
+
347
+ if (!hasEventAccess(selectedEvent.id)) {
348
+ return <div>You don't have access to this event</div>;
349
+ }
350
+
351
+ return <div>Event content for {selectedEvent.name}</div>;
352
+ }
353
+ ```
354
+
355
+ ## Organisation Context
356
+
357
+ ### Organisation Selection
358
+
359
+ ```tsx
360
+ function OrganisationSelector() {
361
+ const { user, selectedOrganisation, setSelectedOrganisation } = useUnifiedAuth();
362
+
363
+ const handleOrganisationChange = (orgId: string) => {
364
+ setSelectedOrganisation(orgId);
365
+ };
366
+
367
+ return (
368
+ <select
369
+ value={selectedOrganisation?.id || ''}
370
+ onChange={(e) => handleOrganisationChange(e.target.value)}
371
+ >
372
+ <option value="">Select organisation</option>
373
+ {user?.organisations?.map(org => (
374
+ <option key={org.id} value={org.id}>
375
+ {org.name}
376
+ </option>
377
+ ))}
378
+ </select>
379
+ );
380
+ }
381
+ ```
382
+
383
+ ## Session Management
384
+
385
+ ### Session Persistence
386
+
387
+ ```tsx
388
+ // Supabase client configuration for session persistence
389
+ const supabase = createClient(url, key, {
390
+ auth: {
391
+ persistSession: true,
392
+ storage: window.localStorage,
393
+ autoRefreshToken: true,
394
+ detectSessionInUrl: true
395
+ }
396
+ });
397
+ ```
398
+
399
+ ### Session Monitoring
400
+
401
+ ```tsx
402
+ import { useEffect } from 'react';
403
+ import { supabase } from './lib/supabase';
404
+
405
+ function SessionMonitor() {
406
+ useEffect(() => {
407
+ const {
408
+ data: { subscription },
409
+ } = supabase.auth.onAuthStateChange((event, session) => {
410
+ console.log('Auth event:', event, session?.user?.id);
411
+
412
+ if (event === 'SIGNED_IN') {
413
+ console.log('User signed in:', session?.user);
414
+ }
415
+ if (event === 'SIGNED_OUT') {
416
+ console.log('User signed out');
417
+ }
418
+ if (event === 'TOKEN_REFRESHED') {
419
+ console.log('Token refreshed');
420
+ }
421
+ });
422
+
423
+ return () => subscription.unsubscribe();
424
+ }, []);
425
+
426
+ return null;
427
+ }
428
+ ```
429
+
430
+ ## Inactivity Management
431
+
432
+ ### Configuration
433
+
434
+ ```tsx
435
+ <UnifiedAuthProvider
436
+ supabaseClient={supabase}
437
+ appName="my-app"
438
+ idleTimeoutMs={30 * 60 * 1000} // 30 minutes
439
+ warnBeforeMs={5 * 60 * 1000} // 5 minutes warning
440
+ onIdleLogout={() => {
441
+ // Custom logout logic
442
+ localStorage.clear();
443
+ window.location.href = '/login';
444
+ }}
445
+ >
446
+ <App />
447
+ </UnifiedAuthProvider>
448
+ ```
449
+
450
+ ### Custom Inactivity Handling
451
+
452
+ ```tsx
453
+ function InactivityHandler() {
454
+ const { user } = useUnifiedAuth();
455
+
456
+ useEffect(() => {
457
+ if (!user) return;
458
+
459
+ let inactivityTimer: NodeJS.Timeout;
460
+ let warningTimer: NodeJS.Timeout;
461
+
462
+ const resetTimers = () => {
463
+ clearTimeout(inactivityTimer);
464
+ clearTimeout(warningTimer);
465
+
466
+ // Set warning timer
467
+ warningTimer = setTimeout(() => {
468
+ alert('You will be logged out in 5 minutes due to inactivity');
469
+ }, 25 * 60 * 1000); // 25 minutes
470
+
471
+ // Set logout timer
472
+ inactivityTimer = setTimeout(() => {
473
+ window.location.href = '/login';
474
+ }, 30 * 60 * 1000); // 30 minutes
475
+ };
476
+
477
+ // Reset timers on user activity
478
+ const events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'];
479
+ events.forEach(event => {
480
+ document.addEventListener(event, resetTimers, true);
481
+ });
482
+
483
+ resetTimers();
484
+
485
+ return () => {
486
+ clearTimeout(inactivityTimer);
487
+ clearTimeout(warningTimer);
488
+ events.forEach(event => {
489
+ document.removeEventListener(event, resetTimers, true);
490
+ });
491
+ };
492
+ }, [user]);
493
+
494
+ return null;
495
+ }
496
+ ```
497
+
498
+ ## Navigation Integration
499
+
500
+ ### Permission-Based Navigation
501
+
502
+ ```tsx
503
+ import { NavigationMenu, NavigationItem } from '@jmruthers/pace-core';
504
+ import { useUnifiedAuth } from '@jmruthers/pace-core';
505
+
506
+ const navigationItems = [
507
+ {
508
+ label: 'Dashboard',
509
+ href: '/dashboard',
510
+ icon: 'Home',
511
+ permissions: ['read:dashboard']
512
+ },
513
+ {
514
+ label: 'Users',
515
+ href: '/users',
516
+ icon: 'Users',
517
+ permissions: ['read:users']
518
+ },
519
+ {
520
+ label: 'Events',
521
+ href: '/events',
522
+ icon: 'Calendar',
523
+ permissions: ['read:events']
524
+ },
525
+ {
526
+ label: 'Settings',
527
+ href: '/settings',
528
+ icon: 'Settings',
529
+ permissions: ['read:settings']
530
+ }
531
+ ];
532
+
533
+ function AppNavigation() {
534
+ const { user } = useUnifiedAuth();
535
+
536
+ return (
537
+ <NavigationMenu
538
+ items={navigationItems}
539
+ currentPath={pathname}
540
+ onNavigate={(href) => router.push(href)}
541
+ user={user}
542
+ />
543
+ );
544
+ }
545
+ ```
546
+
547
+ ### User Menu Integration
548
+
549
+ ```tsx
550
+ import {
551
+ NavigationMenu,
552
+ UserMenu,
553
+ Header
554
+ } from '@jmruthers/pace-core';
555
+
556
+ function AppHeader() {
557
+ const { user, signOut } = useUnifiedAuth();
558
+
559
+ const handleLogout = async () => {
560
+ await signOut();
561
+ window.location.href = '/login';
562
+ };
563
+
564
+ return (
565
+ <Header
566
+ title="My App"
567
+ user={user}
568
+ onLogout={handleLogout}
569
+ navigation={
570
+ <NavigationMenu
571
+ items={navigationItems}
572
+ currentPath={pathname}
573
+ onNavigate={(href) => router.push(href)}
574
+ />
575
+ }
576
+ />
577
+ );
578
+ }
579
+ ```
580
+
581
+ ## Common Patterns
582
+
583
+ ### Authentication State Management
584
+
585
+ ```tsx
586
+ function useAuthState() {
587
+ const { user, loading, error } = useUnifiedAuth();
588
+
589
+ return {
590
+ isAuthenticated: !!user,
591
+ isLoading: loading,
592
+ hasError: !!error,
593
+ user,
594
+ error
595
+ };
596
+ }
597
+ ```
598
+
599
+ ### Conditional Rendering
600
+
601
+ ```tsx
602
+ function ConditionalContent() {
603
+ const { user, loading } = useUnifiedAuth();
604
+
605
+ if (loading) {
606
+ return <div>Loading...</div>;
607
+ }
608
+
609
+ if (!user) {
610
+ return <div>Please log in to continue</div>;
611
+ }
612
+
613
+ return <div>Welcome, {user.email}!</div>;
614
+ }
615
+ ```
616
+
617
+ ### Form Integration
618
+
619
+ ```tsx
620
+ function LoginForm() {
621
+ const [email, setEmail] = useState('');
622
+ const [password, setPassword] = useState('');
623
+ const [loading, setLoading] = useState(false);
624
+ const [error, setError] = useState('');
625
+ const { signIn } = useUnifiedAuth();
626
+
627
+ const handleSubmit = async (e: React.FormEvent) => {
628
+ e.preventDefault();
629
+ setLoading(true);
630
+ setError('');
631
+
632
+ try {
633
+ await signIn({ email, password });
634
+ } catch (err) {
635
+ setError(err instanceof Error ? err.message : 'Login failed');
636
+ } finally {
637
+ setLoading(false);
638
+ }
639
+ };
640
+
641
+ return (
642
+ <form onSubmit={handleSubmit}>
643
+ <input
644
+ type="email"
645
+ value={email}
646
+ onChange={(e) => setEmail(e.target.value)}
647
+ placeholder="Email"
648
+ required
649
+ />
650
+ <input
651
+ type="password"
652
+ value={password}
653
+ onChange={(e) => setPassword(e.target.value)}
654
+ placeholder="Password"
655
+ required
656
+ />
657
+ {error && <div className="error">{error}</div>}
658
+ <button type="submit" disabled={loading}>
659
+ {loading ? 'Signing in...' : 'Sign in'}
660
+ </button>
661
+ </form>
662
+ );
663
+ }
664
+ ```
665
+
666
+ ## Troubleshooting
667
+
668
+ ### Most Common Issues
669
+
670
+ #### 1. Login Not Working
671
+
672
+ **Symptoms:**
673
+ - Login button does nothing
674
+ - "Invalid credentials" error
675
+ - Redirect not happening after login
676
+
677
+ **Immediate Fix:**
678
+ ```tsx
679
+ // ✅ Ensure proper provider hierarchy
680
+ import { UnifiedAuthProvider } from '@jmruthers/pace-core';
681
+ import { supabase } from './lib/supabase';
682
+
683
+ function App() {
684
+ return (
685
+ <UnifiedAuthProvider
686
+ supabaseClient={supabase}
687
+ appName="my-app"
688
+ idleTimeoutMs={30 * 60 * 1000}
689
+ warnBeforeMs={5 * 60 * 1000}
690
+ onIdleLogout={() => window.location.href = '/login'}
691
+ >
692
+ <YourApp />
693
+ </UnifiedAuthProvider>
694
+ );
695
+ }
696
+ ```
697
+
698
+ **Checklist:**
699
+ - [ ] Supabase URL and key are correct
700
+ - [ ] Provider hierarchy correct (Auth > Org > Event)
701
+ - [ ] User credentials are valid in Supabase
702
+ - [ ] Network connectivity working
703
+ - [ ] Browser not blocking cookies
704
+
705
+ #### 2. Session Not Persisting
706
+
707
+ **Symptoms:**
708
+ - User logged out on page refresh
709
+ - Session cleared on browser restart
710
+ - Need to login repeatedly
711
+
712
+ **Fix:**
713
+ ```tsx
714
+ // Check Supabase session configuration
715
+ const supabase = createClient(url, key, {
716
+ auth: {
717
+ persistSession: true,
718
+ storage: window.localStorage,
719
+ autoRefreshToken: true,
720
+ detectSessionInUrl: true
721
+ }
722
+ });
723
+
724
+ // Verify session exists
725
+ useEffect(() => {
726
+ supabase.auth.getSession().then(({ data: { session } }) => {
727
+ console.log('Current session:', session);
728
+ });
729
+ }, []);
730
+ ```
731
+
732
+ #### 3. User State Not Updating
733
+
734
+ **Symptoms:**
735
+ - Login succeeds but user state is null
736
+ - `useUnifiedAuth()` returns undefined
737
+ - Components don't react to auth changes
738
+
739
+ **Fix:**
740
+ ```tsx
741
+ // ✅ Ensure provider is set up correctly
742
+ function App() {
743
+ return (
744
+ <UnifiedAuthProvider supabaseClient={supabase} appName="my-app">
745
+ <AuthTest />
746
+ </UnifiedAuthProvider>
747
+ );
748
+ }
749
+
750
+ function AuthTest() {
751
+ const { user, loading, error } = useUnifiedAuth();
752
+
753
+ if (loading) return <div>Loading...</div>;
754
+ if (error) return <div>Error: {error.message}</div>;
755
+ if (!user) return <div>Not logged in</div>;
756
+
757
+ return <div>Welcome {user.email}</div>;
758
+ }
759
+ ```
760
+
761
+ ### Detailed Solutions
762
+
763
+ #### Wrong Supabase Configuration
764
+
765
+ **Problem:** Using service role key instead of anon key
766
+
767
+ ```tsx
768
+ // ❌ WRONG - Service role key
769
+ const supabase = createClient(url, SERVICE_ROLE_KEY);
770
+
771
+ // ✅ CORRECT - Anonymous key
772
+ const supabase = createClient(url, ANON_KEY);
773
+
774
+ // Check key format
775
+ console.log('Key starts with:', ANON_KEY.substring(0, 30));
776
+ // Should be: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
777
+ ```
778
+
779
+ #### Provider Hierarchy Issues
780
+
781
+ **Problem:** Providers not in correct order
782
+
783
+ ```tsx
784
+ // ❌ WRONG ORDER
785
+ <EventProvider>
786
+ <OrganisationProvider>
787
+ <UnifiedAuthProvider supabaseClient={supabase} appName="my-app">
788
+ <App />
789
+ </UnifiedAuthProvider>
790
+ </OrganisationProvider>
791
+ </EventProvider>
792
+
793
+ // ✅ CORRECT ORDER
794
+ <UnifiedAuthProvider supabaseClient={supabase} appName="my-app">
795
+ <OrganisationProvider>
796
+ <EventProvider>
797
+ <App />
798
+ </EventProvider>
799
+ </OrganisationProvider>
800
+ </UnifiedAuthProvider>
801
+ ```
802
+
803
+ #### Missing Inactivity Timeout Props
804
+
805
+ **Problem:** TypeScript error in v0.5.65+
806
+
807
+ ```tsx
808
+ // ❌ OLD API (broken in v0.5.65+)
809
+ <UnifiedAuthProvider supabaseClient={supabase} appName="my-app">
810
+ <App />
811
+ </UnifiedAuthProvider>
812
+
813
+ // ✅ NEW API (required)
814
+ <UnifiedAuthProvider
815
+ supabaseClient={supabase}
816
+ appName="my-app"
817
+ idleTimeoutMs={30 * 60 * 1000} // Required
818
+ warnBeforeMs={5 * 60 * 1000} // Required
819
+ onIdleLogout={() => navigate('/login')} // Required
820
+ >
821
+ <App />
822
+ </UnifiedAuthProvider>
823
+ ```
824
+
825
+ ### Debugging Techniques
826
+
827
+ #### Enable Debug Logging
828
+
829
+ ```tsx
830
+ <UnifiedAuthProvider
831
+ supabaseClient={supabase}
832
+ appName="my-app"
833
+ debug={true} // Enable debug mode
834
+ idleTimeoutMs={30 * 60 * 1000}
835
+ warnBeforeMs={5 * 60 * 1000}
836
+ onIdleLogout={() => window.location.href = '/login'}
837
+ >
838
+ <App />
839
+ </UnifiedAuthProvider>
840
+ ```
841
+
842
+ #### Check Auth State
843
+
844
+ ```tsx
845
+ function AuthDebugger() {
846
+ const { user, loading, error, session } = useUnifiedAuth();
847
+
848
+ useEffect(() => {
849
+ console.log('Auth state:', {
850
+ user: user?.id,
851
+ email: user?.email,
852
+ loading,
853
+ error: error?.message,
854
+ hasSession: !!session
855
+ });
856
+ }, [user, loading, error, session]);
857
+
858
+ return null;
859
+ }
860
+
861
+ // Add to your app
862
+ <AuthDebugger />
863
+ ```
864
+
865
+ ### Common Error Messages
866
+
867
+ #### "Missing supabaseClient prop"
868
+
869
+ **Problem:** `UnifiedAuthProvider` not receiving supabase client
870
+
871
+ **Fix:**
872
+ ```tsx
873
+ // ✅ Ensure you're passing the client
874
+ import { createClient } from '@supabase/supabase-js';
875
+ import { UnifiedAuthProvider } from '@jmruthers/pace-core';
876
+
877
+ const supabase = createClient(url, key);
878
+
879
+ <UnifiedAuthProvider supabaseClient={supabase} appName="my-app">
880
+ <App />
881
+ </UnifiedAuthProvider>
882
+ ```
883
+
884
+ #### "Invalid credentials"
885
+
886
+ **Problem:** Wrong email/password or user not found
887
+
888
+ **Solutions:**
889
+ 1. Check user exists in Supabase Auth
890
+ 2. Verify email/password are correct
891
+ 3. Check email confirmation required
892
+ 4. Verify user is not disabled
893
+
894
+ ```tsx
895
+ // Check user exists
896
+ const { data, error } = await supabase.auth.signInWithPassword({
897
+ email: 'user@example.com',
898
+ password: 'password'
899
+ });
900
+ console.log('Login result:', { data, error });
901
+ ```
902
+
903
+ #### "Missing timeout props" (v0.5.65+)
904
+
905
+ **Problem:** Required props not provided
906
+
907
+ **Fix:**
908
+ ```tsx
909
+ // Add all required props
910
+ <UnifiedAuthProvider
911
+ supabaseClient={supabase}
912
+ appName="my-app"
913
+ idleTimeoutMs={30 * 60 * 1000} // 30 minutes
914
+ warnBeforeMs={5 * 60 * 1000} // 5 minutes warning
915
+ onIdleLogout={() => window.location.href = '/login'}
916
+ >
917
+ <App />
918
+ </UnifiedAuthProvider>
919
+ ```
920
+
921
+ ## Best Practices
922
+
923
+ ### Security
924
+
925
+ 1. **Use Anonymous Key**: Never use service role key in client-side code
926
+ 2. **Enable RLS**: Use Row Level Security in Supabase
927
+ 3. **Validate Input**: Always validate user input
928
+ 4. **Secure Storage**: Use secure storage for sensitive data
929
+ 5. **HTTPS Only**: Always use HTTPS in production
930
+
931
+ ### Performance
932
+
933
+ 1. **Lazy Loading**: Load authentication components lazily
934
+ 2. **Memoization**: Use React.memo for expensive components
935
+ 3. **Debouncing**: Debounce user input in forms
936
+ 4. **Session Caching**: Cache session data appropriately
937
+ 5. **Error Boundaries**: Use error boundaries for auth components
938
+
939
+ ### User Experience
940
+
941
+ 1. **Loading States**: Always show loading states
942
+ 2. **Error Messages**: Provide clear error messages
943
+ 3. **Redirects**: Handle redirects gracefully
944
+ 4. **Session Warnings**: Warn users before session timeout
945
+ 5. **Accessibility**: Ensure auth components are accessible
946
+
947
+ ### Code Organization
948
+
949
+ 1. **Separation of Concerns**: Separate auth logic from UI
950
+ 2. **Custom Hooks**: Create custom hooks for auth logic
951
+ 3. **Type Safety**: Use TypeScript for better type safety
952
+ 4. **Error Handling**: Implement comprehensive error handling
953
+ 5. **Testing**: Write tests for auth components
954
+
955
+ ## Migration Guide
956
+
957
+ ### From v0.5.64 to v0.5.65+
958
+
959
+ **Breaking Changes:**
960
+ - Inactivity timeout props are now required
961
+ - Provider hierarchy has changed
962
+ - Some hook interfaces have been updated
963
+
964
+ **Migration Steps:**
965
+
966
+ 1. **Update Provider Configuration:**
967
+ ```tsx
968
+ // Before
969
+ <UnifiedAuthProvider supabaseClient={supabase} appName="my-app">
970
+ <App />
971
+ </UnifiedAuthProvider>
972
+
973
+ // After
974
+ <UnifiedAuthProvider
975
+ supabaseClient={supabase}
976
+ appName="my-app"
977
+ idleTimeoutMs={30 * 60 * 1000}
978
+ warnBeforeMs={5 * 60 * 1000}
979
+ onIdleLogout={() => window.location.href = '/login'}
980
+ >
981
+ <App />
982
+ </UnifiedAuthProvider>
983
+ ```
984
+
985
+ 2. **Update Hook Usage:**
986
+ ```tsx
987
+ // Before
988
+ const { user, signIn, signOut } = useUnifiedAuth();
989
+
990
+ // After (same interface, but with additional features)
991
+ const { user, signIn, signOut, selectedEvent, setSelectedEvent } = useUnifiedAuth();
992
+ ```
993
+
994
+ 3. **Test Authentication Flow:**
995
+ - Verify login/logout works
996
+ - Check session persistence
997
+ - Test inactivity timeout
998
+ - Verify error handling
999
+
1000
+ ## Examples
1001
+
1002
+ ### Complete Authentication App
1003
+
1004
+ See the [Authentication Implementation Guide](./authentication.md) for a complete working example with step-by-step instructions.
1005
+
1006
+ ### Advanced Patterns
1007
+
1008
+ See the [Common Patterns Guide](./best-practices/common-patterns.md) for advanced authentication patterns.
1009
+
1010
+ ## Related Documentation
1011
+
1012
+ - [RBAC Integration](./rbac/README.md) - Role-based access control
1013
+ - [Event Management](./events/README.md) - Event-based access control
1014
+ - [Navigation Integration](./navigation.md) - Permission-based navigation
1015
+ - [Troubleshooting Guide](./troubleshooting/README.md) - Common issues and solutions
1016
+
1017
+ ## Conclusion
1018
+
1019
+ PACE Core's authentication system provides a comprehensive solution for user authentication, session management, and access control. With built-in RBAC integration, event management, and inactivity handling, it provides everything needed for secure, user-friendly applications.
1020
+
1021
+ The system is designed to be both powerful and easy to use, with extensive debugging support and clear error messages to help developers build robust authentication flows.