@jmruthers/pace-core 0.4.1 → 0.5.3

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 (660) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/README.md +231 -229
  3. package/dist/{DataTable-2LB6HI6V.js → DataTable-ZQDRE46Q.js} +15 -17
  4. package/dist/{DataTable-BDBqkU-i.d.ts → DataTable-ltTFXHS3.d.ts} +25 -51
  5. package/dist/{Table-CIm9IWqk.d.ts → PublicLoadingSpinner-Bq_-BeK-.d.ts} +635 -122
  6. package/dist/{UnifiedAuthProvider-V7y63NjT.d.ts → RBACProvider-BO4ilsQB.d.ts} +11 -36
  7. package/dist/UnifiedAuthProvider-DGQsy-vY.d.ts +103 -0
  8. package/dist/{api-AIJ3IJX3.js → api-H5A3H4IR.js} +6 -4
  9. package/dist/{appConfig-fB1pP_v3.d.ts → appConfig-BVGyuvI7.d.ts} +1 -1
  10. package/dist/appNameResolver-7GHF5ED2.js +22 -0
  11. package/dist/{audit-PD5L5ZSC.js → audit-BUW3LMJB.js} +3 -3
  12. package/dist/chunk-5H3C2SWM.js +3293 -0
  13. package/dist/chunk-5H3C2SWM.js.map +1 -0
  14. package/dist/chunk-5SIXIV7R.js +1925 -0
  15. package/dist/chunk-5SIXIV7R.js.map +1 -0
  16. package/dist/{chunk-YNU5QJ4S.js → chunk-7BNPOCLL.js} +22 -5
  17. package/dist/chunk-7BNPOCLL.js.map +1 -0
  18. package/dist/{chunk-4ZTIEYU2.js → chunk-CDQ3PX7L.js} +1 -1
  19. package/dist/chunk-CDQ3PX7L.js.map +1 -0
  20. package/dist/chunk-GNTALZV3.js +17 -0
  21. package/dist/chunk-GNTALZV3.js.map +1 -0
  22. package/dist/chunk-GWSBHC4J.js +1349 -0
  23. package/dist/chunk-GWSBHC4J.js.map +1 -0
  24. package/dist/{chunk-JUUNUW3O.js → chunk-HD7PYDUV.js} +14 -5
  25. package/dist/chunk-HD7PYDUV.js.map +1 -0
  26. package/dist/{chunk-H4PZ4B3Y.js → chunk-HXX35Q2M.js} +113 -27
  27. package/dist/chunk-HXX35Q2M.js.map +1 -0
  28. package/dist/chunk-K6B7BLSE.js +388 -0
  29. package/dist/chunk-K6B7BLSE.js.map +1 -0
  30. package/dist/chunk-M4RW7PIP.js +5441 -0
  31. package/dist/chunk-M4RW7PIP.js.map +1 -0
  32. package/dist/chunk-MZBUOP4P.js +119 -0
  33. package/dist/chunk-MZBUOP4P.js.map +1 -0
  34. package/dist/chunk-N2EUGZRW.js +98 -0
  35. package/dist/chunk-N2EUGZRW.js.map +1 -0
  36. package/dist/chunk-NQ4TOOO6.js +20 -0
  37. package/dist/chunk-NQ4TOOO6.js.map +1 -0
  38. package/dist/{chunk-DC5AMYBS.js → chunk-PLDDJCW6.js} +15 -5
  39. package/dist/chunk-PLDDJCW6.js.map +1 -0
  40. package/dist/{chunk-IOX76PSM.js → chunk-PVMYVQSM.js} +270 -28
  41. package/dist/chunk-PVMYVQSM.js.map +1 -0
  42. package/dist/{chunk-4MCJAK7J.js → chunk-QKHFMQ5R.js} +2155 -4853
  43. package/dist/chunk-QKHFMQ5R.js.map +1 -0
  44. package/dist/chunk-QVYBYGT2.js +428 -0
  45. package/dist/chunk-QVYBYGT2.js.map +1 -0
  46. package/dist/{chunk-WHLSWC6W.js → chunk-SS3E6QLB.js} +16 -61
  47. package/dist/chunk-SS3E6QLB.js.map +1 -0
  48. package/dist/chunk-WJARTBCT.js +128 -0
  49. package/dist/chunk-WJARTBCT.js.map +1 -0
  50. package/dist/chunk-YDJW5XTN.js +84 -0
  51. package/dist/chunk-YDJW5XTN.js.map +1 -0
  52. package/dist/components.d.ts +907 -10
  53. package/dist/components.js +3237 -204
  54. package/dist/components.js.map +1 -1
  55. package/dist/{database-CAMsquLm.d.ts → database-C3Szpi5J.d.ts} +28 -11
  56. package/dist/hooks.d.ts +7 -6
  57. package/dist/hooks.js +33 -11
  58. package/dist/hooks.js.map +1 -1
  59. package/dist/index.d.ts +247 -111
  60. package/dist/index.js +330 -185
  61. package/dist/index.js.map +1 -1
  62. package/dist/{organisation-DLNNQhPB.d.ts → organisation-CO3Sh3_D.d.ts} +1 -1
  63. package/dist/providers.d.ts +5 -4
  64. package/dist/providers.js +14 -5
  65. package/dist/rbac/index.d.ts +964 -839
  66. package/dist/rbac/index.js +58 -1970
  67. package/dist/rbac/index.js.map +1 -1
  68. package/dist/styles/core.css +364 -0
  69. package/dist/styles/fonts/georama-italic.woff2 +0 -0
  70. package/dist/styles/fonts/georama.woff2 +0 -0
  71. package/dist/styles/fonts/open-sans-italic.woff2 +0 -0
  72. package/dist/styles/fonts/open-sans.woff2 +0 -0
  73. package/dist/styles/fonts/reddit-mono.woff2 +0 -0
  74. package/dist/styles/index.d.ts +36 -0
  75. package/dist/styles/index.js +24 -0
  76. package/dist/styles/index.js.map +1 -0
  77. package/dist/theming/runtime.d.ts +73 -0
  78. package/dist/theming/runtime.js +16 -0
  79. package/dist/theming/runtime.js.map +1 -0
  80. package/dist/{types-Bavn44NW.d.ts → types-BRDU7N6w.d.ts} +79 -33
  81. package/dist/types.d.ts +5 -5
  82. package/dist/types.js +7 -2
  83. package/dist/types.js.map +1 -1
  84. package/dist/{unified-BtRpPbmp.d.ts → unified-CMPjE_fv.d.ts} +0 -1
  85. package/dist/usePublicRouteParams-B2OcAsur.d.ts +477 -0
  86. package/dist/utils.d.ts +83 -60
  87. package/dist/utils.js +293 -55651
  88. package/dist/utils.js.map +1 -1
  89. package/dist/validation.d.ts +1 -1
  90. package/dist/validation.js +1 -1
  91. package/docs/INDEX.md +192 -0
  92. package/docs/README.md +46 -32
  93. package/docs/api/README.md +231 -229
  94. package/docs/api/classes/ErrorBoundary.md +1 -1
  95. package/docs/api/classes/InvalidScopeError.md +73 -0
  96. package/docs/api/classes/MissingUserContextError.md +66 -0
  97. package/docs/api/classes/OrganisationContextRequiredError.md +66 -0
  98. package/docs/api/classes/PermissionDeniedError.md +73 -0
  99. package/docs/api/classes/PublicErrorBoundary.md +132 -0
  100. package/docs/api/classes/RBACAuditManager.md +270 -0
  101. package/docs/api/classes/RBACCache.md +284 -0
  102. package/docs/api/classes/RBACEngine.md +141 -0
  103. package/docs/api/classes/RBACError.md +76 -0
  104. package/docs/api/classes/RBACNotInitializedError.md +66 -0
  105. package/docs/api/classes/SecureSupabaseClient.md +135 -0
  106. package/docs/api/interfaces/AggregateConfig.md +4 -4
  107. package/docs/api/interfaces/ButtonProps.md +2 -2
  108. package/docs/api/interfaces/CardProps.md +2 -2
  109. package/docs/api/interfaces/ColorPalette.md +1 -1
  110. package/docs/api/interfaces/ColorShade.md +1 -1
  111. package/docs/api/interfaces/DataAccessRecord.md +96 -0
  112. package/docs/api/interfaces/DataTableAction.md +98 -7
  113. package/docs/api/interfaces/DataTableColumn.md +131 -12
  114. package/docs/api/interfaces/DataTableProps.md +77 -274
  115. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  116. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  117. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +235 -0
  118. package/docs/api/interfaces/EventContextType.md +7 -7
  119. package/docs/api/interfaces/EventLogoProps.md +152 -0
  120. package/docs/api/interfaces/EventProviderProps.md +2 -2
  121. package/docs/api/interfaces/FileSizeLimits.md +7 -0
  122. package/docs/api/interfaces/FileUploadProps.md +154 -0
  123. package/docs/api/interfaces/FooterProps.md +1 -1
  124. package/docs/api/interfaces/InactivityWarningModalProps.md +115 -0
  125. package/docs/api/interfaces/InputProps.md +2 -2
  126. package/docs/api/interfaces/LabelProps.md +1 -1
  127. package/docs/api/interfaces/LoginFormProps.md +1 -1
  128. package/docs/api/interfaces/NavigationAccessRecord.md +107 -0
  129. package/docs/api/interfaces/NavigationContextType.md +164 -0
  130. package/docs/api/interfaces/NavigationGuardProps.md +139 -0
  131. package/docs/api/interfaces/NavigationItem.md +1 -1
  132. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  133. package/docs/api/interfaces/NavigationProviderProps.md +117 -0
  134. package/docs/api/interfaces/Organisation.md +1 -1
  135. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  136. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  137. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  138. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  139. package/docs/api/interfaces/PaceAppLayoutProps.md +26 -26
  140. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  141. package/docs/api/interfaces/PageAccessRecord.md +85 -0
  142. package/docs/api/interfaces/PagePermissionContextType.md +140 -0
  143. package/docs/api/interfaces/PagePermissionGuardProps.md +153 -0
  144. package/docs/api/interfaces/PagePermissionProviderProps.md +119 -0
  145. package/docs/api/interfaces/PaletteData.md +1 -1
  146. package/docs/api/interfaces/PermissionEnforcerProps.md +153 -0
  147. package/docs/api/interfaces/PublicErrorBoundaryProps.md +94 -0
  148. package/docs/api/interfaces/PublicErrorBoundaryState.md +68 -0
  149. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +86 -0
  150. package/docs/api/interfaces/PublicPageFooterProps.md +112 -0
  151. package/docs/api/interfaces/PublicPageHeaderProps.md +138 -0
  152. package/docs/api/interfaces/PublicPageLayoutProps.md +138 -0
  153. package/docs/api/interfaces/RBACConfig.md +99 -0
  154. package/docs/api/interfaces/RBACContextType.md +474 -0
  155. package/docs/api/interfaces/RBACLogger.md +112 -0
  156. package/docs/api/interfaces/RBACProviderProps.md +107 -0
  157. package/docs/api/interfaces/RoleBasedRouterContextType.md +151 -0
  158. package/docs/api/interfaces/RoleBasedRouterProps.md +156 -0
  159. package/docs/api/interfaces/RouteAccessRecord.md +107 -0
  160. package/docs/api/interfaces/RouteConfig.md +121 -0
  161. package/docs/api/interfaces/SecureDataContextType.md +168 -0
  162. package/docs/api/interfaces/SecureDataProviderProps.md +132 -0
  163. package/docs/api/interfaces/StorageConfig.md +41 -0
  164. package/docs/api/interfaces/StorageFileInfo.md +74 -0
  165. package/docs/api/interfaces/StorageFileMetadata.md +140 -0
  166. package/docs/api/interfaces/StorageListOptions.md +86 -0
  167. package/docs/api/interfaces/StorageListResult.md +41 -0
  168. package/docs/api/interfaces/StorageUploadOptions.md +88 -0
  169. package/docs/api/interfaces/StorageUploadResult.md +63 -0
  170. package/docs/api/interfaces/StorageUrlOptions.md +47 -0
  171. package/docs/api/interfaces/StyleImport.md +2 -2
  172. package/docs/api/interfaces/ToastActionElement.md +1 -1
  173. package/docs/api/interfaces/ToastProps.md +1 -1
  174. package/docs/api/interfaces/UnifiedAuthContextType.md +465 -64
  175. package/docs/api/interfaces/UnifiedAuthProviderProps.md +95 -9
  176. package/docs/api/interfaces/UseInactivityTrackerOptions.md +136 -0
  177. package/docs/api/interfaces/UseInactivityTrackerReturn.md +123 -0
  178. package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
  179. package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
  180. package/docs/api/interfaces/UsePublicEventOptions.md +34 -0
  181. package/docs/api/interfaces/UsePublicEventReturn.md +68 -0
  182. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +94 -0
  183. package/docs/api/interfaces/UserEventAccess.md +14 -14
  184. package/docs/api/interfaces/UserMenuProps.md +6 -6
  185. package/docs/api/interfaces/UserProfile.md +1 -1
  186. package/docs/api/modules.md +4233 -1134
  187. package/docs/api-reference/components.md +761 -43
  188. package/docs/api-reference/hooks.md +126 -0
  189. package/docs/api-reference/providers.md +141 -65
  190. package/docs/api-reference/types.md +66 -36
  191. package/docs/api-reference/utilities.md +1 -1
  192. package/docs/architecture/README.md +1 -2
  193. package/docs/best-practices/README.md +400 -0
  194. package/docs/consuming-app-example.md +42 -96
  195. package/docs/consuming-app-vite-config.md +233 -0
  196. package/docs/core-concepts/events.md +3 -3
  197. package/docs/core-concepts/organisations.md +0 -1
  198. package/docs/core-concepts/rbac-system.md +23 -10
  199. package/docs/documentation-style-checklist.md +8 -2
  200. package/docs/examples/navigation-menu-auth-fix.md +344 -0
  201. package/docs/getting-started/examples/README.md +15 -1
  202. package/docs/getting-started/examples/basic-auth-app.md +444 -119
  203. package/docs/getting-started/examples/full-featured-app.md +6 -6
  204. package/docs/getting-started/installation.md +231 -52
  205. package/docs/getting-started/quick-start.md +121 -24
  206. package/docs/implementation-guides/app-layout.md +133 -108
  207. package/docs/implementation-guides/data-tables.md +1011 -29
  208. package/docs/implementation-guides/forms.md +3 -3
  209. package/docs/implementation-guides/hierarchical-datatable.md +850 -0
  210. package/docs/implementation-guides/large-datasets.md +2 -2
  211. package/docs/implementation-guides/navigation.md +1 -1
  212. package/docs/implementation-guides/permission-enforcement.md +4 -4
  213. package/docs/implementation-guides/public-pages.md +752 -0
  214. package/docs/migration/README.md +18 -8
  215. package/docs/migration/quick-migration-guide.md +320 -0
  216. package/docs/migration/rbac-migration.md +50 -0
  217. package/docs/migration/v0.4.15-tailwind-scanning.md +272 -0
  218. package/docs/migration/v0.4.16-css-first-approach.md +306 -0
  219. package/docs/migration/v0.4.17-source-path-fix.md +229 -0
  220. package/docs/migration-guide.md +77 -105
  221. package/docs/performance/README.md +1 -4
  222. package/docs/print-components/README.md +258 -0
  223. package/docs/print-components/api-reference.md +636 -0
  224. package/docs/print-components/examples/README.md +204 -0
  225. package/docs/print-components/examples/basic-report.tsx +92 -0
  226. package/docs/print-components/examples/card-catalog.tsx +149 -0
  227. package/docs/print-components/examples/cover-page-report.tsx +163 -0
  228. package/docs/print-components/quick-start.md +363 -0
  229. package/docs/quick-reference.md +53 -36
  230. package/docs/rbac/README.md +136 -69
  231. package/docs/rbac/api-reference.md +39 -8
  232. package/docs/rbac/examples.md +237 -66
  233. package/docs/rbac/getting-started.md +131 -16
  234. package/docs/rbac/quick-start.md +499 -323
  235. package/docs/rbac/troubleshooting.md +240 -262
  236. package/docs/security/README.md +50 -1
  237. package/docs/styles/README.md +226 -111
  238. package/docs/testing/README.md +6 -10
  239. package/docs/troubleshooting/README.md +497 -0
  240. package/docs/troubleshooting/common-issues.md +604 -14
  241. package/docs/troubleshooting/styling-issues.md +219 -0
  242. package/docs/troubleshooting/tailwind-content-scanning.md +213 -0
  243. package/docs/usage.md +54 -91
  244. package/docs/visual-testing.md +0 -7
  245. package/package.json +47 -25
  246. package/src/__mocks__/lucide-react.ts +181 -0
  247. package/src/__tests__/REBUILD_PLAN.md +223 -0
  248. package/src/__tests__/TESTING_GUIDELINES.md +341 -0
  249. package/src/__tests__/fixtures/mocks.ts +93 -0
  250. package/src/__tests__/helpers/component-test-utils.tsx +145 -0
  251. package/src/__tests__/helpers/test-utils.tsx +117 -0
  252. package/src/__tests__/integration/UserProfile.test.tsx +128 -0
  253. package/src/__tests__/setup.ts +71 -0
  254. package/src/__tests__/templates/accessibility.test.template.tsx +279 -0
  255. package/src/__tests__/templates/component.test.template.tsx +144 -0
  256. package/src/__tests__/templates/hook.test.template.ts +173 -0
  257. package/src/__tests__/templates/integration.test.template.tsx +199 -0
  258. package/src/__tests__/types/test.types.ts +106 -0
  259. package/src/components/Alert/Alert.test.tsx +496 -0
  260. package/src/components/Alert/Alert.tsx +134 -0
  261. package/src/components/Alert/index.ts +2 -0
  262. package/src/components/Avatar/Avatar.test.tsx +484 -0
  263. package/src/components/Avatar/Avatar.tsx +84 -0
  264. package/src/components/Avatar/index.ts +2 -0
  265. package/src/components/Button/Button.test.tsx +662 -0
  266. package/src/components/Button/Button.tsx +270 -0
  267. package/src/components/Button/index.ts +2 -0
  268. package/src/components/Card/Card.test.tsx +593 -0
  269. package/src/components/Card/Card.tsx +271 -0
  270. package/src/components/Card/index.ts +1 -0
  271. package/src/components/Checkbox/Checkbox.test.tsx +461 -0
  272. package/src/components/Checkbox/Checkbox.tsx +75 -0
  273. package/src/components/Checkbox/__mocks__/Checkbox.tsx +2 -0
  274. package/src/components/Checkbox/index.ts +2 -0
  275. package/src/components/DataTable/DataTable.tsx +446 -0
  276. package/src/components/DataTable/__tests__/README.md +145 -0
  277. package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +66 -0
  278. package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +103 -0
  279. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +381 -0
  280. package/src/components/DataTable/__tests__/test-utils.ts +94 -0
  281. package/src/components/DataTable/components/AccessDeniedPage.tsx +168 -0
  282. package/src/components/DataTable/components/ActionButtons.tsx +194 -0
  283. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +160 -0
  284. package/src/components/DataTable/components/ColumnFilter.tsx +114 -0
  285. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +100 -0
  286. package/src/components/DataTable/components/DataTableBody.tsx +461 -0
  287. package/src/components/DataTable/components/DataTableCore.tsx +1027 -0
  288. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +214 -0
  289. package/src/components/DataTable/components/DataTableModals.tsx +87 -0
  290. package/src/components/DataTable/components/DataTableToolbar.tsx +262 -0
  291. package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
  292. package/src/components/DataTable/components/EditableRow.tsx +159 -0
  293. package/src/components/DataTable/components/EmptyState.tsx +64 -0
  294. package/src/components/DataTable/components/ExpandButton.tsx +113 -0
  295. package/src/components/DataTable/components/FilterRow.tsx +100 -0
  296. package/src/components/DataTable/components/GroupHeader.tsx +42 -0
  297. package/src/components/DataTable/components/GroupingDropdown.tsx +96 -0
  298. package/src/components/DataTable/components/ImportModal.tsx +345 -0
  299. package/src/components/DataTable/components/LoadingState.tsx +12 -0
  300. package/src/components/DataTable/components/PaginationControls.tsx +332 -0
  301. package/src/components/DataTable/components/UnifiedTableBody.tsx +742 -0
  302. package/src/components/DataTable/components/ViewRowModal.tsx +68 -0
  303. package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
  304. package/src/components/DataTable/components/index.ts +16 -0
  305. package/src/components/DataTable/context/DataTableContext.tsx +97 -0
  306. package/src/components/DataTable/core/ActionManager.ts +235 -0
  307. package/src/components/DataTable/core/ColumnFactory.ts +268 -0
  308. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  309. package/src/components/DataTable/core/DataManager.ts +188 -0
  310. package/src/components/DataTable/core/DataTableContext.tsx +181 -0
  311. package/src/components/DataTable/core/LocalDataAdapter.ts +264 -0
  312. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  313. package/src/components/DataTable/core/StateManager.ts +311 -0
  314. package/src/components/DataTable/core/index.ts +8 -0
  315. package/src/components/DataTable/core/interfaces.ts +338 -0
  316. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +419 -0
  317. package/src/components/DataTable/examples/HierarchicalExample.tsx +475 -0
  318. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +176 -0
  319. package/src/components/DataTable/examples/PerformanceExample.tsx +505 -0
  320. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +95 -0
  321. package/src/components/DataTable/hooks/useColumnReordering.ts +110 -0
  322. package/src/components/DataTable/hooks/useDataTableState.ts +325 -0
  323. package/src/components/DataTable/hooks/useHierarchicalState.ts +174 -0
  324. package/src/components/DataTable/index.ts +68 -0
  325. package/src/components/DataTable/styles.ts +171 -0
  326. package/src/components/DataTable/types.ts +511 -0
  327. package/src/components/DataTable/utils/debugTools.ts +583 -0
  328. package/src/components/DataTable/utils/errorHandling.ts +494 -0
  329. package/src/components/DataTable/utils/exportUtils.ts +126 -0
  330. package/src/components/DataTable/utils/flexibleImport.ts +510 -0
  331. package/src/components/DataTable/utils/hierarchicalSorting.ts +151 -0
  332. package/src/components/DataTable/utils/hierarchicalUtils.ts +218 -0
  333. package/src/components/DataTable/utils/index.ts +1 -0
  334. package/src/components/DataTable/utils/performanceUtils.ts +351 -0
  335. package/src/components/Dialog/Dialog.test.tsx +1139 -0
  336. package/src/components/Dialog/Dialog.tsx +782 -0
  337. package/src/components/Dialog/README.md +804 -0
  338. package/src/components/Dialog/examples/BasicHtmlTest.tsx +55 -0
  339. package/src/components/Dialog/examples/DebugHtmlExample.tsx +68 -0
  340. package/src/components/Dialog/examples/HtmlDialogExample.tsx +202 -0
  341. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +61 -0
  342. package/src/components/Dialog/examples/SmartDialogExample.tsx +322 -0
  343. package/src/components/Dialog/index.ts +12 -0
  344. package/src/components/Dialog/utils/safeHtml.ts +185 -0
  345. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +752 -0
  346. package/src/components/ErrorBoundary/ErrorBoundary.tsx +312 -0
  347. package/src/components/ErrorBoundary/index.ts +8 -0
  348. package/src/components/EventSelector/EventSelector.tsx +360 -0
  349. package/src/components/EventSelector/index.ts +3 -0
  350. package/src/components/EventSelector/types.ts +79 -0
  351. package/src/components/FileUpload/FileUpload.example.tsx +218 -0
  352. package/src/components/FileUpload/FileUpload.test.tsx +665 -0
  353. package/src/components/FileUpload/FileUpload.tsx +237 -0
  354. package/src/components/FileUpload/index.ts +6 -0
  355. package/src/components/Footer/Footer.test.tsx +482 -0
  356. package/src/components/Footer/Footer.tsx +197 -0
  357. package/src/components/Footer/index.ts +17 -0
  358. package/src/components/Form/Form.test.tsx +1158 -0
  359. package/src/components/Form/Form.tsx +166 -0
  360. package/src/components/Form/FormErrorSummary.tsx +113 -0
  361. package/src/components/Form/FormField.tsx +249 -0
  362. package/src/components/Form/FormFieldset.tsx +127 -0
  363. package/src/components/Form/FormLiveRegion.tsx +198 -0
  364. package/src/components/Form/index.ts +26 -0
  365. package/src/components/Header/Header.test.tsx +582 -0
  366. package/src/components/Header/Header.tsx +301 -0
  367. package/src/components/Header/index.ts +4 -0
  368. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +489 -0
  369. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +164 -0
  370. package/src/components/InactivityWarningModal/index.ts +9 -0
  371. package/src/components/Input/Input.test.tsx +466 -0
  372. package/src/components/Input/Input.tsx +201 -0
  373. package/src/components/Input/__mocks__/Input.tsx +2 -0
  374. package/src/components/Input/index.ts +9 -0
  375. package/src/components/Label/Label.tsx +186 -0
  376. package/src/components/Label/index.ts +2 -0
  377. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +450 -0
  378. package/src/components/LoadingSpinner/LoadingSpinner.tsx +98 -0
  379. package/src/components/LoadingSpinner/index.ts +3 -0
  380. package/src/components/LoginForm/LoginForm.test.tsx +816 -0
  381. package/src/components/LoginForm/LoginForm.tsx +273 -0
  382. package/src/components/LoginForm/index.ts +3 -0
  383. package/src/components/NavigationMenu/NavigationMenu.test.tsx +883 -0
  384. package/src/components/NavigationMenu/NavigationMenu.tsx +698 -0
  385. package/src/components/NavigationMenu/index.ts +10 -0
  386. package/src/components/NavigationMenu/types.ts +85 -0
  387. package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +748 -0
  388. package/src/components/OrganisationSelector/OrganisationSelector.tsx +304 -0
  389. package/src/components/OrganisationSelector/index.ts +9 -0
  390. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +891 -0
  391. package/src/components/PaceAppLayout/PaceAppLayout.tsx +699 -0
  392. package/src/components/PaceAppLayout/README.md +278 -0
  393. package/src/components/PaceAppLayout/index.ts +1 -0
  394. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +475 -0
  395. package/src/components/PaceLoginPage/PaceLoginPage.tsx +221 -0
  396. package/src/components/PaceLoginPage/index.ts +1 -0
  397. package/src/components/PasswordReset/PasswordChangeForm.test.tsx +621 -0
  398. package/src/components/PasswordReset/PasswordChangeForm.tsx +186 -0
  399. package/src/components/PasswordReset/PasswordResetForm.test.tsx +605 -0
  400. package/src/components/PasswordReset/PasswordResetForm.tsx +201 -0
  401. package/src/components/PasswordReset/index.ts +4 -0
  402. package/src/components/PrintButton/PrintButton.tsx +321 -0
  403. package/src/components/PrintButton/PrintButtonGroup.tsx +84 -0
  404. package/src/components/PrintButton/PrintToolbar.tsx +94 -0
  405. package/src/components/PrintButton/examples/PrintButtonShowcase.tsx +438 -0
  406. package/src/components/PrintButton/index.ts +33 -0
  407. package/src/components/PrintButton/types.ts +173 -0
  408. package/src/components/PrintCard/PrintCard.tsx +154 -0
  409. package/src/components/PrintCard/PrintCardContent.tsx +57 -0
  410. package/src/components/PrintCard/PrintCardFooter.tsx +60 -0
  411. package/src/components/PrintCard/PrintCardGrid.tsx +91 -0
  412. package/src/components/PrintCard/PrintCardHeader.tsx +78 -0
  413. package/src/components/PrintCard/PrintCardImage.tsx +81 -0
  414. package/src/components/PrintCard/examples/PrintCardShowcase.tsx +239 -0
  415. package/src/components/PrintCard/index.ts +34 -0
  416. package/src/components/PrintCard/types.ts +171 -0
  417. package/src/components/PrintDataTable/PrintDataTable.tsx +215 -0
  418. package/src/components/PrintDataTable/PrintTableGroup.tsx +90 -0
  419. package/src/components/PrintDataTable/PrintTableRow.tsx +76 -0
  420. package/src/components/PrintDataTable/index.ts +25 -0
  421. package/src/components/PrintDataTable/types.ts +67 -0
  422. package/src/components/PrintFooter/PrintFooter.tsx +183 -0
  423. package/src/components/PrintFooter/PrintFooterContent.tsx +71 -0
  424. package/src/components/PrintFooter/PrintFooterInfo.tsx +86 -0
  425. package/src/components/PrintFooter/PrintPageNumber.tsx +90 -0
  426. package/src/components/PrintFooter/examples/PrintFooterShowcase.tsx +390 -0
  427. package/src/components/PrintFooter/index.ts +30 -0
  428. package/src/components/PrintFooter/types.ts +149 -0
  429. package/src/components/PrintGrid/PrintGrid.tsx +180 -0
  430. package/src/components/PrintGrid/PrintGridBreakpoint.tsx +109 -0
  431. package/src/components/PrintGrid/PrintGridContainer.tsx +128 -0
  432. package/src/components/PrintGrid/PrintGridItem.tsx +220 -0
  433. package/src/components/PrintGrid/examples/PrintGridShowcase.tsx +359 -0
  434. package/src/components/PrintGrid/index.ts +31 -0
  435. package/src/components/PrintGrid/types.ts +159 -0
  436. package/src/components/PrintHeader/PrintCoverHeader.tsx +230 -0
  437. package/src/components/PrintHeader/PrintHeader.tsx +150 -0
  438. package/src/components/PrintHeader/index.ts +17 -0
  439. package/src/components/PrintHeader/types.ts +42 -0
  440. package/src/components/PrintLayout/PrintLayout.tsx +122 -0
  441. package/src/components/PrintLayout/PrintLayoutContext.tsx +66 -0
  442. package/src/components/PrintLayout/PrintPageBreak.tsx +52 -0
  443. package/src/components/PrintLayout/examples/PrintShowcase.tsx +230 -0
  444. package/src/components/PrintLayout/index.ts +19 -0
  445. package/src/components/PrintLayout/types.ts +37 -0
  446. package/src/components/PrintPageBreak/PrintPageBreak.tsx +120 -0
  447. package/src/components/PrintPageBreak/PrintPageBreakGroup.tsx +90 -0
  448. package/src/components/PrintPageBreak/PrintPageBreakIndicator.tsx +112 -0
  449. package/src/components/PrintPageBreak/examples/PrintPageBreakShowcase.tsx +279 -0
  450. package/src/components/PrintPageBreak/index.ts +23 -0
  451. package/src/components/PrintPageBreak/types.ts +94 -0
  452. package/src/components/PrintSection/PrintColumn.tsx +104 -0
  453. package/src/components/PrintSection/PrintDivider.tsx +101 -0
  454. package/src/components/PrintSection/PrintSection.tsx +129 -0
  455. package/src/components/PrintSection/PrintSectionContent.tsx +75 -0
  456. package/src/components/PrintSection/PrintSectionHeader.tsx +97 -0
  457. package/src/components/PrintSection/examples/PrintSectionShowcase.tsx +258 -0
  458. package/src/components/PrintSection/index.ts +33 -0
  459. package/src/components/PrintSection/types.ts +155 -0
  460. package/src/components/PrintText/PrintText.tsx +116 -0
  461. package/src/components/PrintText/index.ts +16 -0
  462. package/src/components/PrintText/types.ts +24 -0
  463. package/src/components/Progress/Progress.tsx +116 -0
  464. package/src/components/Progress/index.ts +3 -0
  465. package/src/components/PublicLayout/EventLogo.tsx +287 -0
  466. package/src/components/PublicLayout/PublicErrorBoundary.tsx +279 -0
  467. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +208 -0
  468. package/src/components/PublicLayout/PublicPageContextChecker.tsx +130 -0
  469. package/src/components/PublicLayout/PublicPageDebugger.tsx +104 -0
  470. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +162 -0
  471. package/src/components/PublicLayout/PublicPageFooter.tsx +124 -0
  472. package/src/components/PublicLayout/PublicPageHeader.tsx +178 -0
  473. package/src/components/PublicLayout/PublicPageLayout.tsx +232 -0
  474. package/src/components/PublicLayout/PublicPageProvider.tsx +137 -0
  475. package/src/components/PublicLayout/index.ts +51 -0
  476. package/src/components/Select/Select.test.tsx +948 -0
  477. package/src/components/Select/Select.tsx +660 -0
  478. package/src/components/Select/index.ts +1 -0
  479. package/src/components/SuperAdminGuard.tsx +116 -0
  480. package/src/components/Table/Table.tsx +222 -0
  481. package/src/components/Table/index.ts +11 -0
  482. package/src/components/Toast/Toast.test.tsx +586 -0
  483. package/src/components/Toast/Toast.tsx +339 -0
  484. package/src/components/Toast/index.ts +14 -0
  485. package/src/components/Tooltip/Tooltip.test.tsx +852 -0
  486. package/src/components/Tooltip/Tooltip.tsx +167 -0
  487. package/src/components/Tooltip/index.ts +7 -0
  488. package/src/components/UserMenu/UserMenu.test.tsx +702 -0
  489. package/src/components/UserMenu/UserMenu.tsx +243 -0
  490. package/src/components/UserMenu/index.ts +3 -0
  491. package/src/components/examples/PermissionExample.tsx +150 -0
  492. package/src/components/index.ts +434 -0
  493. package/src/components.ts +19 -0
  494. package/src/constants/performance.ts +14 -0
  495. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  496. package/src/examples/PublicEventPage.tsx +274 -0
  497. package/src/examples/PublicPageApp.tsx +308 -0
  498. package/src/examples/PublicPageUsageExample.tsx +216 -0
  499. package/src/hooks/index.ts +56 -0
  500. package/src/hooks/public/index.ts +34 -0
  501. package/src/hooks/public/usePublicEvent.ts +261 -0
  502. package/src/hooks/public/usePublicEventLogo.ts +285 -0
  503. package/src/hooks/public/usePublicRouteParams.ts +259 -0
  504. package/src/hooks/useAppConfig.ts +94 -0
  505. package/src/hooks/useComponentPerformance.ts +39 -0
  506. package/src/hooks/useCounter.test.ts +135 -0
  507. package/src/hooks/useDataTablePerformance.ts +387 -0
  508. package/src/hooks/useDataTableState.ts +110 -0
  509. package/src/hooks/useDebounce.test.ts +375 -0
  510. package/src/hooks/useDebounce.ts +18 -0
  511. package/src/hooks/useFocusManagement.ts +161 -0
  512. package/src/hooks/useFocusTrap.ts +155 -0
  513. package/src/hooks/useInactivityTracker.ts +372 -0
  514. package/src/hooks/useIsMobile.ts +42 -0
  515. package/src/hooks/useKeyboardShortcuts.ts +237 -0
  516. package/src/hooks/useOrganisationPermissions.test.ts +528 -0
  517. package/src/hooks/useOrganisationPermissions.ts +208 -0
  518. package/src/hooks/useOrganisationSecurity.test.ts +734 -0
  519. package/src/hooks/useOrganisationSecurity.ts +262 -0
  520. package/src/hooks/usePerformanceMonitor.ts +128 -0
  521. package/src/hooks/usePermissionCache.test.ts +542 -0
  522. package/src/hooks/usePermissionCache.ts +455 -0
  523. package/src/hooks/useSecureDataAccess.ts +586 -0
  524. package/src/hooks/useStorage.ts +274 -0
  525. package/src/hooks/useToast.ts +242 -0
  526. package/src/hooks/useZodForm.ts +28 -0
  527. package/src/index.ts +199 -0
  528. package/src/providers/AuthProvider.tsx +369 -0
  529. package/src/providers/EventProvider.tsx +324 -0
  530. package/src/providers/InactivityProvider.tsx +238 -0
  531. package/src/providers/OrganisationProvider.tsx +588 -0
  532. package/src/providers/UnifiedAuthProvider.tsx +327 -0
  533. package/src/providers/index.ts +17 -0
  534. package/src/rbac/README.md +885 -0
  535. package/src/rbac/__tests__/integration.test.tsx +218 -0
  536. package/src/rbac/adapters.tsx +726 -0
  537. package/src/rbac/api.test.ts +441 -0
  538. package/src/rbac/api.ts +339 -0
  539. package/src/rbac/audit-enhanced.ts +339 -0
  540. package/src/rbac/audit.ts +338 -0
  541. package/src/rbac/cache.ts +215 -0
  542. package/src/rbac/components/EnhancedNavigationMenu.tsx +294 -0
  543. package/src/rbac/components/NavigationGuard.tsx +294 -0
  544. package/src/rbac/components/NavigationProvider.tsx +314 -0
  545. package/src/rbac/components/PagePermissionGuard.tsx +430 -0
  546. package/src/rbac/components/PagePermissionProvider.tsx +274 -0
  547. package/src/rbac/components/PermissionEnforcer.tsx +307 -0
  548. package/src/rbac/components/RoleBasedRouter.tsx +425 -0
  549. package/src/rbac/components/SecureDataProvider.tsx +319 -0
  550. package/src/rbac/components/index.ts +64 -0
  551. package/src/rbac/config.ts +133 -0
  552. package/src/rbac/docs/event-based-apps.md +285 -0
  553. package/src/rbac/engine.ts +1026 -0
  554. package/src/rbac/eslint-rules.js +285 -0
  555. package/src/rbac/examples/CompleteRBACExample.tsx +323 -0
  556. package/src/rbac/examples/EventBasedApp.tsx +238 -0
  557. package/src/rbac/hooks/index.ts +21 -0
  558. package/src/rbac/hooks/useCan.test.ts +461 -0
  559. package/src/rbac/hooks/usePermissions.test.ts +359 -0
  560. package/src/rbac/hooks/usePermissions.ts +567 -0
  561. package/src/rbac/hooks/useRBAC.simple.test.ts +90 -0
  562. package/src/rbac/hooks/useRBAC.test.ts +503 -0
  563. package/src/rbac/hooks/useRBAC.ts +262 -0
  564. package/src/rbac/index.ts +109 -0
  565. package/src/rbac/permissions.ts +293 -0
  566. package/src/rbac/providers/RBACProvider.tsx +634 -0
  567. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +687 -0
  568. package/src/rbac/providers/index.ts +11 -0
  569. package/src/rbac/secureClient.ts +244 -0
  570. package/src/rbac/security.ts +346 -0
  571. package/src/rbac/testing/index.tsx +340 -0
  572. package/src/rbac/types.ts +343 -0
  573. package/src/rbac/utils/eventContext.ts +83 -0
  574. package/src/styles/core.css +364 -0
  575. package/src/styles/index.ts +51 -0
  576. package/src/theming/runtime.ts +187 -0
  577. package/src/types/database.ts +472 -0
  578. package/src/types/guards.ts +30 -0
  579. package/src/types/index.ts +25 -0
  580. package/src/types/organisation.ts +184 -0
  581. package/src/types/security.ts +70 -0
  582. package/src/types/supabase.ts +166 -0
  583. package/src/types/theme.ts +6 -0
  584. package/src/types/unified.ts +262 -0
  585. package/src/types/validation.ts +164 -0
  586. package/src/types/vitest-globals.d.ts +43 -0
  587. package/src/utils/__mocks__/supabaseMock.ts +75 -0
  588. package/src/utils/__mocks__/supabaseMock.tsx +198 -0
  589. package/src/utils/appConfig.ts +47 -0
  590. package/src/utils/appIdResolver.ts +130 -0
  591. package/src/utils/appNameResolver.ts +190 -0
  592. package/src/utils/audit.ts +127 -0
  593. package/src/utils/auth-utils.ts +96 -0
  594. package/src/utils/bundleAnalysis.ts +129 -0
  595. package/src/utils/cn.ts +7 -0
  596. package/src/utils/debugLogger.ts +46 -0
  597. package/src/utils/deviceFingerprint.ts +215 -0
  598. package/src/utils/dynamicUtils.ts +105 -0
  599. package/src/utils/formatDate.test.ts +241 -0
  600. package/src/utils/formatting.ts +77 -0
  601. package/src/utils/index.ts +145 -0
  602. package/src/utils/lazyLoad.tsx +44 -0
  603. package/src/utils/organisationContext.ts +135 -0
  604. package/src/utils/performanceBenchmark.ts +64 -0
  605. package/src/utils/performanceBudgets.ts +111 -0
  606. package/src/utils/permissionTypes.ts +37 -0
  607. package/src/utils/permissionUtils.ts +31 -0
  608. package/src/utils/print/PrintDataProcessor.ts +390 -0
  609. package/src/utils/print/examples/PrintUtilitiesShowcase.tsx +397 -0
  610. package/src/utils/print/index.ts +29 -0
  611. package/src/utils/print/types.ts +196 -0
  612. package/src/utils/print/usePrintOptimization.ts +272 -0
  613. package/src/utils/sanitization.ts +264 -0
  614. package/src/utils/schemaUtils.ts +37 -0
  615. package/src/utils/secureDataAccess.ts +361 -0
  616. package/src/utils/secureErrors.ts +79 -0
  617. package/src/utils/secureStorage.ts +244 -0
  618. package/src/utils/security.ts +156 -0
  619. package/src/utils/securityMonitor.ts +45 -0
  620. package/src/utils/sessionTracking.ts +170 -0
  621. package/src/utils/storage/README.md +348 -0
  622. package/src/utils/storage/config.ts +100 -0
  623. package/src/utils/storage/helpers.ts +359 -0
  624. package/src/utils/storage/index.ts +36 -0
  625. package/src/utils/storage/types.ts +90 -0
  626. package/src/utils/validation.ts +111 -0
  627. package/src/utils/validationUtils.ts +120 -0
  628. package/src/validation/common.ts +53 -0
  629. package/src/validation/csrf.ts +214 -0
  630. package/src/validation/index.ts +43 -0
  631. package/src/validation/passwordSchema.ts +125 -0
  632. package/src/validation/sanitization.ts +96 -0
  633. package/src/validation/schemaUtils.ts +42 -0
  634. package/src/validation/sqlInjectionProtection.ts +242 -0
  635. package/src/validation/user.ts +34 -0
  636. package/dist/chunk-4MCJAK7J.js.map +0 -1
  637. package/dist/chunk-4ZTIEYU2.js.map +0 -1
  638. package/dist/chunk-H4PZ4B3Y.js.map +0 -1
  639. package/dist/chunk-IOX76PSM.js.map +0 -1
  640. package/dist/chunk-JUUNUW3O.js.map +0 -1
  641. package/dist/chunk-KK6WIDK6.js +0 -63
  642. package/dist/chunk-KK6WIDK6.js.map +0 -1
  643. package/dist/chunk-U7DY5T33.js +0 -11
  644. package/dist/chunk-U7DY5T33.js.map +0 -1
  645. package/dist/chunk-WHLSWC6W.js.map +0 -1
  646. package/dist/chunk-XI7QFSSC.js +0 -790
  647. package/dist/chunk-XI7QFSSC.js.map +0 -1
  648. package/dist/chunk-XIJMMBDD.js +0 -73
  649. package/dist/chunk-XIJMMBDD.js.map +0 -1
  650. package/dist/chunk-YNU5QJ4S.js.map +0 -1
  651. package/dist/chunk-YWYCNGWH.js +0 -2070
  652. package/dist/chunk-YWYCNGWH.js.map +0 -1
  653. package/dist/chunk-ZJ3UKPIW.js +0 -952
  654. package/dist/chunk-ZJ3UKPIW.js.map +0 -1
  655. package/dist/useAppConfig-CZNJJsT_.d.ts +0 -148
  656. package/dist/{DataTable-2LB6HI6V.js.map → DataTable-ZQDRE46Q.js.map} +0 -0
  657. package/dist/{api-AIJ3IJX3.js.map → api-H5A3H4IR.js.map} +0 -0
  658. package/dist/{audit-PD5L5ZSC.js.map → appNameResolver-7GHF5ED2.js.map} +0 -0
  659. package/dist/{chunk-DC5AMYBS.js.map → audit-BUW3LMJB.js.map} +0 -0
  660. package/dist/{validation-D2-NNCCE.d.ts → validation-PM_iOaTI.d.ts} +6 -6
