@jmruthers/pace-core 0.5.183 → 0.5.185

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 (307) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +60 -1
  3. package/core-usage-manifest.json +312 -0
  4. package/dist/{DataTable-QAB34V6K.js → DataTable-IX2NBUTP.js} +6 -6
  5. package/dist/{DataTable-Bz8ffqyA.d.ts → DataTable-Z9NLVJh0.d.ts} +1 -1
  6. package/dist/{index-Bl--n7-T.d.ts → PublicPageProvider-BABf6JCh.d.ts} +21 -10
  7. package/dist/{UnifiedAuthProvider-7F6T4B6K.js → UnifiedAuthProvider-A4BCQRJY.js} +4 -2
  8. package/dist/{UnifiedAuthProvider-F86d7dSi.d.ts → UnifiedAuthProvider-BG0AL5eE.d.ts} +2 -1
  9. package/dist/{api-ROMBCNKU.js → api-BMFCXVQX.js} +2 -2
  10. package/dist/{chunk-RA3JUFMW.js → chunk-445GEP27.js} +154 -4
  11. package/dist/{chunk-RA3JUFMW.js.map → chunk-445GEP27.js.map} +1 -1
  12. package/dist/{chunk-CSOFYHAG.js → chunk-AISXLWGZ.js} +374 -60
  13. package/dist/chunk-AISXLWGZ.js.map +1 -0
  14. package/dist/{chunk-FUEYYMX5.js → chunk-FXFJRTKI.js} +24 -3
  15. package/dist/chunk-FXFJRTKI.js.map +1 -0
  16. package/dist/{chunk-QETLRQI6.js → chunk-HC67NW5K.js} +380 -360
  17. package/dist/chunk-HC67NW5K.js.map +1 -0
  18. package/dist/chunk-HESYZWZW.js +388 -0
  19. package/dist/chunk-HESYZWZW.js.map +1 -0
  20. package/dist/{chunk-QUVSNGIP.js → chunk-HGPQUCBC.js} +34 -9
  21. package/dist/{chunk-QUVSNGIP.js.map → chunk-HGPQUCBC.js.map} +1 -1
  22. package/dist/{chunk-UHNYIBXL.js → chunk-IXSNYUCT.js} +1 -1
  23. package/dist/chunk-IXSNYUCT.js.map +1 -0
  24. package/dist/{chunk-MI7HBHN3.js → chunk-MX3EIJGQ.js} +4 -3
  25. package/dist/{chunk-MI7HBHN3.js.map → chunk-MX3EIJGQ.js.map} +1 -1
  26. package/dist/{chunk-PWAHJW4G.js → chunk-OKI34GZD.js} +86 -33
  27. package/dist/chunk-OKI34GZD.js.map +1 -0
  28. package/dist/{chunk-W22JP75J.js → chunk-STTZQK2I.js} +3 -3
  29. package/dist/chunk-THRPYOFK.js +215 -0
  30. package/dist/chunk-THRPYOFK.js.map +1 -0
  31. package/dist/{chunk-M7W4CP3M.js → chunk-U6WNSFX5.js} +2 -1
  32. package/dist/chunk-U6WNSFX5.js.map +1 -0
  33. package/dist/{chunk-QCDXODCA.js → chunk-XAUHJD3L.js} +2 -2
  34. package/dist/components.d.ts +182 -6
  35. package/dist/components.js +157 -11
  36. package/dist/components.js.map +1 -1
  37. package/dist/eslint-rules/pace-core-compliance.cjs +406 -0
  38. package/dist/{file-reference-D06mEEWW.d.ts → file-reference-BjR39ktt.d.ts} +7 -1
  39. package/dist/hooks.d.ts +7 -14
  40. package/dist/hooks.js +10 -22
  41. package/dist/hooks.js.map +1 -1
  42. package/dist/index.d.ts +11 -11
  43. package/dist/index.js +79 -16
  44. package/dist/index.js.map +1 -1
  45. package/dist/providers.d.ts +1 -1
  46. package/dist/providers.js +3 -1
  47. package/dist/rbac/index.d.ts +205 -14
  48. package/dist/rbac/index.js +28 -6
  49. package/dist/timezone-_pgH8qrY.d.ts +530 -0
  50. package/dist/{types-_x1f4QBF.d.ts → types-DUyCRSTj.d.ts} +1 -1
  51. package/dist/types.d.ts +1 -1
  52. package/dist/types.js +1 -1
  53. package/dist/{usePublicRouteParams-JJczomYq.d.ts → usePublicRouteParams-CvnC3d-e.d.ts} +113 -2
  54. package/dist/utils.d.ts +109 -151
  55. package/dist/utils.js +128 -138
  56. package/dist/utils.js.map +1 -1
  57. package/docs/api/README.md +60 -1
  58. package/docs/api/classes/ColumnFactory.md +1 -1
  59. package/docs/api/classes/ErrorBoundary.md +1 -1
  60. package/docs/api/classes/InvalidScopeError.md +1 -1
  61. package/docs/api/classes/Logger.md +178 -0
  62. package/docs/api/classes/MissingUserContextError.md +1 -1
  63. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  64. package/docs/api/classes/PermissionDeniedError.md +1 -1
  65. package/docs/api/classes/RBACAuditManager.md +2 -2
  66. package/docs/api/classes/RBACCache.md +1 -1
  67. package/docs/api/classes/RBACEngine.md +2 -2
  68. package/docs/api/classes/RBACError.md +1 -1
  69. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  70. package/docs/api/classes/SecureSupabaseClient.md +5 -5
  71. package/docs/api/classes/StorageUtils.md +1 -1
  72. package/docs/api/enums/FileCategory.md +1 -1
  73. package/docs/api/enums/LogLevel.md +54 -0
  74. package/docs/api/enums/RBACErrorCode.md +1 -1
  75. package/docs/api/enums/RPCFunction.md +1 -1
  76. package/docs/api/interfaces/AggregateConfig.md +1 -1
  77. package/docs/api/interfaces/BadgeProps.md +1 -1
  78. package/docs/api/interfaces/ButtonProps.md +1 -1
  79. package/docs/api/interfaces/CalendarProps.md +18 -2
  80. package/docs/api/interfaces/CardProps.md +1 -1
  81. package/docs/api/interfaces/ColorPalette.md +1 -1
  82. package/docs/api/interfaces/ColorShade.md +1 -1
  83. package/docs/api/interfaces/ComplianceResult.md +30 -0
  84. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  85. package/docs/api/interfaces/DataRecord.md +1 -1
  86. package/docs/api/interfaces/DataTableAction.md +1 -1
  87. package/docs/api/interfaces/DataTableColumn.md +1 -1
  88. package/docs/api/interfaces/DataTableProps.md +1 -1
  89. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  90. package/docs/api/interfaces/DatabaseComplianceResult.md +85 -0
  91. package/docs/api/interfaces/DatabaseIssue.md +41 -0
  92. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  93. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  94. package/docs/api/interfaces/EventAppRoleData.md +6 -6
  95. package/docs/api/interfaces/ExportColumn.md +1 -1
  96. package/docs/api/interfaces/ExportOptions.md +1 -1
  97. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  98. package/docs/api/interfaces/FileMetadata.md +1 -1
  99. package/docs/api/interfaces/FileReference.md +1 -1
  100. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  101. package/docs/api/interfaces/FileUploadOptions.md +24 -8
  102. package/docs/api/interfaces/FileUploadProps.md +24 -13
  103. package/docs/api/interfaces/FooterProps.md +1 -1
  104. package/docs/api/interfaces/FormFieldProps.md +1 -1
  105. package/docs/api/interfaces/FormProps.md +1 -1
  106. package/docs/api/interfaces/GrantEventAppRoleParams.md +9 -9
  107. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  108. package/docs/api/interfaces/InputProps.md +1 -1
  109. package/docs/api/interfaces/LabelProps.md +1 -1
  110. package/docs/api/interfaces/LoggerConfig.md +62 -0
  111. package/docs/api/interfaces/LoginFormProps.md +1 -1
  112. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  113. package/docs/api/interfaces/NavigationContextType.md +1 -1
  114. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  115. package/docs/api/interfaces/NavigationItem.md +1 -1
  116. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  117. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  118. package/docs/api/interfaces/Organisation.md +1 -1
  119. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  120. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  121. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  122. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  123. package/docs/api/interfaces/PaceAppLayoutProps.md +36 -23
  124. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  125. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  126. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  127. package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
  128. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  129. package/docs/api/interfaces/PaletteData.md +1 -1
  130. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  131. package/docs/api/interfaces/ProgressProps.md +1 -1
  132. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  133. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  134. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  135. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  136. package/docs/api/interfaces/QuickFix.md +52 -0
  137. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  138. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  139. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  140. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  141. package/docs/api/interfaces/RBACConfig.md +4 -4
  142. package/docs/api/interfaces/RBACContext.md +1 -1
  143. package/docs/api/interfaces/RBACLogger.md +1 -1
  144. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  145. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  146. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  147. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  148. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  149. package/docs/api/interfaces/RBACResult.md +1 -1
  150. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  151. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  152. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  153. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  154. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  155. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  156. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  157. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  158. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  159. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  160. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  161. package/docs/api/interfaces/RevokeEventAppRoleParams.md +7 -7
  162. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  163. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  164. package/docs/api/interfaces/RoleManagementResult.md +5 -5
  165. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  166. package/docs/api/interfaces/RouteConfig.md +1 -1
  167. package/docs/api/interfaces/RuntimeComplianceResult.md +55 -0
  168. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  169. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  170. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  171. package/docs/api/interfaces/SetupIssue.md +41 -0
  172. package/docs/api/interfaces/StorageConfig.md +1 -1
  173. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  174. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  175. package/docs/api/interfaces/StorageListOptions.md +1 -1
  176. package/docs/api/interfaces/StorageListResult.md +1 -1
  177. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  178. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  179. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  180. package/docs/api/interfaces/StyleImport.md +1 -1
  181. package/docs/api/interfaces/SwitchProps.md +1 -1
  182. package/docs/api/interfaces/TabsContentProps.md +1 -1
  183. package/docs/api/interfaces/TabsListProps.md +1 -1
  184. package/docs/api/interfaces/TabsProps.md +1 -1
  185. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  186. package/docs/api/interfaces/TextareaProps.md +1 -1
  187. package/docs/api/interfaces/ToastActionElement.md +1 -1
  188. package/docs/api/interfaces/ToastProps.md +1 -1
  189. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  190. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  191. package/docs/api/interfaces/UseFormDialogOptions.md +62 -0
  192. package/docs/api/interfaces/UseFormDialogReturn.md +117 -0
  193. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  194. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  195. package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
  196. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  197. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  198. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  199. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  200. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  201. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  202. package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
  203. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  204. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  205. package/docs/api/interfaces/UserEventAccess.md +1 -1
  206. package/docs/api/interfaces/UserMenuProps.md +1 -1
  207. package/docs/api/interfaces/UserProfile.md +1 -1
  208. package/docs/api/modules.md +738 -42
  209. package/docs/api-reference/hooks.md +111 -0
  210. package/docs/api-reference/rpc-functions.md +1 -1
  211. package/docs/api-reference/utilities.md +184 -0
  212. package/docs/getting-started/installation-guide.md +75 -16
  213. package/docs/getting-started/quick-start.md +61 -11
  214. package/docs/implementation-guides/authentication.md +88 -12
  215. package/docs/implementation-guides/file-reference-system.md +2 -1
  216. package/docs/implementation-guides/file-upload-storage.md +21 -0
  217. package/docs/rbac/README.md +1 -0
  218. package/docs/rbac/compliance/compliance-guide.md +544 -0
  219. package/docs/rbac/getting-started.md +158 -33
  220. package/docs/standards/pace-core-compliance.md +432 -0
  221. package/eslint-config-pace-core.cjs +93 -0
  222. package/package.json +15 -3
  223. package/scripts/analyze-bundle.js +232 -0
  224. package/scripts/build-css.js +56 -0
  225. package/scripts/build-docs-incremental.js +1015 -0
  226. package/scripts/check-pace-core-compliance.cjs +2353 -0
  227. package/scripts/generate-docs.js +157 -0
  228. package/scripts/setup-build-cache.js +73 -0
  229. package/scripts/utils/command-runner.js +131 -0
  230. package/scripts/utils/env.js +33 -0
  231. package/scripts/utils/index.js +10 -0
  232. package/scripts/utils/logger.js +88 -0
  233. package/scripts/utils/path-helpers.js +37 -0
  234. package/scripts/validate-formats.js +133 -0
  235. package/scripts/validate-master.js +155 -0
  236. package/scripts/validate-pre-publish.js +140 -0
  237. package/scripts/validate-theme.js +142 -0
  238. package/src/components/Calendar/Calendar.tsx +8 -1
  239. package/src/components/Card/Card.tsx +47 -8
  240. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +314 -0
  241. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +126 -0
  242. package/src/components/DatePickerWithTimezone/README.md +135 -0
  243. package/src/components/DatePickerWithTimezone/index.ts +10 -0
  244. package/src/components/DateTimeField/DateTimeField.test.tsx +358 -0
  245. package/src/components/DateTimeField/DateTimeField.tsx +232 -0
  246. package/src/components/DateTimeField/README.md +148 -0
  247. package/src/components/DateTimeField/index.ts +10 -0
  248. package/src/components/FileUpload/FileUpload.tsx +3 -0
  249. package/src/components/Header/Header.test.tsx +47 -18
  250. package/src/components/Header/Header.tsx +24 -6
  251. package/src/components/PaceAppLayout/PaceAppLayout.tsx +29 -20
  252. package/src/components/PaceAppLayout/README.md +9 -0
  253. package/src/components/PaceLoginPage/PaceLoginPage.tsx +1 -1
  254. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +37 -8
  255. package/src/components/ProtectedRoute/ProtectedRoute.tsx +12 -4
  256. package/src/components/index.ts +8 -0
  257. package/src/eslint-rules/pace-core-compliance.cjs +406 -0
  258. package/src/eslint-rules/pace-core-compliance.js +640 -0
  259. package/src/hooks/__tests__/useFormDialog.test.ts +478 -0
  260. package/src/hooks/index.ts +2 -0
  261. package/src/hooks/useFileReference.test.ts +1 -0
  262. package/src/hooks/useFormDialog.ts +147 -0
  263. package/src/index.ts +27 -0
  264. package/src/providers/services/OrganisationServiceProvider.tsx +6 -5
  265. package/src/providers/services/UnifiedAuthProvider.tsx +24 -3
  266. package/src/rbac/__tests__/scenarios.user-role.test.tsx +3 -0
  267. package/src/rbac/compliance/database-validator.ts +165 -0
  268. package/src/rbac/compliance/index.ts +38 -0
  269. package/src/rbac/compliance/quick-fix-suggestions.ts +209 -0
  270. package/src/rbac/compliance/runtime-compliance.ts +77 -0
  271. package/src/rbac/compliance/setup-validator.ts +131 -0
  272. package/src/rbac/components/PagePermissionGuard.tsx +8 -64
  273. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +35 -21
  274. package/src/rbac/docs/event-based-apps.md +285 -0
  275. package/src/rbac/errors.ts +11 -0
  276. package/src/rbac/hooks/useRoleManagement.ts +292 -12
  277. package/src/rbac/index.ts +30 -0
  278. package/src/services/OrganisationService.ts +4 -0
  279. package/src/types/file-reference.ts +6 -0
  280. package/src/utils/__tests__/timezone.test.ts +345 -0
  281. package/src/utils/file-reference/__tests__/file-reference.test.ts +2 -0
  282. package/src/utils/file-reference/index.ts +1 -0
  283. package/src/utils/formatting/formatDateTimeTimezone.test.ts +167 -0
  284. package/src/utils/formatting/formatting.ts +179 -0
  285. package/src/utils/index.ts +27 -1
  286. package/src/utils/location/index.ts +16 -0
  287. package/src/utils/location/location.test.ts +286 -0
  288. package/src/utils/location/location.ts +175 -0
  289. package/src/utils/timezone/index.ts +17 -0
  290. package/src/utils/timezone/timezone.test.ts +349 -0
  291. package/src/utils/timezone/timezone.ts +281 -0
  292. package/dist/chunk-CSOFYHAG.js.map +0 -1
  293. package/dist/chunk-FUEYYMX5.js.map +0 -1
  294. package/dist/chunk-HKIT6O7W.js +0 -198
  295. package/dist/chunk-HKIT6O7W.js.map +0 -1
  296. package/dist/chunk-KUEN3HFB.js +0 -94
  297. package/dist/chunk-KUEN3HFB.js.map +0 -1
  298. package/dist/chunk-M7W4CP3M.js.map +0 -1
  299. package/dist/chunk-PWAHJW4G.js.map +0 -1
  300. package/dist/chunk-QETLRQI6.js.map +0 -1
  301. package/dist/chunk-UHNYIBXL.js.map +0 -1
  302. package/dist/formatting-5wETwiGF.d.ts +0 -162
  303. /package/dist/{DataTable-QAB34V6K.js.map → DataTable-IX2NBUTP.js.map} +0 -0
  304. /package/dist/{UnifiedAuthProvider-7F6T4B6K.js.map → UnifiedAuthProvider-A4BCQRJY.js.map} +0 -0
  305. /package/dist/{api-ROMBCNKU.js.map → api-BMFCXVQX.js.map} +0 -0
  306. /package/dist/{chunk-W22JP75J.js.map → chunk-STTZQK2I.js.map} +0 -0
  307. /package/dist/{chunk-QCDXODCA.js.map → chunk-XAUHJD3L.js.map} +0 -0