@@ -1,5 +1,7 @@
1
1
  # RBAC Quick Start
2
2
 
3
+ > **⚠️ CRITICAL**: This guide is designed to be impossible to get wrong. Follow every step exactly as written, and your RBAC system will work perfectly.
4
+
3
5
  Build your first RBAC-enabled application in under 10 minutes.
4
6
 
5
7
  ## 🎯 What We'll Build
@@ -7,8 +9,16 @@ Build your first RBAC-enabled application in under 10 minutes.
7
9
  A simple user management app that demonstrates:
8
10
  - Permission-based UI rendering
9
11
  - Component-level access control
10
- - Server-side permission validation
11
- - Caching and performance optimization
12
+ - Proper app ID resolution (fixes "Access Denied" errors)
13
+ - Correct provider setup (fixes 400/406 database errors)
14
+ - App context requirements (organisation vs event-based)
15
+
16
+ ## 🚨 Critical Rules (Follow These or It Won't Work)
17
+
18
+ 1. **Never make direct database queries** to `rbac_apps`, `rbac_global_roles`, or other RBAC tables
19
+ 2. **Always use `PagePermissionGuard`** for page-level permissions (not manual permission checks)
20
+ 3. **Always set up providers correctly** in the exact order shown
21
+ 4. **Use the exact app name** from your environment variable (must match database exactly)
12
22
 