@@ -475,14 +475,15 @@ const files = await service.listFileReferences('pace_person', personId, orgId);
475
475
 
476
476
  ```sql
477
477
  -- Create file reference (replaces insert_file_reference)
478
+ -- Requires page context for context-aware permission checks
478
479
  SELECT data_file_reference_create(
479
480
  p_table_name := 'pace_person',
480
481
  p_record_id := 'person-uuid',
481
482
  p_file_path := 'org-123/profile_photos/file.jpg',
482
483
  p_organisation_id := 'org-uuid',
483
484
  p_app_id := 'app-uuid',
485
+ p_page_context := 'configuration',
484
486
  p_file_metadata := '{"fileName": "photo.jpg"}'::jsonb,
485
- p_category := 'profile_photos',
486
487
  p_is_public := false
487
488
  );
488
489
 
@@ -48,6 +48,7 @@ function MyFileUpload() {
48
48
  organisation_id="org-123"
49
49
  // app_id auto-resolved from app name
50
50
  category={FileCategory.GENERAL_DOCUMENTS}
51
+ pageContext="configuration"
51
52
  accept=".pdf,.doc,.docx"
52
53
  maxSize={5 * 1024 * 1024} // 5MB
53
54
  showProgress={true}
@@ -127,6 +128,7 @@ interface FileUploadProps {
127
128
  organisation_id: string;
128
129
  app_id?: string; // Optional - will be resolved from app name if not provided
129
130
  category: FileCategory;
131
+ pageContext: string; // The page context where the file upload occurs (e.g., 'configuration', 'forms', 'applications')
130
132
  accept?: string;
131
133
  maxSize?: number;
132
134
  multiple?: boolean;
@@ -152,6 +154,7 @@ interface FileUploadProps {
152
154
  record_id="person-123"
153
155
  organisation_id={organisationId}
154
156
  category={FileCategory.PROFILE_PHOTOS}
157
+ pageContext="configuration"
155
158
  accept="image/*"
156
159
  maxSize={2 * 1024 * 1024} // 2MB
157
160
  onUploadSuccess={(result) => console.log('Uploaded:', result.file_reference)}
@@ -168,6 +171,7 @@ interface FileUploadProps {
168
171
  record_id="person-123"
169
172
  organisation_id={organisationId}
170
173
  category={FileCategory.GENERAL_DOCUMENTS}
174
+ pageContext="forms"
171
175
  multiple={true}
172
176
  accept=".pdf,.doc,.docx"
173
177
  showProgress={true}
@@ -197,6 +201,23 @@ interface FileUploadProps {
197
201
  </FileUpload>
198
202
  ```