13
23
  ## 🚀 Step-by-Step Implementation
14
24
 
@@ -23,31 +33,40 @@ cd user-manager
23
33
 
24
34
  ### 2. Install Dependencies
25
35
 
36
+ **CRITICAL**: Use the exact versions specified to avoid compatibility issues.
37
+
26
38
  ```bash
27
- npm install @jmruthers/pace-core @supabase/supabase-js
39
+ npm install @jmruthers/pace-core@^0.4.1 @supabase/supabase-js@^2.38.0
28
40
  npm install -D tailwindcss @types/react @types/react-dom
29
41
  ```
30
42
 
31
- ### 3. Configure Tailwind CSS
43
+ ### 3. Configure Tailwind CSS v4
32
44
 
45
+ Install Tailwind CSS v4:
33
46
  ```bash
34
- npx tailwindcss init
47
+ npm install -D @tailwindcss/vite tailwindcss@^4.0.0
35
48
  ```
36
49
 
37
- Update `tailwind.config.js`:
38
-
39
- ```js
40
- /** @type {import('tailwindcss').Config} */
41
- module.exports = {
42
- content: [
43
- './src/**/*.{js,ts,jsx,tsx}',
44
- './node_modules/@jmruthers/pace-core/**/*.{js,ts,jsx,tsx}',
50
+ Update `vite.config.ts`:
51
+
52
+ ```ts
53
+ // vite.config.ts
54
+ import { defineConfig } from 'vite'
55
+ import react from '@vitejs/plugin-react'
56
+ import tailwindcss from '@tailwindcss/vite'
57
+
58
+ export default defineConfig({
59
+ plugins: [
60
+ react(),
61
+ tailwindcss({
62
+ // CRITICAL: Include pace-core components for scanning
63
+ content: [
64
+ './src/**/*.{js,ts,jsx,tsx}',
65
+ './node_modules/@jmruthers/pace-core/**/*.{js,ts,jsx,tsx}'
66
+ ]
67
+ })
45
68
  ],
46
- theme: {
47
- extend: {},
48
- },
49
- plugins: [],
50
- }
69
+ })
51
70
  ```
52
71
 
53
72
  ### 4. Set Up Environment Variables
@@ -55,389 +74,546 @@ module.exports = {
55
74
  Create `.env.local`:
56
75
 
57
76
  ```bash
58
- REACT_APP_SUPABASE_URL=https://your-project.supabase.co
59
- REACT_APP_SUPABASE_ANON_KEY=your-anon-key-here
77
+ # .env.local
78
+ VITE_SUPABASE_URL=https://your-project.supabase.co
79
+ VITE_SUPABASE_ANON_KEY=your-anon-key-here
80
+ VITE_APP_NAME=user-manager
60
81
  ```
61
82
 
62
- ### 5. Create Supabase Client
83
+ **CRITICAL**:
84
+ - Use `VITE_` prefix for Vite projects
85
+ - Use `NEXT_PUBLIC_` prefix for Next.js projects
86
+ - The `VITE_APP_NAME` must match exactly what you have in the `rbac_apps` table
87
+
88
+ ### 5. Database Setup (CRITICAL)
89
+
90
+ **CRITICAL**: Your app must be registered in the database before you can use RBAC.
91
+
92
+ #### 5.1 Register Your App
93
+
94
+ Run this SQL in your Supabase SQL editor:
95
+
96
+ ```sql
97
+ -- Replace 'user-manager' with your actual app name (must match VITE_APP_NAME)
98
+ INSERT INTO rbac_apps (name, display_name, requires_event, is_active)
99
+ VALUES ('user-manager', 'User Manager', false, true)
100
+ ON CONFLICT (name) DO UPDATE SET
101
+ display_name = EXCLUDED.display_name,
102
+ requires_event = EXCLUDED.requires_event,
103
+ is_active = EXCLUDED.is_active;
104
+ ```
105
+
106
+ #### 5.2 Create App Pages
107
+
108
+ ```sql
109
+ -- Create pages for your app (replace 'user-manager' with your actual app name)
110
+ INSERT INTO rbac_app_pages (app_id, page_name, page_description)
111
+ SELECT
112
+ a.id,
113
+ unnest(ARRAY['dashboard', 'users', 'settings', 'admin']),
114
+ unnest(ARRAY['Main Dashboard', 'User Management', 'App Settings', 'Admin Panel'])
115
+ FROM rbac_apps a
116
+ WHERE a.name = 'user-manager';
117
+ ```
118
+
119
+ #### 5.3 Set Up Page Permissions
120
+
121
+ ```sql
122
+ -- Set up basic permissions for each page (replace 'user-manager' with your actual app name)
123
+ WITH app_pages AS (
124
+ SELECT ap.id as page_id, ap.page_name, a.id as app_id
125
+ FROM rbac_app_pages ap
126
+ JOIN rbac_apps a ON ap.app_id = a.id
127
+ WHERE a.name = 'user-manager'
128
+ )
129
+ INSERT INTO rbac_page_permissions (app_page_id, operation, role_name, allowed, organisation_id)
130
+ SELECT
131
+ ap.page_id,
132
+ op.operation,
133
+ role.role_name,
134
+ CASE
135
+ WHEN role.role_name = 'org_admin' THEN true
136
+ WHEN role.role_name = 'leader' AND ap.page_name != 'admin' THEN true
137
+ WHEN role.role_name = 'member' AND ap.page_name IN ('dashboard', 'users') THEN true
138
+ ELSE false
139
+ END,
140
+ '00000000-0000-0000-0000-000000000000'::uuid -- Replace with your organisation ID
141
+ FROM app_pages ap
142
+ CROSS JOIN (SELECT unnest(ARRAY['read', 'create', 'update', 'delete']) as operation) op
143
+ CROSS JOIN (SELECT unnest(ARRAY['org_admin', 'leader', 'member']) as role_name) role;
144
+ ```
145
+
146
+ #### 5.4 Assign User Roles
147
+
148
+ ```sql
149
+ -- Grant a user the org_admin role (replace with actual user and organisation IDs)
150
+ INSERT INTO rbac_organisation_roles (user_id, organisation_id, role, status, granted_at)
151
+ VALUES (
152
+ 'your-user-id'::uuid,
153
+ 'your-organisation-id'::uuid,
154
+ 'org_admin',
155
+ 'active',
156
+ NOW()
157
+ )
158
+ ON CONFLICT (user_id, organisation_id) DO UPDATE SET
159
+ role = EXCLUDED.role,
160
+ status = EXCLUDED.status,
161
+ updated_at = NOW();
162
+ ```
163
+
164
+ ### 6. App Context Requirements
165
+
166
+ The RBAC system supports two types of apps based on their context requirements:
167
+
168
+ #### Organisation-Based App (Default)
169
+ - **Context**: Requires `organisationId` in scope
170
+ - **Use case**: User management, organisation settings, general dashboards
171
+ - **Database**: `rbac_apps.requires_event = false`
172
+
173
+ #### Event-Based App
174
+ - **Context**: Requires `eventId` in scope, automatically resolves `organisationId` from event
175
+ - **Use case**: Event registration, event management, event-specific reporting
176
+ - **Database**: `rbac_apps.requires_event = true`
177
+
178
+ ### 7. Create Supabase Client
179
+
180
+ Create `src/lib/supabase.ts`:
63
181
 
64
182
  ```typescript