199
203
 
204
+ #### Page Context and Permissions
205
+
206
+ The `pageContext` parameter enables context-aware permission checks for file uploads. Instead of requiring a generic `'create:files'` permission on a `'files'` page, the system checks permissions based on the actual page where the upload occurs.
207
+
208
+ **Permission Check Behavior:**
209
+ - The system checks for `'create:page.{pageContext}'` permission first
210
+ - If that permission doesn't exist, it checks for `'update:page.{pageContext}'` permission
211
+ - The user needs at least one of these permissions to upload files
212
+ - This ensures file uploads are controlled by the same permissions as the page where they occur
213
+
214
+ **Example Use Cases:**
215
+ - Event logo uploads on the `'configuration'` page require `'create:page.configuration'` or `'update:page.configuration'` permission
216
+ - Form document uploads on the `'forms'` page require `'create:page.forms'` or `'update:page.forms'` permission
217
+ - Application file uploads on the `'applications'` page require `'create:page.applications'` or `'update:page.applications'` permission
218
+
219
+ **Important:** The `pageContext` must match a page defined in your RBAC system (`rbac_app_pages` table) for the permission checks to work correctly.
220
+
200
221
  ### FileDisplay
201
222
 
202
223
  A component for displaying and managing files associated with database records.
@@ -66,6 +66,7 @@ function MyComponent() {
66
66
  - **[Event-Based Apps](./event-based-apps.md)** - Get up and running in 10 minutes (foolproof guide for event-based apps)
67
67
  - **[API Reference](./api-reference.md)** - Complete API documentation
68
68
  - **[Troubleshooting](./troubleshooting.md)** - Common issues and solutions
69
+ - **[Compliance Guide](./compliance/compliance-guide.md)** - Ensuring proper RBAC/auth setup and usage
69
70
  - **[Examples](./examples.md)** - Practical usage examples
70
71
  - **[Advanced Patterns](./advanced-patterns.md)** - Complex scenarios and optimizations
71
72
 
@@ -0,0 +1,544 @@
1
+ # RBAC/Auth Compliance Guide
2
+
3
+ > **📚 RBAC Compliance** | [← Back to RBAC Documentation](../README.md) | [Troubleshooting](./troubleshooting-compliance.md) | [Migrating Custom Auth](./migrating-custom-auth.md)
4
+
5
+ This guide explains how to achieve RBAC/auth compliance in your pace app to ensure proper security and consistent usage of pace-core.
6
+
7
+ ## Overview
8
+
9
+ The RBAC/auth compliance system ensures that:
10
+ - All auth/rbac/permission functionality uses pace-core exclusively
11
+ - RBAC system is properly initialized
12
+ - All pages are protected with PagePermissionGuard
13
+ - Supabase configuration is centralized
14
+ - No custom auth/rbac code exists
15
+
16
+ ## Compliance Checks
17
+
18
+ The compliance system checks for:
19
+
20
+ ### 1. Custom Auth/RBAC Code
21
+
22
+ **What it checks:**
23
+ - Custom auth hooks (useAuth, useLogin, useLogout, etc.)
24
+ - Custom RBAC components (PermissionGuard, AuthGuard, etc.)
25
+ - Custom permission utilities (checkPermission, hasAccess, etc.)
26
+
27
+ **How to fix:**
28
+ - Remove custom implementations
29
+ - Import equivalent from `@jmruthers/pace-core` or `@jmruthers/pace-core/rbac`
30
+ - Update all usages
31
+
32
+ See [Migrating Custom Auth](./migrating-custom-auth.md) for detailed migration steps.
33
+
34
+ ### 2. Duplicate Supabase Configuration
35
+
36
+ **What it checks:**
37
+ - Multiple `createClient` calls
38
+ - Supabase environment variables in multiple files
39
+
40
+ **How to fix:**
41
+ - Create a single `supabase.ts` file
42
+ - Export the client instance
43
+ - Import from the shared location everywhere
44
+
45
+ ### 3. Unprotected Pages
46
+
47
+ **What it checks:**
48
+ - Routes without PagePermissionGuard
49
+ - Pages without permission checks
50
+
51
+ **How to fix:**
52
+ - Wrap all routes with PagePermissionGuard
53
+ - Set `pageName` and `operation` props
54
+ - Ensure pages exist in `rbac_app_pages` table
55
+
56
+ ### 4. Direct Supabase Auth Usage
57
+
58
+ **What it checks:**
59
+ - Direct calls to `supabase.auth.signIn`, `supabase.auth.signUp`, etc.
60
+
61
+ **How to fix:**
62
+ - Use `useUnifiedAuth` hook from pace-core
63
+ - Use `UnifiedAuthProvider` to wrap your app
64
+ - Replace all direct auth calls with pace-core methods
65
+
66
+ ### 5. Provider Setup Issues
67
+
68
+ **What it checks:**
69
+ - Missing `UnifiedAuthProvider` or `OrganisationProvider`
70
+ - Incorrect provider nesting order
71
+ - Providers placed in wrong locations
72
+
73
+ **How to fix:**
74
+ - Ensure correct nesting: `QueryClientProvider` → `BrowserRouter` → `UnifiedAuthProvider` → `OrganisationProvider` → `App`
75
+ - Place providers in `main.tsx` or `App.tsx` entry file
76
+ - See [Provider Setup](#provider-setup) section below
77
+
78
+ ### 6. Vite Configuration Issues
79
+
80
+ **What it checks:**
81
+ - `@jmruthers/pace-core` in `optimizeDeps.include` (should be excluded)
82
+ - Missing `@jmruthers/pace-core` in `optimizeDeps.exclude`
83
+ - Missing `react-router-dom` in `resolve.dedupe`
84
+
85
+ **How to fix:**
86
+ - Add `@jmruthers/pace-core` to `optimizeDeps.exclude`
87
+ - Remove `@jmruthers/pace-core` from `optimizeDeps.include`
88
+ - Add `react-router-dom` to `resolve.dedupe`
89
+ - See [Vite Configuration](#vite-configuration) section below
90
+
91
+ ### 7. Router Setup Issues
92
+
93
+ **What it checks:**
94
+ - Missing `BrowserRouter`
95
+ - `BrowserRouter` placed incorrectly (inside `UnifiedAuthProvider` instead of wrapping it)
96
+ - `Routes` used without `BrowserRouter`
97
+
98
+ **How to fix:**
99
+ - Wrap app with `BrowserRouter` from `react-router-dom`
100
+ - Ensure `BrowserRouter` wraps `UnifiedAuthProvider` (not the other way around)
101
+ - See [Router Setup](#router-setup) section below
102
+
103
+ ## Running Compliance Checks
104
+
105
+ ### Static Analysis
106
+
107
+ Run the compliance check script:
108
+
109
+ ```bash
110
+ npm run check:pace-core
111
+ ```
112
+
113
+ This will scan your codebase and report:
114
+ - Custom auth/rbac code
115
+ - Duplicate configurations
116
+ - Unprotected pages
117
+ - Direct Supabase auth usage
118
+ - Provider setup issues
119
+ - Vite configuration problems
120
+ - Router setup issues
121
+
122
+ ### ESLint Rules
123
+
124
+ The compliance system includes ESLint rules that run during development:
125
+
126
+ - `no-custom-auth-code` - Disallows custom auth/rbac implementations
127
+ - `no-duplicate-supabase-config` - Disallows multiple Supabase configurations
128
+ - `require-page-permission-guard` - Requires PagePermissionGuard on routes
129
+ - `no-direct-supabase-auth` - Disallows direct Supabase auth usage
130
+
131
+ ### Runtime Validation
132
+
133
+ Check runtime compliance programmatically:
134
+
135
+ ```typescript
136
+ import { checkRuntimeCompliance } from '@jmruthers/pace-core/rbac';
137
+
138
+ const result = checkRuntimeCompliance();
139
+ if (!result.setup.isCompliant) {
140
+ console.warn('RBAC setup issues:', result.setup.issues);
141
+ }
142
+ ```
143
+
144
+ ## Achieving Compliance
145
+
146
+ ### Step 1: Initialize RBAC
147
+
148
+ ```typescript
149
+ // main.tsx or App.tsx
150
+ import { setupRBAC } from '@jmruthers/pace-core/rbac';
151
+ import { createClient } from '@supabase/supabase-js';
152
+
153
+ const supabase = createClient(
154
+ import.meta.env.VITE_SUPABASE_URL,
155
+ import.meta.env.VITE_SUPABASE_ANON_KEY
156
+ );
157
+
158
+ // ⚠️ REQUIRED: Call setupRBAC before rendering
159
+ setupRBAC(supabase);
160
+ ```
161
+
162
+ ### Step 2: Set Up Providers
163
+
164
+ **⚠️ CRITICAL: Provider nesting order matters!**
165
+
166
+ The correct nesting order is:
167
+ 1. `QueryClientProvider` (outermost)
168
+ 2. `BrowserRouter`
169
+ 3. `UnifiedAuthProvider`
170
+ 4. `OrganisationProvider`
171
+ 5. `App` (innermost)
172
+
173
+ ```tsx
174
+ // main.tsx - Correct setup
175
+ import { BrowserRouter } from 'react-router-dom';
176
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
177
+ import { UnifiedAuthProvider, OrganisationProvider } from '@jmruthers/pace-core';
178
+
179
+ const queryClient = new QueryClient();
180
+
181
+ createRoot(document.getElementById("root")!).render(
182
+ <QueryClientProvider client={queryClient}>
183
+ <BrowserRouter>
184
+ <UnifiedAuthProvider supabaseClient={supabase} appName={APP_NAME}>
185
+ <OrganisationProvider>
186
+ <App />
187
+ </OrganisationProvider>
188
+ </UnifiedAuthProvider>
189
+ </BrowserRouter>
190
+ </QueryClientProvider>
191
+ );
192
+ ```
193
+
194
+ **Common mistakes to avoid:**
195
+ - ❌ `BrowserRouter` inside `UnifiedAuthProvider` (causes Router context errors)
196
+ - ❌ `UnifiedAuthProvider` wrapping `BrowserRouter` (causes context errors)
197
+ - ❌ Missing `BrowserRouter` (causes `useNavigate` errors)
198
+
199
+ ### Step 3: Protect All Pages
200
+
201
+ ```tsx
202
+ // pages/Dashboard.tsx
203
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
204
+
205
+ function Dashboard() {
206
+ return (
207
+ <PagePermissionGuard pageName="dashboard" operation="read">
208
+ <DashboardContent />
209
+ </PagePermissionGuard>
210
+ );
211
+ }
212
+ ```
213
+
214
+ ### Step 4: Use pace-core Auth
215
+
216
+ ```tsx
217
+ // components/Login.tsx
218
+ import { useUnifiedAuth } from '@jmruthers/pace-core';
219
+
220
+ function Login() {
221
+ const { signIn } = useUnifiedAuth();
222
+
223
+ const handleLogin = async () => {
224
+ await signIn({ email, password });
225
+ };
226
+
227
+ return <button onClick={handleLogin}>Login</button>;
228
+ }
229
+ ```
230
+
231
+ ### Step 5: Configure Vite
232
+
233
+ **⚠️ CRITICAL: Vite configuration prevents React context mismatches!**
234
+
235
+ Add to your `vite.config.ts`:
236
+
237
+ ```typescript
238
+ import { defineConfig } from 'vite';
239
+
240
+ export default defineConfig({
241
+ resolve: {
242
+ dedupe: ['react', 'react-dom', 'react-router-dom']
243
+ },
244
+ optimizeDeps: {
245
+ include: [
246
+ 'react',
247
+ 'react-dom',
248
+ 'react/jsx-runtime'
249
+ ],
250
+ // CRITICAL: Exclude pace-core to prevent React context mismatches
251
+ exclude: ['@jmruthers/pace-core', 'react-router-dom']
252
+ }
253
+ });
254
+ ```
255
+
256
+ **Why this matters:**
257
+ - Pre-bundling `@jmruthers/pace-core` creates separate React instances
258
+ - This causes "useUnifiedAuth must be used within a UnifiedAuthProvider" errors
259
+ - Excluding it ensures pace-core uses the same React instance as your app
260
+
261
+ ### Step 6: Centralize Supabase Config
262
+
263
+ ```typescript
264
+ // src/lib/supabase.ts
265
+ import { createClient } from '@supabase/supabase-js';
266
+
267
+ export const supabase = createClient(
268
+ import.meta.env.VITE_SUPABASE_URL,
269
+ import.meta.env.VITE_SUPABASE_ANON_KEY
270
+ );
271
+ ```
272
+
273
+ ## Database Configuration
274
+
275
+ Ensure your database is properly configured:
276
+
277
+ 1. **App Registration**: App must exist in `rbac_apps` table
278
+ 2. **Pages**: All pages must be registered in `rbac_app_pages` table
279
+ 3. **Permissions**: Permissions must be configured in `rbac_page_permissions` table
280
+ 4. **User Roles**: Users must have roles in `rbac_organisation_roles` table
281
+
282
+ See [RBAC Quick Start](../quick-start.md) for database setup instructions.
283
+
284
+ ## Quick Fixes
285
+
286
+ The compliance system provides quick fix suggestions:
287
+
288
+ ```typescript
289
+ import { getQuickFixes } from '@jmruthers/pace-core/rbac';
290
+
291
+ const fixes = getQuickFixes('custom-auth-code', { name: 'useAuth', type: 'hook' });
292
+ fixes.forEach(fix => {
293
+ console.log(fix.suggestion);
294
+ console.log(fix.codeExample);
295
+ });
296
+ ```
297
+
298
+ ## CI/CD Integration
299
+
300
+ Add compliance checks to your CI/CD pipeline:
301
+
302
+ ```yaml
303
+ # .github/workflows/compliance.yml
304
+ - name: Check pace-core compliance
305
+ run: npm run check:pace-core
306
+ ```
307
+
308
+ The script exits with code 1 if compliance issues are found, causing the build to fail.
309
+
310
+ ## Troubleshooting Common Issues
311
+
312
+ ### Provider Setup Issues
313
+
314
+ **Issue:** "useUnifiedAuth must be used within a UnifiedAuthProvider" error
315
+
316
+ **Possible causes:**
317
+ 1. `UnifiedAuthProvider` is missing or not wrapping your app
318
+ 2. `BrowserRouter` is inside `UnifiedAuthProvider` (wrong nesting)
319
+ 3. Vite is pre-bundling `@jmruthers/pace-core` (React context mismatch)
320
+
321
+ **Solution:**
322
+ 1. **Check provider nesting** in `main.tsx`:
323
+ ```tsx
324
+ // ✅ CORRECT
325
+ <QueryClientProvider>
326
+ <BrowserRouter>
327
+ <UnifiedAuthProvider>
328
+ <OrganisationProvider>
329
+ <App />
330
+ </OrganisationProvider>
331
+ </UnifiedAuthProvider>
332
+ </BrowserRouter>
333
+ </QueryClientProvider>
334
+
335
+ // ❌ WRONG - BrowserRouter inside UnifiedAuthProvider
336
+ <UnifiedAuthProvider>
337
+ <BrowserRouter>
338
+ <App />
339
+ </BrowserRouter>
340
+ </UnifiedAuthProvider>
341
+ ```
342
+
343
+ 2. **Check Vite config** - ensure `@jmruthers/pace-core` is in `optimizeDeps.exclude`:
344
+ ```typescript
345
+ optimizeDeps: {
346
+ exclude: ['@jmruthers/pace-core', 'react-router-dom']
347
+ }
348
+ ```
349
+
350
+ 3. **Clear Vite cache** and restart dev server:
351
+ ```bash
352
+ rm -rf node_modules/.vite
353
+ npm run dev
354
+ ```
355
+
356
+ ### Router Context Issues
357
+
358
+ **Issue:** "useNavigate() may be used only in the context of a <Router> component" error
359
+
360
+ **Possible causes:**
361
+ 1. Missing `BrowserRouter`
362
+ 2. `BrowserRouter` placed incorrectly
363
+ 3. `react-router-dom` being pre-bundled by Vite
364
+
365
+ **Solution:**
366
+ 1. **Add BrowserRouter** wrapping your app:
367
+ ```tsx
368
+ import { BrowserRouter } from 'react-router-dom';
369
+
370
+ <BrowserRouter>
371
+ <UnifiedAuthProvider>
372
+ <App />
373
+ </UnifiedAuthProvider>
374
+ </BrowserRouter>
375
+ ```
376
+
377
+ 2. **Update Vite config**:
378
+ ```typescript
379
+ resolve: {
380
+ dedupe: ['react', 'react-dom', 'react-router-dom']
381
+ },
382
+ optimizeDeps: {
383
+ exclude: ['react-router-dom']
384
+ }
385
+ ```
386
+
387
+ 3. **Clear Vite cache** and restart
388
+
389
+ ### Vite Configuration Issues
390
+
391
+ **Issue:** React context mismatch errors, components can't find providers
392
+
393
+ **Possible causes:**
394
+ 1. `@jmruthers/pace-core` is being pre-bundled by Vite
395
+ 2. Multiple React instances in the bundle
396
+
397
+ **Solution:**
398
+ 1. **Exclude pace-core from pre-bundling**:
399
+ ```typescript
400
+ optimizeDeps: {
401
+ exclude: ['@jmruthers/pace-core']
402
+ }
403
+ ```
404
+
405
+ 2. **Dedupe React dependencies**:
406
+ ```typescript
407
+ resolve: {
408
+ dedupe: ['react', 'react-dom', 'react-router-dom']
409
+ }
410
+ ```
411
+
412
+ 3. **Clear Vite cache**:
413
+ ```bash
414
+ rm -rf node_modules/.vite
415
+ ```
416
+
417
+ ### Custom Auth/RBAC Code Detected
418
+
419
+ **Issue:** Custom `useAuth` hook or `PermissionGuard` component found
420
+
421
+ **Solution:**
422
+ 1. Remove your custom implementation
423
+ 2. Import from pace-core:
424
+ ```typescript
425
+ import { useUnifiedAuth } from '@jmruthers/pace-core';
426
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
427
+ ```
428
+ 3. Update all usages - see [Migration Examples](#migrating-from-custom-code) below
429
+
430
+ ### Duplicate Supabase Configuration
431
+
432
+ **Issue:** Multiple `createClient` calls found
433
+
434
+ **Solution:**
435
+ 1. Create a single `supabase.ts` file:
436
+ ```typescript
437
+ // src/lib/supabase.ts
438
+ export const supabase = createClient(url, key);
439
+ ```
440
+ 2. Remove all other `createClient` calls
441
+ 3. Import from the shared location everywhere
442
+
443
+ ### Unprotected Pages
444
+
445
+ **Issue:** Route without PagePermissionGuard
446
+
447
+ **Solution:**
448
+ 1. Wrap all routes with PagePermissionGuard:
449
+ ```tsx
450
+ <PagePermissionGuard pageName="dashboard" operation="read">
451
+ <Dashboard />
452
+ </PagePermissionGuard>
453
+ ```
454
+ 2. Ensure pages exist in `rbac_app_pages` table
455
+
456
+ ### Direct Supabase Auth Usage
457
+
458
+ **Issue:** Direct `supabase.auth` calls detected
459
+
460
+ **Solution:**
461
+ 1. Use `useUnifiedAuth` hook instead:
462
+ ```typescript
463
+ const { signIn } = useUnifiedAuth();
464
+ await signIn({ email, password });
465
+ ```
466
+ 2. Ensure `UnifiedAuthProvider` wraps your app
467
+
468
+ ### RBAC Not Initialized
469
+
470
+ **Issue:** `setupRBAC()` not called
471
+
472
+ **Solution:**
473
+ ```typescript
474
+ // main.tsx - Must be called before rendering
475
+ import { setupRBAC } from '@jmruthers/pace-core/rbac';
476
+ setupRBAC(supabase);
477
+ ```
478
+
479
+ ## Migrating from Custom Code
480
+
481
+ ### Migrating `useAuth` Hook
482
+
483
+ **Before:**
484
+ ```typescript
485
+ // src/hooks/useAuth.ts
486
+ export function useAuth() {
487
+ const [user, setUser] = useState(null);
488
+ // ... custom logic
489
+ }
490
+ ```
491
+
492
+ **After:**
493
+ ```typescript
494
+ import { useUnifiedAuth } from '@jmruthers/pace-core';
495
+ const { user } = useUnifiedAuth();
496
+ ```
497
+
498
+ ### Migrating `PermissionGuard` Component
499
+
500
+ **Before:**
501
+ ```tsx
502
+ <PermissionGuard permission="read:users">
503
+ <UsersPage />
504
+ </PermissionGuard>
505
+ ```
506
+
507
+ **After:**
508
+ ```tsx
509
+ <PagePermissionGuard pageName="users" operation="read">
510
+ <UsersPage />
511
+ </PagePermissionGuard>
512
+ ```
513
+
514
+ ### Migrating `checkPermission` Utility
515
+
516
+ **Before:**
517
+ ```typescript
518
+ const hasAccess = checkPermission(user, 'read:users');
519
+ ```
520
+
521
+ **After:**
522
+ ```typescript
523
+ import { isPermitted } from '@jmruthers/pace-core/rbac';
524
+ const hasAccess = await isPermitted({
525
+ userId: user.id,
526
+ scope: { organisationId: org.id },
527
+ permission: 'read:page.users'
528
+ });
529
+ ```
530
+
531
+ ### Step-by-Step Migration Process
532
+
533
+ 1. **Audit:** Run `npm run check:pace-core` to find all custom code
534
+ 2. **Setup:** Ensure `setupRBAC()` is called and providers are configured
535
+ 3. **Migrate:** Replace custom code with pace-core equivalents one component at a time
536
+ 4. **Test:** Verify all auth flows and permission checks work
537
+ 5. **Clean:** Remove custom files and update all imports
538
+
539
+ ## Next Steps
540
+
541
+ - [RBAC Troubleshooting](../troubleshooting.md) - General RBAC issues
542
+ - [RBAC Quick Start](../quick-start.md) - Getting started with RBAC
543
+ - [RBAC API Reference](../api-reference.md) - Complete API documentation
544
+