65
183
  // src/lib/supabase.ts
66
184
  import { createClient } from '@supabase/supabase-js'
67
185
 
68
- const supabaseUrl = process.env.REACT_APP_SUPABASE_URL!
69
- const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY!
186
+ const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
187
+ const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY
188
+
189
+ if (!supabaseUrl || !supabaseAnonKey) {
190
+ throw new Error('Missing Supabase environment variables')
191
+ }
70
192
 
71
193
  export const supabase = createClient(supabaseUrl, supabaseAnonKey)
72
194
  ```
73
195
 
74
- ### 6. Set Up App Structure
196
+ ### 8. App Setup (CRITICAL)
75
197
 
76
- ```tsx
77
- // src/App.tsx - COMPLETE setup
78
- import React from 'react';
79
- import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
80
- import { setupRBAC } from '@jmruthers/pace-core/rbac';
198
+ Create `src/App.tsx` with this EXACT structure:
199
+
200
+ ```typescript
201
+ // src/App.tsx
202
+ import React from 'react'
203
+ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
81
204
  import {
82
205
  UnifiedAuthProvider,
83
- OrganisationProvider
84
- } from '@jmruthers/pace-core';
85
- import { supabase } from './lib/supabase';
86
- import { AppLayout } from './components/AppLayout';
87
- import { LoginPage } from './components/LoginPage';
88
- import { DashboardPage } from './components/DashboardPage';
89
- import { UsersPage } from './components/UsersPage';
206
+ OrganisationProvider,
207
+ EventProvider
208
+ } from '@jmruthers/pace-core/providers'
209
+ import { setRBACAppName } from '@jmruthers/pace-core/utils'
210
+ import { supabase } from './lib/supabase'
211
+ import { Dashboard } from './pages/Dashboard'
212
+ import { Users } from './pages/Users'
213
+ import { Login } from './pages/Login'
214
+
215
+ // CRITICAL: Set the app name for RBAC resolution
216
+ const APP_NAME = import.meta.env.VITE_APP_NAME
217
+
218
+ if (!APP_NAME) {
219
+ throw new Error('VITE_APP_NAME environment variable is required')
220
+ }
90
221
 
91
- // ⚠️ REQUIRED: Setup RBAC first
92
- setupRBAC(supabase);
222
+ // CRITICAL: Set the app name globally for RBAC
223
+ setRBACAppName(APP_NAME)
93
224
 
94
225
  function App() {
95
226
  return (
96
227
  <UnifiedAuthProvider
97
- supabaseClient={supabase}
98
- appName="user-manager"
228
+ supabaseClient={supabase}
99
229
  >
100
230
  <OrganisationProvider>
101
- <Router>
102
- <Routes>
103
- <Route path="/login" element={<LoginPage />} />
104
- <Route path="/" element={<AppLayout />}>
105
- <Route index element={<DashboardPage />} />
106
- <Route path="users" element={<UsersPage />} />
107
- </Route>
108
- </Routes>
109
- </Router>
231
+ <EventProvider>
232
+ <Router>
233
+ <Routes>
234
+ <Route path="/login" element={<Login />} />
235
+ <Route path="/" element={<Dashboard />} />
236
+ <Route path="/users" element={<Users />} />
237
+ </Routes>
238
+ </Router>
239
+ </EventProvider>
110
240
  </OrganisationProvider>
111
241
  </UnifiedAuthProvider>
112
- );
242
+ )
113
243
  }
114
244
 
115
- export default App;
245
+ export default App
116
246
  ```
117
247
 
118
- ### 7. Create Login Page
119
-
120
- ```tsx
121
- // src/components/LoginPage.tsx
122
- import { LoginForm } from '@jmruthers/pace-core';
123
- import { useNavigate } from 'react-router-dom';
248
+ ### 9. Create Login Page
124
249
 
125
- export function LoginPage() {
126
- const navigate = useNavigate();
250
+ Create `src/pages/Login.tsx`:
127
251
 
128
- const handleLoginSuccess = () => {
129
- navigate('/');
130
- };
252
+ ```typescript
253
+ // src/pages/Login.tsx
254
+ import React, { useState } from 'react'
255
+ import { useNavigate } from 'react-router-dom'
256
+ import { supabase } from '../lib/supabase'
257
+
258
+ export function Login() {
259
+ const [email, setEmail] = useState('')
260
+ const [password, setPassword] = useState('')
261
+ const [loading, setLoading] = useState(false)
262
+ const navigate = useNavigate()
263
+
264
+ const handleLogin = async (e: React.FormEvent) => {
265
+ e.preventDefault()
266
+ setLoading(true)
267
+
268
+ try {
269
+ const { data, error } = await supabase.auth.signInWithPassword({
270
+ email,
271
+ password
272
+ })
273
+
274
+ if (error) {
275
+ alert('Login failed: ' + error.message)
276
+ return
277
+ }
278
+
279
+ if (data.user) {
280
+ navigate('/')
281
+ }
282
+ } catch (error) {
283
+ alert('Login failed: ' + (error as Error).message)
284
+ } finally {
285
+ setLoading(false)
286
+ }
287
+ }
131
288
 
132
289
  return (
133
290
  <div className="min-h-screen flex items-center justify-center bg-gray-50">
134
291
  <div className="max-w-md w-full space-y-8">
135
292
  <div>
136
293
  <h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
137
- Sign in to User Manager
294
+ Sign in to your account
138
295
  </h2>
139
296
  </div>
140
- <LoginForm onLoginSuccess={handleLoginSuccess} />
297
+ <form className="mt-8 space-y-6" onSubmit={handleLogin}>
298
+ <div>
299
+ <label htmlFor="email" className="sr-only">
300
+ Email address
301
+ </label>
302
+ <input
303
+ id="email"
304
+ name="email"
305
+ type="email"
306
+ required
307
+ className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
308
+ placeholder="Email address"
309
+ value={email}
310
+ onChange={(e) => setEmail(e.target.value)}
311
+ />
312
+ </div>
313
+ <div>
314
+ <label htmlFor="password" className="sr-only">
315
+ Password
316
+ </label>
317
+ <input
318
+ id="password"
319
+ name="password"
320
+ type="password"
321
+ required
322
+ className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
323
+ placeholder="Password"
324
+ value={password}
325
+ onChange={(e) => setPassword(e.target.value)}
326
+ />
327
+ </div>
328
+ <div>
329
+ <button
330
+ type="submit"
331
+ disabled={loading}
332
+ className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50"
333
+ >
334
+ {loading ? 'Signing in...' : 'Sign in'}
335
+ </button>
336
+ </div>
337
+ </form>
141
338
  </div>
142
339
  </div>
143
- );
340
+ )
144
341
  }
145
342
  ```
146
343
 
147
- ### 8. Create App Layout
344
+ ### 10. Create Dashboard Page
148
345
 
149
- ```tsx
150
- // src/components/AppLayout.tsx
151
- import { PaceAppLayout } from '@jmruthers/pace-core';
152
- import { Outlet } from 'react-router-dom';
153
-
154
- const navItems = [
155
- {
156
- title: 'Dashboard',
157
- href: '/',
158
- icon: 'HomeIcon'
159
- },
160
- {
161
- title: 'Users',
162
- href: '/users',
163
- icon: 'UsersIcon'
346
+ Create `src/pages/Dashboard.tsx`:
347
+
348
+ ```typescript
349
+ // src/pages/Dashboard.tsx
350
+ import React from 'react'
351
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers'
352
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac'
353
+ import { Link } from 'react-router-dom'
354
+ import { supabase } from '../lib/supabase'
355
+
356
+ export function Dashboard() {
357
+ const { user, selectedOrganisationId } = useUnifiedAuth()
358
+
359
+ if (!user) {
360
+ return <div>Please log in</div>
164
361
  }
165
- ];
166
362
 
167
- export function AppLayout() {
168
363
  return (
169
- <PaceAppLayout
170
- appName="User Manager"
171
- navItems={navItems}
172
- >
173
- <Outlet />
174
- </PaceAppLayout>
175
- );
364
+ <div className="min-h-screen bg-gray-50">
365
+ <nav className="bg-white shadow">
366
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
367
+ <div className="flex justify-between h-16">
368
+ <div className="flex items-center">
369
+ <h1 className="text-xl font-semibold">Dashboard</h1>
370
+ </div>
371
+ <div className="flex items-center space-x-4">
372
+ <span className="text-sm text-gray-700">
373
+ {user.email} | Org: {selectedOrganisationId}
374
+ </span>
375
+ <button
376
+ onClick={() => supabase.auth.signOut()}
377
+ className="text-sm text-gray-500 hover:text-gray-700"
378
+ >
379
+ Sign out
380
+ </button>
381
+ </div>
382
+ </div>
383
+ </div>
384
+ </nav>
385
+
386
+ <main className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
387
+ <div className="px-4 py-6 sm:px-0">
388
+ <div className="border-4 border-dashed border-gray-200 rounded-lg h-96 p-8">
389
+ <h2 className="text-2xl font-bold mb-4">Welcome to your Dashboard</h2>
390
+
391
+ {/* CRITICAL: Use PagePermissionGuard for page-level permissions */}
392
+ <PagePermissionGuard
393
+ pageName="dashboard"
394
+ operation="read"
395
+ fallback={<div>You don't have permission to view the dashboard</div>}
396
+ >
397
+ <div className="space-y-4">
398
+ <p>You have access to the dashboard!</p>
399
+
400
+ <div className="space-x-4">
401
+ <Link
402
+ to="/users"
403
+ className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
404
+ >
405
+ View Users
406
+ </Link>
407
+ </div>
408
+ </div>
409
+ </PagePermissionGuard>
410
+ </div>
411
+ </div>
412
+ </main>
413
+ </div>
414
+ )
176
415
  }
177
416
  ```
178
417
 
179
- ### 9. Create Dashboard Page
418
+ ### 11. Create Users Page
419
+
420
+ Create `src/pages/Users.tsx`:
421
+
422
+ ```typescript
423
+ // src/pages/Users.tsx
424
+ import React from 'react'
425
+ import { useUnifiedAuth } from '@jmruthers/pace-core/providers'
426
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac'
427
+ import { Link } from 'react-router-dom'
428
+ import { supabase } from '../lib/supabase'
429
+
430
+ export function Users() {
431
+ const { user, selectedOrganisationId } = useUnifiedAuth()
432
+
433
+ if (!user) {
434
+ return <div>Please log in</div>
435
+ }
180
436
 
181
- ```tsx
182
- // src/components/DashboardPage.tsx
183
- import { Card, CardHeader, CardTitle, CardContent } from '@jmruthers/pace-core';
184
- import { PermissionEnforcer, useCan } from '@jmruthers/pace-core/rbac';
185
- import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
186
-
187
- export function DashboardPage() {
188
- const { user, selectedOrganisationId } = useUnifiedAuth();
189
-
190
- // Pattern 1: PermissionEnforcer for automatic scope resolution
191
437
  return (
192
- <div className="p-6">
193
- <h1 className="text-2xl font-bold mb-6">Dashboard</h1>
194
-
195
- <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
196
- <Card>
197
- <CardHeader>
198
- <CardTitle>Total Users</CardTitle>
199
- </CardHeader>
200
- <CardContent>
201
- <p className="text-3xl font-bold">24</p>
202
- </CardContent>
203
- </Card>
204
-
205
- <Card>
206
- <CardHeader>
207
- <CardTitle>Active Sessions</CardTitle>
208
- </CardHeader>
209
- <CardContent>
210
- <p className="text-3xl font-bold">12</p>
211
- </CardContent>
212
- </Card>
213
-
214
- <Card>
215
- <CardHeader>
216
- <CardTitle>Permissions</CardTitle>
217
- </CardHeader>
218
- <CardContent>
219
- <PermissionStatus userId={user?.id} organisationId={selectedOrganisationId} />
220
- </CardContent>
221
- </Card>
222
- </div>
223
-
224
- {/* Pattern 1: PermissionEnforcer - automatic scope resolution */}
225
- <PermissionEnforcer
226
- permissions={['manage:users']}
227
- operation="user-management"
228
- fallback={<div>You need user management permissions</div>}
229
- >
230
- <div className="mt-6">
231
- <h2 className="text-lg font-semibold mb-4">User Management</h2>
232
- <p>You have user management permissions!</p>
438
+ <div className="min-h-screen bg-gray-50">
439
+ <nav className="bg-white shadow">
440
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
441
+ <div className="flex justify-between h-16">
442
+ <div className="flex items-center">
443
+ <Link to="/" className="text-blue-600 hover:text-blue-800 mr-4">
444
+ Back to Dashboard
445
+ </Link>
446
+ <h1 className="text-xl font-semibold">Users</h1>
447
+ </div>
448
+ <div className="flex items-center space-x-4">
449
+ <span className="text-sm text-gray-700">
450
+ {user.email} | Org: {selectedOrganisationId}
451
+ </span>
452
+ <button
453
+ onClick={() => supabase.auth.signOut()}
454
+ className="text-sm text-gray-500 hover:text-gray-700"
455
+ >
456
+ Sign out
457
+ </button>
458
+ </div>
459
+ </div>
460
+ </div>
461
+ </nav>
462
+
463
+ <main className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
464
+ <div className="px-4 py-6 sm:px-0">
465
+ <div className="border-4 border-dashed border-gray-200 rounded-lg h-96 p-8">
466
+ <h2 className="text-2xl font-bold mb-4">User Management</h2>
467
+
468
+ {/* CRITICAL: Use PagePermissionGuard for page-level permissions */}
469
+ <PagePermissionGuard
470
+ pageName="users"
471
+ operation="read"
472
+ fallback={<div>You don't have permission to view users</div>}
473
+ >
474
+ <div className="space-y-4">
475
+ <p>You have access to the users page!</p>
476
+ <p>This means your RBAC system is working correctly.</p>
477
+
478
+ <div className="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded">
479
+ <strong>Success!</strong> Your RBAC setup is working correctly.
480
+ </div>
481
+ </div>
482
+ </PagePermissionGuard>
483
+ </div>
233
484
  </div>
234
- </PermissionEnforcer>
485
+ </main>
235
486
  </div>
236
- );
237
- }
238
-
239
- // Pattern 2: useCan for specific permission checks
240
- function PermissionStatus({ userId, organisationId }) {
241
- const { can, isLoading, error } = useCan(
242
- userId || '',
243
- { organisationId: organisationId || '' },
244
- 'manage:users'
245
- );
246
-
247
- if (isLoading) return <p className="text-3xl font-bold">Loading...</p>;
248
- if (error) return <p className="text-3xl font-bold text-red-500">Error</p>;
249
-
250
- return (
251
- <p className="text-3xl font-bold">
252
- {can ? 'Admin' : 'User'}
253
- </p>
254
- );
487
+ )
255
488
  }
256
489
  ```
257
490
 
258
- ### 10. Create Users Page with Permission Guards
491
+ ## 🧪 Test Your Setup
259
492
 
260
- ```tsx
261
- // src/components/UsersPage.tsx
262
- import { DataTable } from '@jmruthers/pace-core';
263
- import { PermissionEnforcer, useCan } from '@jmruthers/pace-core/rbac';
264
- import { useUnifiedAuth } from '@jmruthers/pace-core/providers';
265
- import { useState } from 'react';
266
-
267
- interface User {
268
- id: string;
269
- name: string;
270
- email: string;
271
- role: string;
272
- lastLogin: string;
273
- }
493
+ 1. **Start your development server**:
494
+ ```bash
495
+ npm run dev
496
+ ```
274
497
 
275
- const sampleUsers: User[] = [
276
- { id: '1', name: 'John Doe', email: 'john@example.com', role: 'admin', lastLogin: '2024-01-15' },
277
- { id: '2', name: 'Jane Smith', email: 'jane@example.com', role: 'user', lastLogin: '2024-01-14' },
278
- { id: '3', name: 'Bob Johnson', email: 'bob@example.com', role: 'user', lastLogin: '2024-01-13' },
279
- ];
280
-
281
- const columns = [
282
- {
283
- accessorKey: 'name',
284
- header: 'Name',
285
- },
286
- {
287
- accessorKey: 'email',
288
- header: 'Email',
289
- },
290
- {
291
- accessorKey: 'role',
292
- header: 'Role',
293
- },
294
- {
295
- accessorKey: 'lastLogin',
296
- header: 'Last Login',
297
- },
298
- ];
299
-
300
- export function UsersPage() {
301
- const [users] = useState<User[]>(sampleUsers);
302
- const { user, selectedOrganisationId } = useUnifiedAuth();
498
+ 2. **Navigate to your app** (usually `http://localhost:3000` or `http://localhost:5173`)
303
499
 
304
- return (
305
- <div className="p-6">
306
- <div className="flex justify-between items-center mb-6">
307
- <h1 className="text-2xl font-bold">Users</h1>
308
-
309
- {/* Pattern 1: PermissionEnforcer - automatic scope resolution */}
310
- <PermissionEnforcer
311
- permissions={['create:users']}
312
- operation="user-creation"
313
- fallback={null} // Don't show anything if no permission
314
- >
315
- <button className="bg-blue-500 text-white px-4 py-2 rounded">
316
- Add User
317
- </button>
318
- </PermissionEnforcer>
319
- </div>
320
-
321
- <DataTable
322
- data={users}
323
- columns={columns}
324
- features={{
325
- search: true,
326
- pagination: true,
327
- }}
328
- />
329
-
330
- {/* Pattern 2: useCan for specific permission checks */}
331
- <DeleteActions userId={user?.id} organisationId={selectedOrganisationId} />
332
- </div>
333
- );
334
- }
500
+ 3. **You should see the login page**
335
501
 
336
- // Pattern 2: useCan for specific permission checks
337
- function DeleteActions({ userId, organisationId }) {
338
- const { can, isLoading, error } = useCan(
339
- userId || '',
340
- { organisationId: organisationId || '' },
341
- 'delete:users'
342
- );
502
+ 4. **Log in with a user that has the `org_admin` role**
343
503
 
344
- if (isLoading) return <div>Checking permissions...</div>;
345
- if (error) return <div>Error: {error.message}</div>;
346
- if (!can) return null;
504
+ 5. **You should be redirected to the dashboard**
347
505
 
348
- return (
349
- <div className="mt-4">
350
- <h3 className="text-lg font-semibold mb-2">Admin Actions</h3>
351
- <button className="bg-red-500 text-white px-4 py-2 rounded">
352
- Delete Selected Users
353
- </button>
354
- </div>
355
- );
356
- }
357
- ```
506
+ 6. **Click "View Users" - you should see the users page**
358
507
 
359
- ## 🎉 You're Done!
508
+ 7. **If you see "You don't have permission" messages, check the troubleshooting section below**
360
509
 
361
- Your app now has:
362
- - ✅ User authentication with Supabase
363
- - ✅ Role-based access control
364
- - ✅ Permission-based UI rendering
365
- - ✅ Component-level access control
366
- - ✅ Modern UI components
510
+ ## 🎉 Success Checklist
367
511
 
368
- ## 🚀 Next Steps
512
+ Your RBAC setup is working correctly if:
369
513
 
370
- - **[API Reference](./api-reference.md)** - Explore all available APIs
371
- - **[Examples](./examples.md)** - See more complex usage patterns
372
- - **[Advanced Patterns](./advanced-patterns.md)** - Learn optimization techniques
373
- - **[Troubleshooting](./troubleshooting.md)** - Common issues and solutions
514
+ - [ ] You can log in successfully
515
+ - [ ] You see the dashboard without "Access Denied" messages
516
+ - [ ] You can navigate to the users page
517
+ - [ ] You see "Success! Your RBAC setup is working correctly" on the users page
518
+ - [ ] No 400/406 errors in the browser console
519
+ - [ ] No "App not found" errors in the console
374
520
 
375
- ## 🔧 Customization
521
+ ## 🚨 Troubleshooting
376
522
 
377
- ### Add More Permissions
523
+ ### Issue: "Access Denied" on all pages
378
524
 
379
- ```tsx
380
- // Check multiple permissions
381
- const { hasPermission } = useCan();
525
+ **Check these in order:**
382
526
 
383
- const permissions = await Promise.all([
384
- hasPermission('read:users', { userId, scope }),
385
- hasPermission('create:users', { userId, scope }),
386
- hasPermission('update:users', { userId, scope }),
387
- hasPermission('delete:users', { userId, scope }),
388
- ]);
527
+ 1. **Verify your app is registered**:
528
+ ```sql
529
+ SELECT * FROM rbac_apps WHERE name = 'user-manager';
530
+ ```
389
531
 
390
- const [canRead, canCreate, canUpdate, canDelete] = permissions;
391
- ```
532
+ 2. **Check your environment variable**:
533
+ ```typescript
534
+ console.log('App name:', import.meta.env.VITE_APP_NAME);
535
+ ```
392
536
 
393
- ### Add Access Level Checks
537
+ 3. **Verify user has roles**:
538
+ ```sql
539
+ SELECT * FROM rbac_organisation_roles WHERE user_id = 'your-user-id';
540
+ ```
394
541
 
395
- ```tsx
396
- import { useAccessLevel, AccessLevelGuard } from '@jmruthers/pace-core';
542
+ 4. **Check page permissions exist**:
543
+ ```sql
544
+ SELECT pp.*, ap.page_name, a.name as app_name
545
+ FROM rbac_page_permissions pp
546
+ JOIN rbac_app_pages ap ON pp.app_page_id = ap.id
547
+ JOIN rbac_apps a ON ap.app_id = a.id
548
+ WHERE a.name = 'user-manager';
549
+ ```
397
550
 
398
- function AdminPanel() {
399
- const { accessLevel, isLoading } = useAccessLevel({
400
- userId: 'current-user-id',
401
- scope: { organisationId: 'current-org-id' }
402
- });
551
+ ### Issue: 400/406 Database Errors
403
552
 
404
- return (
405
- <AccessLevelGuard
406
- userId="current-user-id"
407
- scope={{ organisationId: "current-org-id" }}
408
- requiredLevel="admin"
409
- >
410
- <div>Admin-only content</div>
411
- </AccessLevelGuard>
412
- );
413
- }
414
- ```
553
+ **This means your app is making incorrect database queries. Check:**
554
+
555
+ 1. **You're using the providers correctly** (Step 8)
556
+ 2. **You're not making direct database queries to RBAC tables**
557
+ 3. **You're using the PagePermissionGuard component** (not manual permission checks)
558
+
559
+ ### Issue: "App not found or inactive"
560
+
561
+ **Check:**
562
+
563
+ 1. **Your app name in the database matches your environment variable exactly**
564
+ 2. **Your app is marked as active** (`is_active = true`)
565
+ 3. **You're using the correct app name in the UnifiedAuthProvider**
566
+
567
+ ### Issue: Components not rendering
568
+
569
+ **Check:**
570
+
571
+ 1. **You're using PagePermissionGuard (not manual permission checks)**
572
+ 2. **You're providing the correct pageName and operation**
573
+ 3. **The page exists in rbac_app_pages table**
574
+
575
+ ## 🏢 App Context Requirements
576
+
577
+ Your app is configured as an **organisation-based app** by default. This means:
578
+
579
+ - ✅ Requires `organisationId` in permission scope
580
+ - ✅ Works with organisation-level permissions
581
+ - ✅ Automatically enforces organisation context
415
582
 
416
- ### Add Server-Side Validation
583
+ ### Switching to Event-Based App
417
584
 
585
+ If you want to create an event-based app instead:
586
+
587
+ 1. **Update Database**:
588
+ ```sql
589
+ UPDATE rbac_apps
590
+ SET requires_event = true
591
+ WHERE name = 'user-manager';
592
+ ```
593
+
594
+ 2. **Update Frontend**:
418
595
  ```tsx
419
- // API route example
420
- import { isPermitted } from '@jmruthers/pace-core';
421
-
422
- export async function POST(request: Request) {
423
- const { userId, organisationId } = await request.json();
424
-
425
- const canCreate = await isPermitted({
426
- userId,
427
- scope: { organisationId },
428
- permission: 'create:users'
429
- });
430
-
431
- if (!canCreate) {
432
- return Response.json({ error: 'Insufficient permissions' }, { status: 403 });
433
- }
434
-
435
- // Proceed with user creation
436
- }
596
+ // Event-based app requires eventId instead of organisationId
597
+ const scope = { eventId: selectedEventId, appId: 'user-manager' };
437
598
  ```
438
599
 
439
- ## 🆘 Need Help?
600
+ 3. **Automatic Organisation Resolution**:
601
+ The system will automatically resolve the organisation ID from the event context.
602
+
603
+ ## 🚀 Next Steps
604
+
605
+ - **[API Reference](./api-reference.md)** - Complete API documentation
606
+ - **[Examples](./examples.md)** - More complex usage patterns
607
+ - **[Troubleshooting](./troubleshooting.md)** - Advanced troubleshooting
608
+ - **[Migration Guide](../migration/rbac-migration.md)** - If migrating from legacy RBAC
609
+
610
+ ## 🆘 Still Having Issues?
611
+
612
+ If you're still having problems after following this guide exactly:
613
+
614
+ 1. **Check the browser console** for specific error messages
615
+ 2. **Verify your database setup** matches the SQL commands exactly
616
+ 3. **Make sure your environment variables** are set correctly
617
+ 4. **Check that your user has the correct roles** in the database
440
618
 
441
- - Check [Troubleshooting](./troubleshooting.md) for common issues
442
- - Review [Examples](./examples.md) for usage patterns
443
- - See [API Reference](./api-reference.md) for detailed documentation
619
+ This guide is designed to be foolproof - if you follow it exactly, your RBAC system will work correctly.