@jmruthers/pace-core 0.5.181 → 0.5.182

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 (750) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +16 -2
  3. package/dist/{AuthService-DYuQPJj6.d.ts → AuthService-B-cd2MA4.d.ts} +9 -11
  4. package/dist/{DataTable-CWAZZcXC.d.ts → DataTable-Bz8ffqyA.d.ts} +1 -1
  5. package/dist/{DataTable-UA6CL4JI.js → DataTable-QAB34V6K.js} +14 -15
  6. package/dist/UnifiedAuthProvider-7F6T4B6K.js +13 -0
  7. package/dist/{UnifiedAuthProvider-DJxGTftH.d.ts → UnifiedAuthProvider-F86d7dSi.d.ts} +5 -6
  8. package/dist/{api-45XYYO2A.js → api-ROMBCNKU.js} +5 -5
  9. package/dist/{audit-64X3VJXB.js → audit-WRS3KJKI.js} +4 -4
  10. package/dist/auth-BZOJqrdd.d.ts +49 -0
  11. package/dist/{chunk-CX5M4ZAG.js → chunk-5DRSZLL2.js} +1 -1
  12. package/dist/chunk-5DRSZLL2.js.map +1 -0
  13. package/dist/{chunk-BESYRHQM.js → chunk-6C4YBBJM.js} +10 -7
  14. package/dist/chunk-6C4YBBJM.js.map +1 -0
  15. package/dist/{chunk-PLDDJCW6.js → chunk-7D4SUZUM.js} +2 -13
  16. package/dist/{chunk-HRO5HWN2.js → chunk-CSOFYHAG.js} +55 -162
  17. package/dist/chunk-CSOFYHAG.js.map +1 -0
  18. package/dist/{chunk-ANBQRTPX.js → chunk-E66EQZE6.js} +3 -5
  19. package/dist/{chunk-ANBQRTPX.js.map → chunk-E66EQZE6.js.map} +1 -1
  20. package/dist/{chunk-Q5QRDWKI.js → chunk-F2IMUDXZ.js} +4 -6
  21. package/dist/chunk-F2IMUDXZ.js.map +1 -0
  22. package/dist/{chunk-SBVILCCA.js → chunk-FSFQFJCU.js} +28 -6
  23. package/dist/chunk-FSFQFJCU.js.map +1 -0
  24. package/dist/chunk-FUEYYMX5.js +2296 -0
  25. package/dist/chunk-FUEYYMX5.js.map +1 -0
  26. package/dist/{chunk-FFKNH6U5.js → chunk-HKIT6O7W.js} +3 -5
  27. package/dist/{chunk-FFKNH6U5.js.map → chunk-HKIT6O7W.js.map} +1 -1
  28. package/dist/chunk-KQCRWDSA.js +1 -0
  29. package/dist/{chunk-S5OFRT4M.js → chunk-KUEN3HFB.js} +6 -6
  30. package/dist/chunk-KUEN3HFB.js.map +1 -0
  31. package/dist/chunk-LMC26NLJ.js +84 -0
  32. package/dist/chunk-LMC26NLJ.js.map +1 -0
  33. package/dist/{chunk-BVYWGZVV.js → chunk-M7W4CP3M.js} +52 -19
  34. package/dist/chunk-M7W4CP3M.js.map +1 -0
  35. package/dist/{chunk-HZLDFOE4.js → chunk-MI7HBHN3.js} +164 -243
  36. package/dist/chunk-MI7HBHN3.js.map +1 -0
  37. package/dist/{chunk-PPMP5J6T.js → chunk-PWAHJW4G.js} +180 -29
  38. package/dist/chunk-PWAHJW4G.js.map +1 -0
  39. package/dist/chunk-PWLANIRT.js +127 -0
  40. package/dist/{chunk-XDNLUEXI.js.map → chunk-PWLANIRT.js.map} +1 -1
  41. package/dist/chunk-QCDXODCA.js +75 -0
  42. package/dist/chunk-QCDXODCA.js.map +1 -0
  43. package/dist/{chunk-D7LCGMVS.js → chunk-QETLRQI6.js} +526 -887
  44. package/dist/chunk-QETLRQI6.js.map +1 -0
  45. package/dist/{chunk-5MT24GKJ.js → chunk-QUVSNGIP.js} +264 -262
  46. package/dist/chunk-QUVSNGIP.js.map +1 -0
  47. package/dist/chunk-QXHPKYJV.js +113 -0
  48. package/dist/chunk-QXHPKYJV.js.map +1 -0
  49. package/dist/{chunk-OWAG3GSU.js → chunk-R77UEZ4E.js} +11 -1
  50. package/dist/chunk-R77UEZ4E.js.map +1 -0
  51. package/dist/{chunk-ZYTYSTO5.js → chunk-RA3JUFMW.js} +314 -161
  52. package/dist/chunk-RA3JUFMW.js.map +1 -0
  53. package/dist/{chunk-ERISIBYU.js → chunk-SQGMNID3.js} +3 -8
  54. package/dist/chunk-SQGMNID3.js.map +1 -0
  55. package/dist/{chunk-XJ2HZOBU.js → chunk-UHNYIBXL.js} +1 -1
  56. package/dist/chunk-UHNYIBXL.js.map +1 -0
  57. package/{src/utils/secureStorage.ts → dist/chunk-VBXEHIUJ.js} +113 -88
  58. package/dist/{chunk-7QCC6MCP.js.map → chunk-VBXEHIUJ.js.map} +1 -1
  59. package/dist/{chunk-VZ4VDGTB.js → chunk-W22JP75J.js} +5 -13
  60. package/dist/{chunk-VZ4VDGTB.js.map → chunk-W22JP75J.js.map} +1 -1
  61. package/dist/components.d.ts +12 -93
  62. package/dist/components.js +23 -106
  63. package/dist/components.js.map +1 -1
  64. package/dist/core-CUElvH_C.d.ts +164 -0
  65. package/dist/database.generated-CBmg2950.d.ts +8284 -0
  66. package/dist/event-CW5YB_2p.d.ts +239 -0
  67. package/dist/{file-reference-C6Gkn77H.d.ts → file-reference-D06mEEWW.d.ts} +7 -5
  68. package/dist/functions-D_kgHktt.d.ts +208 -0
  69. package/dist/hooks.d.ts +54 -7
  70. package/dist/hooks.js +204 -17
  71. package/dist/hooks.js.map +1 -1
  72. package/dist/{EventLogo-B3V3otev.d.ts → index-Bl--n7-T.d.ts} +387 -397
  73. package/dist/index.d.ts +94 -261
  74. package/dist/index.js +314 -126
  75. package/dist/index.js.map +1 -1
  76. package/dist/providers.d.ts +7 -8
  77. package/dist/providers.js +6 -13
  78. package/dist/rbac/index.d.ts +171 -101
  79. package/dist/rbac/index.js +23 -17
  80. package/dist/styles/index.d.ts +1 -3
  81. package/dist/styles/index.js +2 -17
  82. package/dist/theming/runtime.js +3 -3
  83. package/dist/types-UU913iLA.d.ts +102 -0
  84. package/dist/{types-Dfz9dmVH.d.ts → types-_x1f4QBF.d.ts} +6 -6
  85. package/dist/types.d.ts +88 -227
  86. package/dist/types.js +64 -112
  87. package/dist/types.js.map +1 -1
  88. package/dist/{usePublicRouteParams-B7PabvuH.d.ts → usePublicRouteParams-JJczomYq.d.ts} +203 -6
  89. package/dist/utils.d.ts +299 -13
  90. package/dist/utils.js +481 -55
  91. package/dist/utils.js.map +1 -1
  92. package/dist/validation-643vUDZW.d.ts +177 -0
  93. package/docs/DOCUMENTATION_REVIEW_TRACKER.md +511 -0
  94. package/docs/README.md +9 -8
  95. package/docs/api/README.md +16 -2
  96. package/docs/api/classes/ColumnFactory.md +1 -1
  97. package/docs/api/classes/ErrorBoundary.md +1 -1
  98. package/docs/api/classes/InvalidScopeError.md +4 -4
  99. package/docs/api/classes/MissingUserContextError.md +4 -4
  100. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  101. package/docs/api/classes/PermissionDeniedError.md +4 -4
  102. package/docs/api/classes/RBACAuditManager.md +14 -14
  103. package/docs/api/classes/RBACCache.md +1 -1
  104. package/docs/api/classes/RBACEngine.md +2 -2
  105. package/docs/api/classes/RBACError.md +4 -4
  106. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  107. package/docs/api/classes/SecureSupabaseClient.md +29 -9
  108. package/docs/api/classes/StorageUtils.md +1 -1
  109. package/docs/api/enums/FileCategory.md +17 -17
  110. package/docs/api/enums/RBACErrorCode.md +228 -0
  111. package/docs/api/enums/RPCFunction.md +118 -0
  112. package/docs/api/interfaces/AggregateConfig.md +1 -1
  113. package/docs/api/interfaces/BadgeProps.md +1 -1
  114. package/docs/api/interfaces/ButtonProps.md +2 -2
  115. package/docs/api/interfaces/CalendarProps.md +1 -1
  116. package/docs/api/interfaces/CardProps.md +29 -3
  117. package/docs/api/interfaces/ColorPalette.md +1 -1
  118. package/docs/api/interfaces/ColorShade.md +1 -1
  119. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  120. package/docs/api/interfaces/DataRecord.md +1 -1
  121. package/docs/api/interfaces/DataTableAction.md +2 -2
  122. package/docs/api/interfaces/DataTableColumn.md +6 -6
  123. package/docs/api/interfaces/DataTableProps.md +1 -1
  124. package/docs/api/interfaces/DataTableToolbarButton.md +2 -2
  125. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  126. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  127. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  128. package/docs/api/interfaces/ExportColumn.md +5 -5
  129. package/docs/api/interfaces/ExportOptions.md +4 -4
  130. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  131. package/docs/api/interfaces/FileMetadata.md +13 -13
  132. package/docs/api/interfaces/FileReference.md +12 -12
  133. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  134. package/docs/api/interfaces/FileUploadOptions.md +10 -10
  135. package/docs/api/interfaces/FileUploadProps.md +19 -19
  136. package/docs/api/interfaces/FooterProps.md +1 -1
  137. package/docs/api/interfaces/FormFieldProps.md +166 -0
  138. package/docs/api/interfaces/FormProps.md +113 -0
  139. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  140. package/docs/api/interfaces/InactivityWarningModalProps.md +8 -8
  141. package/docs/api/interfaces/InputProps.md +2 -2
  142. package/docs/api/interfaces/LabelProps.md +8 -8
  143. package/docs/api/interfaces/LoginFormProps.md +1 -1
  144. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  145. package/docs/api/interfaces/NavigationContextType.md +1 -1
  146. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  147. package/docs/api/interfaces/NavigationItem.md +17 -73
  148. package/docs/api/interfaces/NavigationMenuProps.md +38 -53
  149. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  150. package/docs/api/interfaces/Organisation.md +13 -13
  151. package/docs/api/interfaces/OrganisationContextType.md +21 -21
  152. package/docs/api/interfaces/OrganisationMembership.md +15 -15
  153. package/docs/api/interfaces/OrganisationProviderProps.md +59 -2
  154. package/docs/api/interfaces/OrganisationSecurityError.md +5 -5
  155. package/docs/api/interfaces/PaceAppLayoutProps.md +26 -39
  156. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  157. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  158. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  159. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  160. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  161. package/docs/api/interfaces/PaletteData.md +1 -1
  162. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  163. package/docs/api/interfaces/ProgressProps.md +50 -0
  164. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  165. package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
  166. package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
  167. package/docs/api/interfaces/PublicPageLayoutProps.md +15 -15
  168. package/docs/api/interfaces/RBACAccessValidateParams.md +52 -0
  169. package/docs/api/interfaces/RBACAccessValidateResult.md +41 -0
  170. package/docs/api/interfaces/RBACAuditLogParams.md +85 -0
  171. package/docs/api/interfaces/RBACAuditLogResult.md +52 -0
  172. package/docs/api/interfaces/RBACConfig.md +2 -2
  173. package/docs/api/interfaces/RBACContext.md +52 -0
  174. package/docs/api/interfaces/RBACLogger.md +1 -1
  175. package/docs/api/interfaces/RBACPageAccessCheckParams.md +74 -0
  176. package/docs/api/interfaces/RBACPermissionCheckParams.md +74 -0
  177. package/docs/api/interfaces/RBACPermissionCheckResult.md +52 -0
  178. package/docs/api/interfaces/RBACPermissionsGetParams.md +63 -0
  179. package/docs/api/interfaces/RBACPermissionsGetResult.md +63 -0
  180. package/docs/api/interfaces/RBACResult.md +58 -0
  181. package/docs/api/interfaces/RBACRoleGrantParams.md +63 -0
  182. package/docs/api/interfaces/RBACRoleGrantResult.md +52 -0
  183. package/docs/api/interfaces/RBACRoleRevokeParams.md +63 -0
  184. package/docs/api/interfaces/RBACRoleRevokeResult.md +52 -0
  185. package/docs/api/interfaces/RBACRoleValidateParams.md +52 -0
  186. package/docs/api/interfaces/RBACRoleValidateResult.md +63 -0
  187. package/docs/api/interfaces/RBACRolesListParams.md +52 -0
  188. package/docs/api/interfaces/RBACRolesListResult.md +74 -0
  189. package/docs/api/interfaces/RBACSessionTrackParams.md +74 -0
  190. package/docs/api/interfaces/RBACSessionTrackResult.md +52 -0
  191. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  192. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  193. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  194. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  195. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  196. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  197. package/docs/api/interfaces/RouteConfig.md +1 -1
  198. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  199. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  200. package/docs/api/interfaces/SessionRestorationLoaderProps.md +15 -2
  201. package/docs/api/interfaces/StorageConfig.md +1 -1
  202. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  203. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  204. package/docs/api/interfaces/StorageListOptions.md +1 -1
  205. package/docs/api/interfaces/StorageListResult.md +1 -1
  206. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  207. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  208. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  209. package/docs/api/interfaces/StyleImport.md +1 -1
  210. package/docs/api/interfaces/SwitchProps.md +1 -1
  211. package/docs/api/interfaces/TabsContentProps.md +1 -1
  212. package/docs/api/interfaces/TabsListProps.md +1 -1
  213. package/docs/api/interfaces/TabsProps.md +1 -1
  214. package/docs/api/interfaces/TabsTriggerProps.md +43 -2
  215. package/docs/api/interfaces/TextareaProps.md +2 -2
  216. package/docs/api/interfaces/ToastActionElement.md +1 -1
  217. package/docs/api/interfaces/ToastProps.md +1 -1
  218. package/docs/api/interfaces/UnifiedAuthContextType.md +61 -61
  219. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  220. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  221. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  222. package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
  223. package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
  224. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  225. package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
  226. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  227. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  228. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  229. package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
  230. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  231. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  232. package/docs/api/interfaces/UserEventAccess.md +1 -1
  233. package/docs/api/interfaces/UserMenuProps.md +4 -4
  234. package/docs/api/interfaces/UserProfile.md +7 -7
  235. package/docs/api/modules.md +484 -462
  236. package/docs/api-reference/components.md +186 -15
  237. package/docs/api-reference/deprecated.md +376 -0
  238. package/docs/api-reference/hooks.md +149 -19
  239. package/docs/api-reference/providers.md +61 -6
  240. package/docs/api-reference/rpc-functions.md +397 -0
  241. package/docs/api-reference/types.md +135 -78
  242. package/docs/api-reference/utilities.md +51 -380
  243. package/docs/architecture/README.md +49 -3
  244. package/docs/architecture/database-schema-requirements.md +40 -3
  245. package/docs/architecture/rbac-security-architecture.md +41 -4
  246. package/docs/architecture/services.md +127 -42
  247. package/docs/best-practices/README.md +51 -5
  248. package/docs/best-practices/accessibility.md +32 -3
  249. package/docs/best-practices/common-patterns.md +50 -3
  250. package/docs/best-practices/deployment.md +50 -4
  251. package/docs/best-practices/performance.md +50 -3
  252. package/docs/best-practices/security.md +94 -41
  253. package/docs/best-practices/testing.md +33 -4
  254. package/docs/core-concepts/authentication.md +5 -5
  255. package/docs/core-concepts/events.md +3 -3
  256. package/docs/core-concepts/organisations.md +3 -3
  257. package/docs/core-concepts/permissions.md +3 -3
  258. package/docs/core-concepts/rbac-system.md +5 -5
  259. package/docs/documentation-index.md +30 -8
  260. package/docs/getting-started/documentation-index.md +1 -1
  261. package/docs/getting-started/examples/README.md +7 -5
  262. package/docs/getting-started/examples/basic-auth-app.md +3 -0
  263. package/docs/getting-started/examples/full-featured-app.md +5 -3
  264. package/docs/getting-started/faq.md +6 -6
  265. package/docs/getting-started/installation-guide.md +192 -13
  266. package/docs/getting-started/local-development.md +303 -0
  267. package/docs/getting-started/quick-reference.md +3 -3
  268. package/docs/getting-started/quick-start.md +517 -0
  269. package/docs/implementation-guides/app-layout.md +45 -3
  270. package/docs/implementation-guides/authentication.md +66 -7
  271. package/docs/implementation-guides/component-styling.md +53 -3
  272. package/docs/implementation-guides/data-tables.md +76 -7
  273. package/docs/implementation-guides/datatable-filtering.md +1 -2
  274. package/docs/implementation-guides/datatable-rbac-usage.md +0 -1
  275. package/docs/implementation-guides/dynamic-colors.md +155 -4
  276. package/docs/implementation-guides/file-reference-system.md +72 -3
  277. package/docs/implementation-guides/file-upload-storage.md +72 -3
  278. package/docs/implementation-guides/forms.md +53 -3
  279. package/docs/implementation-guides/inactivity-tracking.md +53 -3
  280. package/docs/implementation-guides/large-datasets.md +1 -1
  281. package/docs/implementation-guides/navigation.md +55 -5
  282. package/docs/implementation-guides/organisation-security.md +72 -3
  283. package/docs/implementation-guides/performance.md +57 -1
  284. package/docs/implementation-guides/permission-enforcement.md +81 -8
  285. package/docs/implementation-guides/public-pages.md +560 -14
  286. package/docs/migration/MIGRATION_GUIDE.md +409 -50
  287. package/docs/migration/README.md +37 -3
  288. package/docs/migration/organisation-context-timing-fix.md +39 -4
  289. package/docs/migration/quick-migration-guide.md +41 -5
  290. package/docs/migration/rbac-migration.md +59 -3
  291. package/docs/migration/service-architecture.md +77 -14
  292. package/docs/rbac/README.md +79 -3
  293. package/docs/rbac/advanced-patterns.md +47 -3
  294. package/docs/rbac/api-reference.md +77 -8
  295. package/docs/rbac/event-based-apps.md +50 -5
  296. package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
  297. package/docs/rbac/examples.md +39 -3
  298. package/docs/rbac/getting-started.md +63 -4
  299. package/docs/rbac/quick-start.md +57 -5
  300. package/docs/rbac/rbac-rls-integration.md +68 -6
  301. package/docs/rbac/super-admin-guide.md +47 -3
  302. package/docs/rbac/troubleshooting.md +3 -3
  303. package/docs/security/README.md +68 -3
  304. package/docs/security/checklist.md +50 -3
  305. package/docs/standards/01-architecture-standard.md +39 -0
  306. package/docs/standards/02-api-and-rpc-standard.md +39 -0
  307. package/docs/standards/03-component-standard.md +32 -0
  308. package/docs/standards/04-code-style-standard.md +32 -0
  309. package/docs/standards/05-security-standard.md +30 -0
  310. package/docs/standards/06-testing-and-docs-standard.md +29 -0
  311. package/docs/standards/README.md +35 -0
  312. package/docs/styles/README.md +89 -8
  313. package/docs/testing/README.md +175 -24
  314. package/docs/troubleshooting/README.md +50 -3
  315. package/docs/troubleshooting/common-issues.md +271 -5
  316. package/docs/troubleshooting/debugging.md +54 -1
  317. package/docs/troubleshooting/migration.md +54 -1
  318. package/docs/troubleshooting/organisation-context-setup.md +29 -3
  319. package/docs/troubleshooting/styling-issues.md +246 -4
  320. package/{src/components/DataTable/examples → examples/DataTable}/GroupingAggregationExample.tsx +1 -1
  321. package/examples/{components 2/DataTable/HierarchicalActionsExample.tsx → DataTable/HierarchicalActionsExample.tsx} +7 -6
  322. package/{src/components/DataTable/examples → examples/DataTable}/HierarchicalExample.tsx +8 -6
  323. package/examples/{components 2/DataTable/PerformanceExample.tsx → DataTable/PerformanceExample.tsx} +2 -2
  324. package/examples/{components 2/DataTable/index.ts → DataTable/index.ts} +1 -0
  325. package/{src/components/Dialog/examples → examples/Dialog}/HtmlDialogExample.tsx +3 -3
  326. package/examples/{components 2/Dialog/ScrollableDialogExample.tsx → Dialog/ScrollableDialogExample.tsx} +1 -1
  327. package/{src/components/Dialog/examples → examples/Dialog}/SmartDialogExample.tsx +1 -1
  328. package/examples/{components 2/Dialog/index.ts → Dialog/index.ts} +0 -3
  329. package/examples/{features/public-pages → PublicPages}/CorrectPublicPageImplementation.tsx +52 -17
  330. package/examples/{features/public-pages → PublicPages}/PublicEventPage.tsx +65 -35
  331. package/examples/{features/public-pages → PublicPages}/PublicPageApp.tsx +52 -18
  332. package/examples/{features/public-pages → PublicPages}/PublicPageUsageExample.tsx +28 -15
  333. package/examples/README.md +81 -33
  334. package/examples/index.ts +14 -12
  335. package/examples/{RBAC → rbac}/CompleteRBACExample.tsx +1 -1
  336. package/examples/{features/rbac → rbac}/EventBasedApp.tsx +4 -4
  337. package/examples/{features/rbac → rbac}/PermissionExample.tsx +5 -3
  338. package/package.json +21 -27
  339. package/src/__tests__/helpers/test-utils.tsx +29 -3
  340. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +7 -5
  341. package/src/components/Alert/Alert.test.tsx +2 -2
  342. package/src/components/Alert/Alert.tsx +4 -4
  343. package/src/components/Avatar/Avatar.test.tsx +17 -6
  344. package/src/components/Badge/Badge.test.tsx +1 -1
  345. package/src/components/Badge/Badge.tsx +2 -2
  346. package/src/components/Button/Button.test.tsx +2 -2
  347. package/src/components/Button/Button.tsx +11 -7
  348. package/src/components/Calendar/Calendar.test.tsx +41 -8
  349. package/src/components/Calendar/Calendar.tsx +39 -36
  350. package/src/components/Card/Card.tsx +51 -13
  351. package/src/components/Checkbox/Checkbox.test.tsx +36 -12
  352. package/src/components/DataTable/DataTable.test.tsx +1 -1
  353. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +13 -7
  354. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +14 -42
  355. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +13 -10
  356. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +14 -11
  357. package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +4 -2
  358. package/src/components/DataTable/__tests__/DataTable.test.tsx +13 -7
  359. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +13 -10
  360. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +15 -11
  361. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +12 -6
  362. package/src/components/DataTable/__tests__/keyboard.test.tsx +12 -6
  363. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +10 -6
  364. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +1 -1
  365. package/src/components/DataTable/components/DataTableBody.tsx +10 -25
  366. package/src/components/DataTable/components/DataTableCore.tsx +1 -1
  367. package/src/components/DataTable/components/FilterRow.tsx +3 -1
  368. package/src/components/DataTable/components/ImportModal.tsx +1 -1
  369. package/src/components/DataTable/components/VirtualizedDataTable.tsx +9 -9
  370. package/src/components/DataTable/core/ColumnFactory.ts +6 -6
  371. package/src/components/DataTable/core/DataTableContext.tsx +14 -10
  372. package/src/components/DataTable/core/LocalDataAdapter.ts +2 -1
  373. package/src/components/DataTable/core/PluginRegistry.ts +3 -3
  374. package/src/components/DataTable/core/StateManager.ts +12 -11
  375. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +104 -0
  376. package/src/components/DataTable/core/__tests__/DataManager.test.ts +101 -0
  377. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +84 -0
  378. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +102 -0
  379. package/src/components/DataTable/core/__tests__/StateManager.test.ts +104 -0
  380. package/src/components/DataTable/core/interfaces.ts +17 -17
  381. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +124 -0
  382. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +117 -0
  383. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +102 -0
  384. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +53 -0
  385. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +0 -2
  386. package/src/components/DataTable/hooks/useDataTablePermissions.ts +9 -8
  387. package/src/components/DataTable/types.ts +5 -5
  388. package/src/components/DataTable/utils/aggregationUtils.ts +4 -4
  389. package/src/components/DataTable/utils/columnUtils.ts +3 -2
  390. package/src/components/DataTable/utils/debugTools.ts +1 -1
  391. package/src/components/DataTable/utils/exportUtils.ts +6 -6
  392. package/src/components/DataTable/utils/hierarchicalSorting.ts +6 -6
  393. package/src/components/DataTable/utils/hierarchicalUtils.ts +0 -8
  394. package/src/components/DataTable/utils/index.ts +0 -1
  395. package/src/components/DataTable/utils/performanceUtils.ts +9 -4
  396. package/src/components/Dialog/Dialog.test.tsx +49 -27
  397. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +13 -8
  398. package/src/components/EventSelector/EventSelector.test.tsx +60 -12
  399. package/src/components/EventSelector/EventSelector.tsx +38 -15
  400. package/src/components/EventSelector/index.ts +2 -2
  401. package/src/components/FileDisplay/FileDisplay.test.tsx +143 -85
  402. package/src/components/FileDisplay/FileDisplay.tsx +1 -0
  403. package/src/components/FileUpload/FileUpload.test.tsx +532 -152
  404. package/src/components/FileUpload/FileUpload.tsx +43 -8
  405. package/src/components/Footer/Footer.test.tsx +19 -14
  406. package/src/components/Form/Form.test.tsx +96 -14
  407. package/src/components/Form/Form.tsx +210 -1
  408. package/src/components/Form/index.ts +3 -7
  409. package/src/components/Header/Header.test.tsx +24 -17
  410. package/src/components/Header/Header.tsx +3 -1
  411. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -4
  412. package/src/components/Input/Input.test.tsx +61 -36
  413. package/src/components/Label/{__tests__/Label.test.tsx → Label.test.tsx} +2 -2
  414. package/src/components/Label/Label.tsx +2 -3
  415. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +6 -5
  416. package/src/components/LoadingSpinner/LoadingSpinner.tsx +6 -2
  417. package/src/components/LoginForm/LoginForm.test.tsx +14 -13
  418. package/src/components/LoginForm/LoginForm.tsx +1 -1
  419. package/src/components/LoginForm/index.ts +7 -0
  420. package/src/components/NavigationMenu/NavigationMenu.test.tsx +233 -20
  421. package/src/components/NavigationMenu/NavigationMenu.tsx +191 -55
  422. package/src/components/NavigationMenu/index.ts +1 -1
  423. package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +20 -11
  424. package/src/components/OrganisationSelector/OrganisationSelector.tsx +1 -1
  425. package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.integration.test.tsx → PaceAppLayout.integration.test.tsx} +272 -79
  426. package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.performance.test.tsx → PaceAppLayout.performance.test.tsx} +155 -32
  427. package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.security.test.tsx → PaceAppLayout.security.test.tsx} +211 -65
  428. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +498 -210
  429. package/src/components/PaceAppLayout/PaceAppLayout.tsx +63 -64
  430. package/src/components/PaceAppLayout/test-setup.tsx +192 -0
  431. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +193 -39
  432. package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.test.tsx +2 -2
  433. package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.tsx +10 -4
  434. package/src/components/PasswordChange/index.ts +2 -0
  435. package/src/components/Progress/Progress.test.tsx +11 -0
  436. package/src/components/Progress/Progress.tsx +1 -1
  437. package/src/components/Progress/index.ts +10 -0
  438. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +2 -1
  439. package/src/components/PublicLayout/PublicLayout.test.tsx +1210 -0
  440. package/src/components/PublicLayout/PublicPageLayout.tsx +190 -36
  441. package/src/components/PublicLayout/PublicPageProvider.tsx +8 -7
  442. package/src/components/PublicLayout/index.ts +10 -28
  443. package/src/components/Select/Select.test.tsx +7 -7
  444. package/src/components/Select/Select.tsx +277 -11
  445. package/src/components/Select/index.ts +1 -2
  446. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +232 -0
  447. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +40 -19
  448. package/src/components/Table/{__tests__/Table.test.tsx → Table.test.tsx} +94 -41
  449. package/src/components/Tabs/Tabs.test.tsx +10 -9
  450. package/src/components/Tabs/Tabs.tsx +61 -33
  451. package/src/components/Textarea/Textarea.test.tsx +31 -18
  452. package/src/components/Toast/Toast.tsx +2 -2
  453. package/src/components/Tooltip/Tooltip.test.tsx +1 -1
  454. package/src/components/UserMenu/UserMenu.test.tsx +7 -6
  455. package/src/components/UserMenu/UserMenu.tsx +2 -2
  456. package/src/components/index.ts +5 -4
  457. package/src/constants/performance.ts +19 -8
  458. package/src/hooks/__tests__/useAppConfig.unit.test.ts +21 -22
  459. package/src/hooks/__tests__/useEvents.unit.test.ts +5 -4
  460. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +2 -2
  461. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -0
  462. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +16 -11
  463. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +1 -3
  464. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +1 -3
  465. package/src/hooks/__tests__/useRBAC.unit.test.ts +24 -2
  466. package/src/hooks/index.ts +4 -0
  467. package/src/hooks/public/index.ts +2 -0
  468. package/src/hooks/public/usePublicEvent.ts +4 -6
  469. package/src/hooks/public/usePublicRouteParams.ts +1 -1
  470. package/src/hooks/services/useAuth.ts +2 -4
  471. package/src/hooks/services/useCurrentEvent.ts +1 -1
  472. package/src/hooks/useAppConfig.ts +1 -1
  473. package/src/hooks/useDataTablePerformance.ts +2 -2
  474. package/src/hooks/useEventTheme.ts +1 -1
  475. package/src/hooks/useEvents.ts +51 -10
  476. package/src/hooks/useOrganisationPermissions.test.ts +3 -3
  477. package/src/hooks/useOrganisationPermissions.ts +1 -1
  478. package/src/hooks/useOrganisationSecurity.ts +2 -2
  479. package/src/hooks/usePermissionCache.test.ts +9 -9
  480. package/src/hooks/usePermissionCache.ts +2 -2
  481. package/src/index.ts +19 -12
  482. package/src/providers/OrganisationProvider.tsx +73 -9
  483. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +113 -13
  484. package/src/providers/__tests__/AuthProvider.test.tsx +2 -1
  485. package/src/providers/__tests__/EventProvider.test.tsx +24 -15
  486. package/src/providers/__tests__/OrganisationProvider.test.tsx +87 -36
  487. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +80 -24
  488. package/src/providers/index.ts +0 -3
  489. package/src/providers/services/AuthServiceProvider.tsx +2 -17
  490. package/src/providers/services/EventServiceProvider.tsx +11 -16
  491. package/src/providers/services/InactivityServiceProvider.tsx +9 -12
  492. package/src/providers/services/OrganisationServiceProvider.tsx +9 -12
  493. package/src/providers/services/UnifiedAuthProvider.tsx +85 -18
  494. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +11 -4
  495. package/src/rbac/__tests__/scenarios.user-role.test.tsx +105 -21
  496. package/src/rbac/adapters.tsx +1 -1
  497. package/src/rbac/api.ts +20 -4
  498. package/src/rbac/audit-enhanced.ts +47 -2
  499. package/src/rbac/audit.ts +47 -2
  500. package/src/rbac/components/NavigationGuard.tsx +1 -1
  501. package/src/rbac/components/NavigationProvider.test.tsx +7 -6
  502. package/src/rbac/components/NavigationProvider.tsx +1 -1
  503. package/src/rbac/components/PagePermissionGuard.tsx +1 -1
  504. package/src/rbac/components/PagePermissionProvider.test.tsx +7 -6
  505. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  506. package/src/rbac/components/PermissionEnforcer.tsx +1 -1
  507. package/src/rbac/components/RoleBasedRouter.tsx +1 -1
  508. package/src/rbac/components/SecureDataProvider.test.tsx +7 -6
  509. package/src/rbac/components/SecureDataProvider.tsx +1 -1
  510. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +6 -6
  511. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +11 -10
  512. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +10 -11
  513. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +19 -15
  514. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +13 -12
  515. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +19 -15
  516. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +18 -18
  517. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +11 -10
  518. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +8 -7
  519. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +10 -11
  520. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +48 -19
  521. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +476 -0
  522. package/src/rbac/hooks/index.ts +3 -0
  523. package/src/rbac/hooks/usePermissions.ts +31 -85
  524. package/src/rbac/hooks/useRBAC.test.ts +13 -1
  525. package/src/rbac/hooks/useRBAC.ts +13 -67
  526. package/src/rbac/hooks/useResolvedScope.ts +11 -0
  527. package/src/rbac/hooks/useSecureSupabase.ts +308 -0
  528. package/src/rbac/index.ts +3 -0
  529. package/src/rbac/secureClient.ts +53 -6
  530. package/src/rbac/security.ts +37 -1
  531. package/src/{types/rbac-functions.ts → rbac/types/functions.ts} +30 -30
  532. package/src/rbac/types.ts +3 -2
  533. package/src/services/AuthService.ts +33 -25
  534. package/src/services/EventService.ts +56 -44
  535. package/src/services/InactivityService.ts +33 -53
  536. package/src/services/OrganisationService.ts +36 -40
  537. package/src/services/__tests__/AuthService.restoreSession.test.ts +6 -2
  538. package/src/services/__tests__/EventService.test.ts +67 -33
  539. package/src/services/interfaces/IEventService.ts +1 -1
  540. package/src/styles/core.css +2 -2
  541. package/src/styles/index.ts +1 -5
  542. package/src/types/__tests__/guards.test.ts +1 -1
  543. package/src/types/__tests__/type-validation.test.ts +0 -1
  544. package/src/types/auth.ts +42 -2
  545. package/src/types/core.ts +251 -0
  546. package/src/types/database.ts +11 -496
  547. package/src/types/event.ts +102 -0
  548. package/src/types/file-reference.ts +6 -4
  549. package/src/types/guards.ts +2 -1
  550. package/src/types/index.ts +48 -14
  551. package/src/types/lodash.debounce.d.ts +15 -0
  552. package/src/types/organisation.ts +14 -10
  553. package/src/types/supabase.ts +15 -17
  554. package/src/utils/__tests__/secureErrors.unit.test.ts +1 -1
  555. package/src/utils/__tests__/validationUtils.unit.test.ts +0 -29
  556. package/src/utils/app/appNameResolver.ts +1 -1
  557. package/src/utils/dynamic/dynamicUtils.ts +3 -2
  558. package/src/utils/file-reference/index.ts +25 -6
  559. package/src/utils/security/secureErrors.ts +1 -1
  560. package/src/utils/validation/index.ts +6 -12
  561. package/src/utils/validation/validationUtils.ts +0 -13
  562. package/dist/UnifiedAuthProvider-B37ATQHE.js +0 -16
  563. package/dist/auth-DReDSLq9.d.ts +0 -16
  564. package/dist/chunk-3JI76CYK.js +0 -2444
  565. package/dist/chunk-3JI76CYK.js.map +0 -1
  566. package/dist/chunk-56XJ3TU6.js +0 -11
  567. package/dist/chunk-56XJ3TU6.js.map +0 -1
  568. package/dist/chunk-5MT24GKJ.js.map +0 -1
  569. package/dist/chunk-7QCC6MCP.js +0 -288
  570. package/dist/chunk-BESYRHQM.js.map +0 -1
  571. package/dist/chunk-BJPBT3CU.js +0 -21
  572. package/dist/chunk-BJPBT3CU.js.map +0 -1
  573. package/dist/chunk-BVYWGZVV.js.map +0 -1
  574. package/dist/chunk-CX5M4ZAG.js.map +0 -1
  575. package/dist/chunk-D7LCGMVS.js.map +0 -1
  576. package/dist/chunk-EGI6MUL6.js +0 -27
  577. package/dist/chunk-EGI6MUL6.js.map +0 -1
  578. package/dist/chunk-ERISIBYU.js.map +0 -1
  579. package/dist/chunk-HRO5HWN2.js.map +0 -1
  580. package/dist/chunk-HZLDFOE4.js.map +0 -1
  581. package/dist/chunk-JISYG63F.js +0 -70
  582. package/dist/chunk-JISYG63F.js.map +0 -1
  583. package/dist/chunk-LIMSTKYD.js +0 -61
  584. package/dist/chunk-LIMSTKYD.js.map +0 -1
  585. package/dist/chunk-OWAG3GSU.js.map +0 -1
  586. package/dist/chunk-PPMP5J6T.js.map +0 -1
  587. package/dist/chunk-Q5QRDWKI.js.map +0 -1
  588. package/dist/chunk-S5OFRT4M.js.map +0 -1
  589. package/dist/chunk-SBVILCCA.js.map +0 -1
  590. package/dist/chunk-TUMEWN34.js +0 -15
  591. package/dist/chunk-TUMEWN34.js.map +0 -1
  592. package/dist/chunk-XDNLUEXI.js +0 -138
  593. package/dist/chunk-XJ2HZOBU.js.map +0 -1
  594. package/dist/chunk-ZYTYSTO5.js.map +0 -1
  595. package/dist/chunk-ZZ2SS7NI.js +0 -237
  596. package/dist/chunk-ZZ2SS7NI.js.map +0 -1
  597. package/dist/database-C6jy7EOu.d.ts +0 -500
  598. package/dist/organisation-D6qRDtbF.d.ts +0 -93
  599. package/dist/schema-DTDZQe2u.d.ts +0 -28
  600. package/dist/unified-DQ4VcT7H.d.ts +0 -198
  601. package/dist/useInactivityTracker-TO6ZOF35.js +0 -11
  602. package/dist/validation.d.ts +0 -47
  603. package/dist/validation.js +0 -24
  604. package/dist/validation.js.map +0 -1
  605. package/docs/DOCUMENTATION_AUDIT.md +0 -172
  606. package/docs/DOCUMENTATION_STANDARD.md +0 -137
  607. package/docs/api/classes/PublicErrorBoundary.md +0 -132
  608. package/docs/api/interfaces/EventLogoProps.md +0 -152
  609. package/docs/api/interfaces/PublicErrorBoundaryProps.md +0 -94
  610. package/docs/api/interfaces/PublicErrorBoundaryState.md +0 -68
  611. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +0 -86
  612. package/docs/architecture/rpc-function-standards.md +0 -1106
  613. package/docs/getting-started/consuming-app-vite-config.md +0 -239
  614. package/docs/implementation-guides/event-theming-summary.md +0 -226
  615. package/docs/implementation-guides/public-pages-advanced.md +0 -1038
  616. package/docs/migration/v0.4.15-tailwind-scanning.md +0 -278
  617. package/docs/migration/v0.4.16-css-first-approach.md +0 -312
  618. package/docs/migration/v0.4.17-source-path-fix.md +0 -235
  619. package/docs/rbac/RBAC_EVENT_CONTEXT_LOADING.md +0 -222
  620. package/docs/rbac/RBAC_LOGIN_SAFETY_FIX.md +0 -95
  621. package/docs/rbac/RBAC_V0.5.147_FIX.md +0 -117
  622. package/docs/rbac/README-rbac-rls-integration.md +0 -374
  623. package/docs/styles/usage.md +0 -227
  624. package/docs/testing/visual-testing.md +0 -120
  625. package/docs/troubleshooting/DEBUG_NETWORK_ERROR.md +0 -152
  626. package/docs/troubleshooting/FIX_SUPABASE_CORS.md +0 -184
  627. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +0 -193
  628. package/docs/troubleshooting/database-view-compatibility.md +0 -125
  629. package/docs/troubleshooting/react-hooks-issue-analysis.md +0 -172
  630. package/docs/troubleshooting/tailwind-content-scanning.md +0 -219
  631. package/examples/RBAC/EventBasedApp.tsx +0 -239
  632. package/examples/RBAC/PermissionExample.tsx +0 -151
  633. package/examples/STRUCTURE.md +0 -125
  634. package/examples/components 2/DataTable/HierarchicalExample.tsx +0 -475
  635. package/examples/components 2/Dialog/BasicHtmlTest.tsx +0 -55
  636. package/examples/components 2/Dialog/DebugHtmlExample.tsx +0 -68
  637. package/examples/components 2/Dialog/HtmlDialogExample.tsx +0 -202
  638. package/examples/components 2/Dialog/SimpleHtmlTest.tsx +0 -61
  639. package/examples/components 2/Dialog/SmartDialogExample.tsx +0 -322
  640. package/examples/components 2/index.ts +0 -11
  641. package/examples/features/index.ts +0 -12
  642. package/examples/features/rbac/CompleteRBACExample.tsx +0 -324
  643. package/examples/features/rbac/index.ts +0 -13
  644. package/examples/public-pages/CorrectPublicPageImplementation.tsx +0 -301
  645. package/examples/public-pages/PublicEventPage.tsx +0 -274
  646. package/examples/public-pages/PublicPageApp.tsx +0 -308
  647. package/examples/public-pages/PublicPageUsageExample.tsx +0 -216
  648. package/examples/public-pages/index.ts +0 -14
  649. package/src/__tests__/TEST_STANDARD.md +0 -1008
  650. package/src/components/Checkbox/__mocks__/Checkbox.tsx +0 -2
  651. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +0 -421
  652. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +0 -177
  653. package/src/components/DataTable/examples/PerformanceExample.tsx +0 -506
  654. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +0 -316
  655. package/src/components/DataTable/examples/__tests__/HierarchicalExample.test.tsx +0 -45
  656. package/src/components/DataTable/examples/__tests__/InitialPageSizeExample.test.tsx +0 -211
  657. package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +0 -126
  658. package/src/components/Dialog/README.md +0 -804
  659. package/src/components/Dialog/examples/BasicHtmlTest.tsx +0 -55
  660. package/src/components/Dialog/examples/DebugHtmlExample.tsx +0 -68
  661. package/src/components/Dialog/examples/ScrollableDialogExample.tsx +0 -290
  662. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +0 -61
  663. package/src/components/Dialog/examples/__tests__/HtmlDialogExample.test.tsx +0 -71
  664. package/src/components/Dialog/examples/__tests__/SimpleHtmlTest.test.tsx +0 -122
  665. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +0 -147
  666. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +0 -611
  667. package/src/components/Dialog/utils/safeHtml.ts +0 -185
  668. package/src/components/EventSelector/types.ts +0 -79
  669. package/src/components/Form/FormErrorSummary.tsx +0 -113
  670. package/src/components/Form/FormField.tsx +0 -249
  671. package/src/components/Form/FormFieldset.tsx +0 -127
  672. package/src/components/Form/FormLiveRegion.tsx +0 -198
  673. package/src/components/Input/__mocks__/Input.tsx +0 -2
  674. package/src/components/NavigationMenu/types.ts +0 -85
  675. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +0 -326
  676. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -1078
  677. package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
  678. package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
  679. package/src/components/PasswordReset/index.ts +0 -2
  680. package/src/components/ProtectedRoute/README.md +0 -164
  681. package/src/components/PublicLayout/EventLogo.tsx +0 -175
  682. package/src/components/PublicLayout/PublicErrorBoundary.tsx +0 -282
  683. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +0 -216
  684. package/src/components/PublicLayout/PublicPageContextChecker.tsx +0 -131
  685. package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
  686. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
  687. package/src/components/PublicLayout/PublicPageFooter.tsx +0 -124
  688. package/src/components/PublicLayout/PublicPageHeader.tsx +0 -209
  689. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +0 -449
  690. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +0 -393
  691. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +0 -192
  692. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +0 -351
  693. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +0 -402
  694. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +0 -460
  695. package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +0 -313
  696. package/src/components/Select/hooks.ts +0 -289
  697. package/src/hooks/useCounter.test.ts +0 -131
  698. package/src/hooks/useDebounce.test.ts +0 -375
  699. package/src/providers/AuthProvider.tsx +0 -15
  700. package/src/providers/EventProvider.tsx +0 -16
  701. package/src/providers/InactivityProvider.tsx +0 -15
  702. package/src/providers/OrganisationProvider.context.test.tsx +0 -169
  703. package/src/providers/UnifiedAuthProvider.tsx +0 -15
  704. package/src/types/theme.ts +0 -6
  705. package/src/types/unified.ts +0 -265
  706. package/src/utils/appConfig.ts +0 -47
  707. package/src/utils/appIdResolver.test.ts +0 -499
  708. package/src/utils/appIdResolver.ts +0 -130
  709. package/src/utils/appNameResolver.simple.test.ts +0 -212
  710. package/src/utils/appNameResolver.test.ts +0 -121
  711. package/src/utils/appNameResolver.ts +0 -191
  712. package/src/utils/audit.ts +0 -127
  713. package/src/utils/auth-utils.ts +0 -96
  714. package/src/utils/bundleAnalysis.ts +0 -129
  715. package/src/utils/debugLogger.ts +0 -67
  716. package/src/utils/deviceFingerprint.ts +0 -215
  717. package/src/utils/dynamicUtils.ts +0 -105
  718. package/src/utils/file-reference.test.ts +0 -788
  719. package/src/utils/file-reference.ts +0 -519
  720. package/src/utils/formatDate.test.ts +0 -237
  721. package/src/utils/formatting.ts +0 -170
  722. package/src/utils/lazyLoad.tsx +0 -44
  723. package/src/utils/logger.ts +0 -179
  724. package/src/utils/organisationContext.test.ts +0 -322
  725. package/src/utils/organisationContext.ts +0 -153
  726. package/src/utils/performanceBenchmark.ts +0 -64
  727. package/src/utils/performanceBudgets.ts +0 -110
  728. package/src/utils/permissionTypes.ts +0 -37
  729. package/src/utils/permissionUtils.test.ts +0 -393
  730. package/src/utils/permissionUtils.ts +0 -34
  731. package/src/utils/sanitization.ts +0 -264
  732. package/src/utils/schemaUtils.ts +0 -37
  733. package/src/utils/secureDataAccess.test.ts +0 -711
  734. package/src/utils/secureDataAccess.ts +0 -377
  735. package/src/utils/secureErrors.ts +0 -79
  736. package/src/utils/security.ts +0 -156
  737. package/src/utils/securityMonitor.ts +0 -45
  738. package/src/utils/sessionTracking.ts +0 -126
  739. package/src/utils/validation.ts +0 -111
  740. package/src/utils/validationUtils.ts +0 -120
  741. package/src/validation/index.ts +0 -12
  742. /package/dist/{DataTable-UA6CL4JI.js.map → DataTable-QAB34V6K.js.map} +0 -0
  743. /package/dist/{UnifiedAuthProvider-B37ATQHE.js.map → UnifiedAuthProvider-7F6T4B6K.js.map} +0 -0
  744. /package/dist/{api-45XYYO2A.js.map → api-ROMBCNKU.js.map} +0 -0
  745. /package/dist/{audit-64X3VJXB.js.map → audit-WRS3KJKI.js.map} +0 -0
  746. /package/dist/{chunk-PLDDJCW6.js.map → chunk-7D4SUZUM.js.map} +0 -0
  747. /package/dist/{useInactivityTracker-TO6ZOF35.js.map → chunk-KQCRWDSA.js.map} +0 -0
  748. /package/examples/{components 2/DataTable → DataTable}/InitialPageSizeExample.tsx +0 -0
  749. /package/examples/{features/public-pages → PublicPages}/index.ts +0 -0
  750. /package/examples/{RBAC → rbac}/index.ts +0 -0
@@ -1,1106 +0,0 @@
1
- # RPC Function Standards
2
-
3
- ## Overview
4
-
5
- This document defines the standards for creating, naming, and structuring RPC (Remote Procedure Call) functions in the PACE Core database. These standards ensure consistency, security, and maintainability across all database functions.
6
-
7
- ## Naming Convention
8
-
9
- ### Pattern
10
-
11
- RPC function names must follow: **`<family>_<domain>_<verb>`**
12
-
13
- ### Family Prefixes
14
-
15
- The family prefix categorizes the function's purpose:
16
-
17
- - **`data_`** - Data access functions that retrieve or manipulate application data
18
- - Examples: `data_user_events_get`, `data_cake_meals_get`, `data_user_organisations_get`
19
-
20
- - **`rbac_`** - RBAC (Role-Based Access Control) functions for permission checking, role management, and security
21
- - Examples: `rbac_check_permission_simplified`, `rbac_permissions_get`, `rbac_role_grant`
22
-
23
- - **`util_`** - Utility functions for common operations, helpers, and shared logic
24
- - Examples: `util_app_resolve`, `util_format_date`
25
-
26
- - **`app_`** - Application-specific functions tied to a particular app module
27
- - Examples: `app_cake_supply_calculate`, `app_cake_distribution_get`
28
-
29
- ### Domain
30
-
31
- The domain identifies the entity or context the function operates on:
32
-
33
- - **User-related**: `user_events`, `user_organisations`, `user_roles`
34
- - **App-specific**: `cake_meals`, `cake_distribution`, `cake_supply`
35
- - **System**: `permissions`, `roles`, `session`, `audit`
36
-
37
- ### Verb
38
-
39
- The verb describes the action being performed:
40
-
41
- - **`get`** - Retrieve a single record or collection
42
- - **`list`** - Retrieve a collection (alternative to `get`)
43
- - **`create`** - Create a new record
44
- - **`update`** - Update an existing record
45
- - **`delete`** - Delete a record
46
- - **`check`** - Validate or check a condition (returns boolean)
47
- - **`validate`** - Validate data or access (returns boolean or result)
48
- - **`grant`** - Grant a permission or role
49
- - **`revoke`** - Revoke a permission or role
50
- - **`calculate`** - Perform calculations
51
- - **`resolve`** - Resolve or transform data
52
-
53
- ### Examples
54
-
55
- ```sql
56
- -- ✅ Good examples
57
- data_user_events_get -- Get user events
58
- data_cake_meals_get -- Get cake meals
59
- rbac_check_permission_simplified -- Check permission
60
- rbac_permissions_get -- Get permissions
61
- rbac_role_grant -- Grant role
62
- util_app_resolve -- Resolve app
63
- data_cake_distribution_list -- List distribution data
64
-
65
- -- ❌ Bad examples
66
- getUserEvents -- Wrong: camelCase, missing prefix
67
- cake_meals_get -- Wrong: missing family prefix
68
- rbac_checkPermission -- Wrong: camelCase
69
- get_cake_meals -- Wrong: wrong prefix order
70
- ```
71
-
72
- ## Function Structure
73
-
74
- ### Standard Template
75
-
76
- ```sql
77
- CREATE OR REPLACE FUNCTION public.<family>_<domain>_<verb>(
78
- p_param1 TEXT, -- ⚠️ Use TEXT for strings, NOT CHARACTER VARYING
79
- p_param2 INTEGER DEFAULT NULL, -- Use INTEGER, DOUBLE PRECISION, SMALLINT for numbers
80
- p_param3 BOOLEAN DEFAULT NULL, -- Use BOOLEAN for boolean values
81
- p_user_id UUID DEFAULT auth.uid(),
82
- p_organisation_id UUID DEFAULT NULL
83
- )
84
- RETURNS TABLE(
85
- column1 TYPE,
86
- column2 TYPE
87
- )
88
- LANGUAGE plpgsql
89
- SECURITY DEFINER
90
- SET search_path TO 'public'
91
- AS $$
92
- DECLARE
93
- v_local_variable TYPE;
94
- v_is_super_admin BOOLEAN := false;
95
- BEGIN
96
- -- 1. Input validation
97
- IF p_param1 IS NULL THEN
98
- RETURN;
99
- END IF;
100
-
101
- -- 2. Super admin check (if applicable)
102
- SELECT EXISTS(
103
- SELECT 1 FROM rbac_global_roles
104
- WHERE user_id = COALESCE(p_user_id, auth.uid())
105
- AND role = 'super_admin'
106
- AND valid_from <= NOW()
107
- AND (valid_to IS NULL OR valid_to >= NOW())
108
- ) INTO v_is_super_admin;
109
-
110
- IF v_is_super_admin THEN
111
- -- Super admin logic
112
- RETURN QUERY SELECT ...;
113
- RETURN;
114
- END IF;
115
-
116
- -- 3. Organisation context validation (if required)
117
- IF p_organisation_id IS NULL THEN
118
- RAISE EXCEPTION 'Organisation context is required';
119
- RETURN;
120
- END IF;
121
-
122
- -- 4. Dynamic RBAC permission check (replaces manual organisation/event checks)
123
- -- Use rbac_check_permission_simplified() for consistency with RLS policies
124
- -- ⚠️ CRITICAL: Permission format must match what rbac_permissions_get returns
125
- -- Format: 'operation:page.{pageName}' (e.g., 'read:page.dishes', 'create:page.meals')
126
- -- The permission string is passed to rbac_permissions_get and must match exactly
127
- IF NOT rbac_check_permission_simplified(
128
- COALESCE(p_user_id, auth.uid()),
129
- 'read:page.dishes', -- Format: operation:page.{pageName} - MUST match rbac_permissions_get output
130
- p_organisation_id,
131
- p_event_id, -- p_event_id if event-scoped, NULL if org-scoped
132
- (SELECT id FROM rbac_apps WHERE name = 'CAKE' LIMIT 1), -- p_app_id
133
- 'dishes' -- p_page_id (page name from rbac_app_pages)
134
- ) THEN
135
- RETURN; -- No permission
136
- END IF;
137
-
138
- -- 5. Main logic (RLS is bypassed but we've checked permissions above)
139
- RETURN QUERY SELECT ...;
140
-
141
- EXCEPTION WHEN OTHERS THEN
142
- RAISE WARNING 'Function failed: %', SQLERRM;
143
- RETURN;
144
- END;
145
- $$;
146
- ```
147
-
148
- ### Key Requirements
149
-
150
- 1. **Always use `SECURITY DEFINER`** - Functions must run with elevated privileges to bypass RLS. **However**, you must still implement security checks using `rbac_check_permission_simplified()` internally (see Dynamic RLS Integration section above).
151
-
152
- 2. **Always set `SET search_path TO 'public'`** - Prevents SQL injection attacks
153
-
154
- 3. **Parameter Naming and Types**:
155
- - Prefix all parameters with `p_` (e.g., `p_event_id`, `p_user_id`)
156
- - Use `p_user_id UUID DEFAULT auth.uid()` for user context
157
- - Use `p_organisation_id UUID DEFAULT NULL` for organisation context
158
- - Use descriptive names
159
- - **⚠️ CRITICAL: Parameter Type Requirements**:
160
- - **String parameters MUST use `TEXT`**, NOT `CHARACTER VARYING` or `VARCHAR`
161
- - **Numeric parameters**: Use `DOUBLE PRECISION` for decimal numbers, `INTEGER` for whole numbers, `SMALLINT` for small integers
162
- - **Boolean parameters**: Use `BOOLEAN`
163
- - **Date/Time parameters**: Use `DATE`, `TIMESTAMP`, or `TIMESTAMPTZ` as appropriate
164
- - **UUID parameters**: Use `UUID`
165
- - **Why TEXT instead of CHARACTER VARYING?**
166
- - Application code calls functions with TEXT parameters
167
- - PostgreSQL cannot automatically choose between TEXT and CHARACTER VARYING versions
168
- - Having both creates ambiguity errors: "Could not choose the best candidate function"
169
- - TEXT is the standard PostgreSQL type for string parameters in RPC functions
170
- - Even though database columns may use CHARACTER VARYING, function parameters should use TEXT
171
-
172
- 4. **Variable Naming**:
173
- - Prefix local variables with `v_` (e.g., `v_is_super_admin`, `v_event_exists`)
174
- - Use descriptive names
175
-
176
- 5. **Return Types**:
177
- - Use `RETURNS TABLE(...)` for functions that return multiple rows
178
- - Use `RETURNS BOOLEAN` for check/validation functions
179
- - Use `RETURNS JSON` or `RETURNS JSONB` for complex data
180
- - Use `RETURNS UUID` or `RETURNS TEXT` for single values
181
-
182
- 6. **Error Handling**:
183
- - Always include `EXCEPTION WHEN OTHERS` block
184
- - Log errors with `RAISE WARNING` or `RAISE NOTICE`
185
- - Return empty results on error (fail-secure)
186
-
187
- 7. **Security Checks**:
188
- - Always check super_admin status first (if applicable)
189
- - Always use `rbac_check_permission_simplified()` for permission checks (ensures consistency with dynamic RLS)
190
- - Always validate organisation membership (for non-super-admin)
191
- - Always validate event access (for event-scoped functions)
192
- - Never trust client-provided parameters without validation
193
- - **Important**: Even though RLS is bypassed with `SECURITY DEFINER`, you must implement the same security checks that RLS policies would enforce
194
-
195
- 8. **Comments**:
196
- - Add header comment explaining function purpose
197
- - Document parameters
198
- - Document return value
199
- - Document security implications
200
-
201
- ## Dynamic RLS Integration
202
-
203
- ### Overview
204
-
205
- PACE Core uses **Dynamic RLS (Row Level Security)** with RBAC-aware policies. This means RLS policies use `rbac_check_permission_simplified()` to dynamically check permissions based on the current RBAC configuration, rather than hardcoded role checks.
206
-
207
- ### RPC Functions vs RLS Policies
208
-
209
- There are **two layers** of security in PACE Core:
210
-
211
- 1. **RLS Policies** - For direct table access (client-side queries)
212
- - Use `rbac_check_permission_simplified()` in policy USING clauses
213
- - Enforce security at the database level for all direct queries
214
- - Example: `CREATE POLICY ... USING (rbac_check_permission_simplified(...))`
215
-
216
- 2. **RPC Functions** - For complex operations (server-side logic)
217
- - Run with `SECURITY DEFINER` which **bypasses RLS**
218
- - Must implement their own security checks
219
- - Should use `rbac_check_permission_simplified()` internally for consistency
220
-
221
- ### Why RPC Functions Bypass RLS
222
-
223
- RPC functions use `SECURITY DEFINER` which bypasses RLS. This is **intentional and required** for several reasons:
224
-
225
- #### Technical Reasons
226
-
227
- 1. **Performance** - RPC functions need to query multiple tables efficiently without RLS overhead on every operation
228
- 2. **Complex Logic** - Functions perform calculations, aggregations, and joins that RLS policies can't handle elegantly
229
- 3. **Query Optimization** - Functions can optimize queries for specific use cases without RLS interference
230
-
231
- #### Security Architecture Reasons
232
-
233
- 4. **Centralized Security** - Functions implement security checks in one place rather than relying on multiple RLS policies
234
- 5. **Explicit Control** - Security logic is visible in the function code, not hidden in policy definitions
235
- 6. **Defense in Depth** - Even if RLS has bugs or is misconfigured, RPC function security checks still apply
236
- 7. **RLS as Safety Net** - RLS policies provide defense-in-depth for any direct queries, but RPC functions don't rely on them
237
-
238
- #### Why This Architecture is Better
239
-
240
- **Problem with RLS-Only Approach:**
241
- - RLS policies can have bugs (we saw this with `cake_diner` policy)
242
- - RLS policies can be misconfigured or forgotten
243
- - Multiple policies on multiple tables = multiple places for bugs
244
- - Direct queries bypass security if RLS is broken
245
-
246
- **Solution with RPC Functions:**
247
- - All security logic in one place (the function)
248
- - Explicit permission checks that are easy to audit
249
- - RLS still exists as defense-in-depth (catches bugs)
250
- - Can't bypass security even if RLS fails
251
-
252
- **Important**: You must still implement security checks in the RPC function itself. Bypassing RLS doesn't mean bypassing security - it means implementing security explicitly rather than relying on RLS policies.
253
-
254
- ### Using `rbac_check_permission_simplified()` in RPC Functions
255
-
256
- RPC functions should use `rbac_check_permission_simplified()` for permission checks to ensure consistency with RLS policies:
257
-
258
- ```sql
259
- CREATE OR REPLACE FUNCTION data_cake_meals_get(
260
- p_event_id TEXT,
261
- p_user_id UUID DEFAULT auth.uid(),
262
- p_organisation_id UUID DEFAULT NULL
263
- )
264
- RETURNS TABLE(...)
265
- LANGUAGE plpgsql
266
- SECURITY DEFINER
267
- SET search_path TO 'public'
268
- AS $$
269
- BEGIN
270
- -- Super admin check (always first)
271
- IF EXISTS(SELECT 1 FROM rbac_global_roles WHERE user_id = p_user_id AND role = 'super_admin') THEN
272
- RETURN QUERY SELECT * FROM cake_meal WHERE meal_event_id = p_event_id;
273
- RETURN;
274
- END IF;
275
-
276
- -- Use rbac_check_permission_simplified for dynamic RBAC checking
277
- -- ⚠️ CRITICAL: Permission format must be 'operation:page.{pageName}'
278
- -- This matches the format returned by rbac_permissions_get()
279
- IF NOT rbac_check_permission_simplified(
280
- p_user_id,
281
- 'read:page.meals', -- Format: operation:page.{pageName}
282
- p_organisation_id,
283
- p_event_id,
284
- (SELECT id FROM rbac_apps WHERE name = 'CAKE' LIMIT 1),
285
- 'meals' -- Page name (resolved to page ID internally)
286
- ) THEN
287
- RETURN; -- No permission
288
- END IF;
289
-
290
- -- Return data (bypasses RLS due to SECURITY DEFINER)
291
- RETURN QUERY
292
- SELECT * FROM cake_meal
293
- WHERE meal_event_id = p_event_id
294
- AND organisation_id = p_organisation_id;
295
- END;
296
- $$;
297
- ```
298
-
299
- ### Key Points
300
-
301
- 1. **Always check permissions** - Even though RLS is bypassed, you must check permissions
302
- 2. **Use the same function** - Use `rbac_check_permission_simplified()` just like RLS policies do
303
- 3. **Consistent behavior** - This ensures RPC functions and direct queries have the same security behavior
304
- 4. **Performance** - `rbac_check_permission_simplified()` is optimized and cached
305
-
306
- ### RPC-First Architecture (Recommended)
307
-
308
- **Security Best Practice**: Use RPC functions as the **primary access method** for all database operations. Treat RLS as defense-in-depth, not a primary security control.
309
-
310
- #### Why RPC Functions Should Be Preferred
311
-
312
- 1. **Centralized Security Logic**
313
- - All security checks in one place (the RPC function)
314
- - Easier to audit and review
315
- - Consistent behavior across all operations
316
-
317
- 2. **Avoids RLS Bypass Issues**
318
- - RLS policies can have bugs, be misconfigured, or be bypassed
319
- - RPC functions with explicit permission checks are more reliable
320
- - SECURITY DEFINER functions bypass RLS, but implement their own checks
321
-
322
- 3. **Better Performance Control**
323
- - Can optimize queries for specific use cases
324
- - Can add caching at the function level
325
- - Can pre-compute complex operations
326
-
327
- 4. **Audit and Logging**
328
- - All data access goes through known functions
329
- - Easier to log and monitor
330
- - Can add audit trails automatically
331
-
332
- 5. **Business Logic Enforcement**
333
- - Complex business rules enforced at database level
334
- - Data validation and transformations in one place
335
- - Prevents inconsistent logic across applications
336
-
337
- #### Current Architecture (Allows Both)
338
-
339
- Currently, PACE Core supports both RPC functions and direct queries:
340
-
341
- **Use RPC Functions when:**
342
- - Complex calculations or aggregations needed
343
- - Multiple tables need to be joined with complex logic
344
- - Performance is critical (pre-computed results)
345
- - Business logic is too complex for RLS policies
346
- - **Security-sensitive operations** (preferred for all operations)
347
-
348
- **Use Direct Queries (with RLS) when:**
349
- - Simple CRUD operations (only if RLS policies are properly configured)
350
- - Standard filtering and sorting
351
- - Client-side filtering is sufficient
352
- - No complex business logic required
353
- - ⚠️ **Not recommended for production** - Use RPC functions instead
354
-
355
- #### Recommended Future Architecture: RPC-Only Access
356
-
357
- For maximum security, consider migrating to an **RPC-only architecture**:
358
-
359
- 1. **All table access through RPC functions**
360
- - Create RPC functions for all data operations
361
- - Ban direct table queries from application code
362
- - Use RLS as pure defense-in-depth (should never be relied upon)
363
-
364
- 2. **Benefits of RPC-Only:**
365
- - **Single point of security enforcement** - All access controlled in functions
366
- - **Easier auditing** - All access logged through RPC layer
367
- - **Consistent behavior** - Same security checks for all operations
368
- - **Easier maintenance** - Security logic in one place
369
- - **Prevents bugs** - Can't accidentally bypass security by querying directly
370
-
371
- 3. **RLS as Defense-in-Depth:**
372
- - RLS policies still exist and provide protection
373
- - But RPC functions bypass them (SECURITY DEFINER)
374
- - RLS catches any bugs or unauthorized direct access attempts
375
- - Acts as a safety net, not primary security
376
-
377
- 4. **Migration Path:**
378
- ```
379
- Phase 1: Create RPC functions for all operations
380
- Phase 2: Update applications to use RPC functions
381
- Phase 3: Enable strict mode to log/block direct queries
382
- Phase 4: Remove direct query access entirely
383
- ```
384
-
385
- ### Example: Consistent Security Between RLS and RPC
386
-
387
- **RLS Policy (for direct queries):**
388
- ```sql
389
- CREATE POLICY "rbac_cake_meal_select" ON cake_meal
390
- FOR SELECT TO authenticated
391
- USING (
392
- organisation_id IS NOT NULL
393
- AND (
394
- is_user_super_admin()
395
- OR rbac_check_permission_simplified(
396
- auth.uid(),
397
- 'read:page.meals', -- Format: operation:page.{pageName}
398
- organisation_id,
399
- meal_event_id,
400
- (SELECT id FROM rbac_apps WHERE name = 'CAKE' LIMIT 1),
401
- 'meals' -- Page name
402
- )
403
- )
404
- );
405
- ```
406
-
407
- **RPC Function (for complex operations):**
408
- ```sql
409
- CREATE OR REPLACE FUNCTION data_cake_meals_get(...)
410
- ...
411
- BEGIN
412
- -- Same security check logic as RLS policy
413
- IF NOT (
414
- v_is_super_admin OR
415
- rbac_check_permission_simplified(
416
- p_user_id,
417
- 'read:page.meals', -- Format: operation:page.{pageName}
418
- p_organisation_id,
419
- p_event_id,
420
- (SELECT id FROM rbac_apps WHERE name = 'CAKE' LIMIT 1),
421
- 'meals' -- Page name
422
- )
423
- ) THEN
424
- RETURN;
425
- END IF;
426
- ...
427
- END;
428
- ```
429
-
430
- Both use the **same permission checking function**, ensuring consistent security behavior.
431
-
432
- ## Security Best Practices
433
-
434
- ### 1. Input Validation
435
-
436
- Always validate inputs:
437
-
438
- ```sql
439
- -- Check for NULL required parameters
440
- IF p_event_id IS NULL THEN
441
- RETURN;
442
- END IF;
443
-
444
- -- Check for invalid values
445
- IF NOT EXISTS(SELECT 1 FROM event WHERE event_id = p_event_id) THEN
446
- RETURN;
447
- END IF;
448
- ```
449
-
450
- ### 2. Organisation Context
451
-
452
- Always require organisation context for non-super-admin operations:
453
-
454
- ```sql
455
- -- Get organisation from context if not provided
456
- IF p_organisation_id IS NULL THEN
457
- p_organisation_id := current_setting('app.organisation_id', true)::uuid;
458
- END IF;
459
-
460
- IF p_organisation_id IS NULL THEN
461
- RAISE EXCEPTION 'Organisation context is required';
462
- END IF;
463
- ```
464
-
465
- ### 3. Super Admin Bypass
466
-
467
- Always check for super_admin status first:
468
-
469
- ```sql
470
- DECLARE
471
- v_is_super_admin BOOLEAN;
472
- BEGIN
473
- SELECT EXISTS(
474
- SELECT 1 FROM rbac_global_roles
475
- WHERE user_id = COALESCE(p_user_id, auth.uid())
476
- AND role = 'super_admin'
477
- AND valid_from <= NOW()
478
- AND (valid_to IS NULL OR valid_to >= NOW())
479
- ) INTO v_is_super_admin;
480
-
481
- IF v_is_super_admin THEN
482
- -- Super admin can access all data
483
- RETURN QUERY SELECT * FROM table_name;
484
- RETURN;
485
- END IF;
486
-
487
- -- Regular user logic with RBAC checks
488
- ...
489
- END;
490
- ```
491
-
492
- ### 4. Organisation Membership Validation
493
-
494
- Always validate organisation membership:
495
-
496
- ```sql
497
- IF NOT EXISTS(
498
- SELECT 1 FROM rbac_organisation_roles
499
- WHERE user_id = COALESCE(p_user_id, auth.uid())
500
- AND organisation_id = p_organisation_id
501
- AND status = 'active'
502
- AND revoked_at IS NULL
503
- AND valid_from <= NOW()
504
- AND (valid_to IS NULL OR valid_to >= NOW())
505
- ) THEN
506
- RETURN; -- No access
507
- END IF;
508
- ```
509
-
510
- ### 5. Event Access Validation
511
-
512
- For event-scoped functions:
513
-
514
- ```sql
515
- IF NOT EXISTS(
516
- SELECT 1 FROM rbac_event_app_roles
517
- WHERE user_id = COALESCE(p_user_id, auth.uid())
518
- AND event_id = p_event_id
519
- AND app_id = (SELECT id FROM rbac_apps WHERE name = 'CAKE' LIMIT 1)
520
- AND status = 'active'
521
- ) THEN
522
- RETURN; -- No event access
523
- END IF;
524
- ```
525
-
526
- ## Performance Considerations
527
-
528
- ### 1. Use Indexes
529
-
530
- Ensure queries use indexed columns:
531
- - `organisation_id`
532
- - `user_id`
533
- - `event_id`
534
- - Foreign key columns
535
-
536
- ### 2. Limit Result Sets
537
-
538
- Always use `LIMIT` when appropriate:
539
-
540
- ```sql
541
- RETURN QUERY
542
- SELECT * FROM table_name
543
- WHERE condition
544
- ORDER BY column
545
- LIMIT 1000; -- Prevent large result sets
546
- ```
547
-
548
- ### 3. Avoid N+1 Queries
549
-
550
- Use CTEs (Common Table Expressions) or JOINs instead of subqueries:
551
-
552
- ```sql
553
- -- ❌ Bad: N+1 query pattern
554
- FOR rec IN SELECT id FROM table1 LOOP
555
- SELECT * INTO v_data FROM table2 WHERE table1_id = rec.id;
556
- END LOOP;
557
-
558
- -- ✅ Good: Single query with JOIN
559
- RETURN QUERY
560
- SELECT t1.*, t2.*
561
- FROM table1 t1
562
- JOIN table2 t2 ON t2.table1_id = t1.id;
563
- ```
564
-
565
- ### 4. Cache Expensive Checks
566
-
567
- For functions called frequently, consider caching super_admin checks:
568
-
569
- ```sql
570
- -- Cache super_admin status in function
571
- DECLARE
572
- v_is_super_admin BOOLEAN;
573
- BEGIN
574
- -- Check once, use multiple times
575
- SELECT EXISTS(...) INTO v_is_super_admin;
576
-
577
- IF v_is_super_admin THEN
578
- -- Fast path
579
- ELSE
580
- -- Regular path with RBAC
581
- END IF;
582
- END;
583
- ```
584
-
585
- ## Testing Requirements
586
-
587
- ### Unit Tests
588
-
589
- Functions should be tested with:
590
-
591
- 1. **Null inputs** - Should handle gracefully
592
- 2. **Invalid inputs** - Should return empty or error
593
- 3. **Super admin access** - Should bypass checks
594
- 4. **Organisation membership** - Should enforce correctly
595
- 5. **Event access** - Should validate for event-scoped functions
596
- 6. **Empty results** - Should return empty set, not error
597
- 7. **Error conditions** - Should fail gracefully
598
-
599
- ### Example Test
600
-
601
- ```sql
602
- -- Test super admin access
603
- SELECT * FROM data_user_events_get('event-123', 'super-admin-user-id', NULL);
604
- -- Should return all events
605
-
606
- -- Test regular user with access
607
- SELECT * FROM data_user_events_get('event-123', 'regular-user-id', 'org-123');
608
- -- Should return events user has access to
609
-
610
- -- Test user without access
611
- SELECT * FROM data_user_events_get('event-123', 'unauthorized-user-id', 'org-123');
612
- -- Should return empty
613
-
614
- -- Test NULL input
615
- SELECT * FROM data_user_events_get(NULL, 'user-id', 'org-123');
616
- -- Should return empty gracefully
617
- ```
618
-
619
- ## Permission Format
620
-
621
- ### ⚠️ CRITICAL: Correct Permission Format
622
-
623
- **The permission string format is critical and must match exactly what `rbac_permissions_get()` returns.**
624
-
625
- #### Correct Format
626
-
627
- ```sql
628
- -- ✅ CORRECT: Format is 'operation:page.{pageName}'
629
- rbac_check_permission_simplified(
630
- p_user_id,
631
- 'create:page.dishes', -- Format: operation:page.{pageName}
632
- p_organisation_id,
633
- p_event_id,
634
- v_app_id,
635
- 'dishes' -- Page name (resolved to page ID internally)
636
- )
637
- ```
638
-
639
- #### Common Mistakes
640
-
641
- ```sql
642
- -- ❌ WRONG: Missing 'page.' prefix
643
- 'create:dishes'
644
-
645
- -- ❌ WRONG: Wrong separator
646
- 'create:page/dishes'
647
-
648
- -- ❌ WRONG: Wrong format entirely
649
- 'dishes:create'
650
- ```
651
-
652
- #### How to Determine the Correct Format
653
-
654
- 1. **Check existing migrations** - Look at recent migrations that work
655
- 2. **Check RLS policies** - Use the same format as RLS policies for the same resource
656
- 3. **Verify with rbac_permissions_get** - The permission string must match what this function returns in the `permission_type` column
657
-
658
- #### Examples by Operation Type
659
-
660
- ```sql
661
- -- Page-based permissions (most common)
662
- 'read:page.dishes' -- Read dishes page
663
- 'create:page.dishes' -- Create dishes
664
- 'update:page.dishes' -- Update dishes
665
- 'delete:page.dishes' -- Delete dishes
666
-
667
- 'read:page.meals' -- Read meals page
668
- 'read:page.distribution' -- Read distribution page
669
- 'read:page.deliveries' -- Read deliveries page
670
-
671
- -- File-based permissions (special case)
672
- 'read:files' -- Read files
673
- 'create:files' -- Create files
674
- 'delete:files' -- Delete files
675
- ```
676
-
677
- #### Parameter Guidelines
678
-
679
- ```sql
680
- rbac_check_permission_simplified(
681
- p_user_id, -- User ID (required)
682
- 'create:page.dishes', -- Permission string (format: operation:page.{pageName})
683
- p_organisation_id, -- Organisation ID (required for non-super-admin)
684
- p_event_id, -- Event ID (optional, for event-scoped permissions)
685
- v_app_id, -- App ID (required, usually CAKE app)
686
- 'dishes' -- Page name (required, matches the page name in rbac_app_pages)
687
- )
688
- ```
689
-
690
- ## Migration Guidelines
691
-
692
- ### Creating New Functions
693
-
694
- 1. **Create migration file with correct timestamp**:
695
- ```bash
696
- # Generate timestamp: YYYYMMDDHHMMSS
697
- date +%Y%m%d%H%M%S
698
- # Example output: 20251104113510
699
-
700
- # Create file: supabase/migrations/20251104113510_descriptive_name.sql
701
- ```
702
- ⚠️ **CRITICAL**: Always generate a NEW timestamp for each migration. Never reuse timestamps from previous migrations, even if they haven't been pushed yet.
703
-
704
- 2. **Add function**: Use standard template above
705
- 3. **Add comments**: Document purpose, parameters, returns
706
- 4. **Add grants**: `GRANT EXECUTE ON FUNCTION ... TO authenticated;`
707
- 5. **Add tests**: Include test queries in migration
708
- 6. **Regenerate types**: Run `npm run generate-types` to automatically generate TypeScript types from the database schema
709
- 7. **Verify types**: Check that `Database['public']['Functions']['function_name']` exists in `packages/core/src/types/database.generated.ts`
710
-
711
- ### ⚠️ Common Migration Mistakes
712
-
713
- 1. **Reusing old migration timestamps**:
714
- - ❌ **WRONG**: Reusing `20251104113047` if it's already been pushed
715
- - ✅ **CORRECT**: Generate new timestamp: `date +%Y%m%d%H%M%S` → `20251104113510`
716
- - Always create a NEW file with a NEW timestamp for each migration
717
-
718
- 2. **Wrong permission format**:
719
- - ❌ **WRONG**: `'create:dishes'` or `'read:meals'`
720
- - ✅ **CORRECT**: `'create:page.dishes'` or `'read:page.meals'`
721
- - Always use `'operation:page.{pageName}'` format, not `'operation:resource'`
722
- - The format must match exactly what `rbac_permissions_get()` returns
723
-
724
- 3. **Missing page_id parameter**: Always provide the page name as the last parameter (e.g., `'dishes'`, `'meals'`, `'distribution'`)
725
-
726
- 4. **Using CHARACTER VARYING instead of TEXT for string parameters**:
727
- - ❌ **WRONG**: `p_unit_id CHARACTER VARYING` or `p_dish_name VARCHAR`
728
- - ✅ **CORRECT**: `p_unit_id TEXT` or `p_dish_name TEXT`
729
- - **CRITICAL**: All string parameters MUST use `TEXT`, NOT `CHARACTER VARYING` or `VARCHAR`
730
- - Having both TEXT and CHARACTER VARYING versions causes "Could not choose the best candidate function" errors
731
- - Application code calls functions with TEXT parameters, so functions must accept TEXT
732
- - Even though database columns may use CHARACTER VARYING, function parameters should use TEXT
733
-
734
- 5. **Creating duplicate function versions**:
735
- - ❌ **WRONG**: Creating both `app_cake_unit_update(TEXT, ...)` and `app_cake_unit_update(CHARACTER VARYING, ...)`
736
- - ✅ **CORRECT**: Only create `app_cake_unit_update(TEXT, ...)`
737
- - Before creating a new function, check if a version already exists
738
- - If updating a function, use `CREATE OR REPLACE FUNCTION` to update the existing version
739
- - If you need to change parameter types, drop the old version first: `DROP FUNCTION IF EXISTS ... CASCADE;`
740
-
741
- 6. **Ambiguous column references**:
742
- - ❌ **WRONG**: `SELECT mealtype_name FROM cake_mealtype`
743
- - ✅ **CORRECT**: `SELECT cake_mealtype.mealtype_name FROM cake_mealtype`
744
- - Always fully qualify table names when there might be ambiguity
745
- - **MANDATORY**: When using JOINs, always use table aliases and prefix ALL column references
746
- - Common ambiguous columns: `organisation_id`, `created_by`, `updated_by`, `created_at`, `updated_at`
747
- - See "Avoiding Ambiguous Column References" section below for detailed guidance
748
-
749
- 7. **Not checking existing migrations**: Before creating a new migration, check if a similar one already exists to avoid duplicates
750
-
751
- ### Updating Existing Functions
752
-
753
- 1. **Use `CREATE OR REPLACE FUNCTION`** - Ensures idempotency
754
- 2. **Preserve backward compatibility** - Add new parameters with defaults
755
- 3. **Version changes** - Update function name if breaking changes (e.g., `_v2`)
756
- 4. **Document changes** - Add comments explaining changes
757
- 5. **Regenerate types**: Run `npm run generate-types` after function changes to update TypeScript types
758
-
759
- ### Deprecating Functions
760
-
761
- 1. **Add deprecation notice**:
762
- ```sql
763
- COMMENT ON FUNCTION old_function IS 'DEPRECATED: Use new_function instead';
764
- ```
765
-
766
- 2. **Keep function** - Don't delete immediately, allow migration period
767
-
768
- 3. **Update references** - Update all callers before removing
769
-
770
- ## Avoiding Ambiguous Column References
771
-
772
- ### Overview
773
-
774
- Ambiguous column reference errors occur when PostgreSQL cannot determine which table a column belongs to in a query with JOINs. This is a common source of silent failures in RPC functions.
775
-
776
- ### Mandatory Rules
777
-
778
- 1. **Always use table aliases in JOINs**: Never write JOINs without table aliases
779
- 2. **Fully qualify ALL column references**: Every column in SELECT, WHERE, ORDER BY, GROUP BY, and HAVING clauses must be prefixed with its table alias
780
- 3. **Common ambiguous columns**: The following columns exist in multiple tables and MUST always be prefixed:
781
- - `organisation_id`
782
- - `created_by`, `updated_by`
783
- - `created_at`, `updated_at`
784
- - `event_id` and its variations (e.g., `dish_event_id`, `meal_event_id`)
785
-
786
- ### Correct Patterns
787
-
788
- ```sql
789
- -- ✅ CORRECT: All columns properly prefixed with table aliases
790
- SELECT
791
- d.dish_id,
792
- d.dish_name,
793
- d.organisation_id,
794
- d.created_at,
795
- mt.mealtype_name,
796
- e.event_name,
797
- e.organisation_id AS event_organisation_id
798
- FROM cake_dish d
799
- LEFT JOIN cake_mealtype mt ON d.dish_mealtype_id = mt.mealtype_id
800
- LEFT JOIN event e ON d.dish_event_id = e.event_id
801
- WHERE d.dish_event_id = p_event_id
802
- AND d.organisation_id = p_organisation_id
803
- ORDER BY d.dish_code, mt.mealtype_name;
804
-
805
- -- ✅ CORRECT: CTEs with proper aliases
806
- WITH distribution_items AS (
807
- SELECT
808
- d.item_id,
809
- d.collection_date,
810
- SUM(d.required_quantity) as total_quantity
811
- FROM data_cake_distribution_list(p_event_id, p_user_id, p_organisation_id) d
812
- GROUP BY d.item_id, d.collection_date
813
- )
814
- SELECT
815
- di.item_id,
816
- di.collection_date,
817
- di.total_quantity
818
- FROM distribution_items di
819
- WHERE di.item_id = p_item_id;
820
- ```
821
-
822
- ### Incorrect Patterns
823
-
824
- ```sql
825
- -- ❌ WRONG: Missing table prefixes in SELECT
826
- SELECT
827
- dish_id,
828
- dish_name,
829
- organisation_id, -- AMBIGUOUS: Could be from cake_dish or event
830
- mealtype_name
831
- FROM cake_dish d
832
- LEFT JOIN cake_mealtype mt ON d.dish_mealtype_id = mt.mealtype_id
833
- LEFT JOIN event e ON d.dish_event_id = e.event_id;
834
-
835
- -- ❌ WRONG: Missing table prefix in WHERE clause
836
- SELECT d.dish_id, d.dish_name
837
- FROM cake_dish d
838
- LEFT JOIN event e ON d.dish_event_id = e.event_id
839
- WHERE organisation_id = p_organisation_id; -- AMBIGUOUS: Which table?
840
-
841
- -- ❌ WRONG: Missing table prefix in ORDER BY
842
- SELECT d.dish_id, d.dish_name, e.event_name
843
- FROM cake_dish d
844
- LEFT JOIN event e ON d.dish_event_id = e.event_id
845
- ORDER BY created_at; -- AMBIGUOUS: Which table's created_at?
846
-
847
- -- ❌ WRONG: SELECT INTO with multiple columns but wrong variable count
848
- SELECT d.dish_code, d.dish_name, mt.mealtype_name
849
- INTO v_mealtype_name -- WRONG: Only one variable for three columns
850
- FROM cake_dish d
851
- LEFT JOIN cake_mealtype mt ON d.dish_mealtype_id = mt.mealtype_id;
852
- ```
853
-
854
- ### SELECT INTO Statements
855
-
856
- When using `SELECT ... INTO`, ensure:
857
- 1. The number of columns matches the number of variables
858
- 2. All columns are properly prefixed with table aliases
859
- 3. Use separate variables for each column
860
-
861
- ```sql
862
- -- ✅ CORRECT: Proper SELECT INTO with multiple variables
863
- DECLARE
864
- v_dish_code TEXT;
865
- v_dish_name TEXT;
866
- v_mealtype_name TEXT;
867
- v_updated_at TIMESTAMPTZ;
868
- BEGIN
869
- SELECT
870
- d.dish_code,
871
- d.dish_name,
872
- mt.mealtype_name,
873
- d.updated_at
874
- INTO
875
- v_dish_code,
876
- v_dish_name,
877
- v_mealtype_name,
878
- v_updated_at
879
- FROM cake_dish d
880
- LEFT JOIN cake_mealtype mt ON d.dish_mealtype_id = mt.mealtype_id
881
- WHERE d.dish_id = p_dish_id;
882
- END;
883
- ```
884
-
885
- ### CTEs and Subqueries
886
-
887
- When using CTEs (Common Table Expressions) or subqueries:
888
- 1. Use descriptive aliases for CTEs
889
- 2. Fully qualify all column references within CTEs
890
- 3. When referencing CTEs in the main query, use the CTE alias
891
-
892
- ```sql
893
- -- ✅ CORRECT: CTE with proper aliases
894
- WITH unit_diners AS (
895
- SELECT
896
- d.diner_unit_id,
897
- d.diner_diettype_id,
898
- SUM(COALESCE(d.diner_adult, 0)) as adults,
899
- SUM(COALESCE(d.diner_youth, 0)) as youth
900
- FROM cake_diner d
901
- INNER JOIN event_units eu ON d.diner_unit_id = eu.unit_id
902
- WHERE (d.diner_adult > 0 OR d.diner_youth > 0)
903
- GROUP BY d.diner_unit_id, d.diner_diettype_id
904
- )
905
- SELECT
906
- ud.diner_unit_id,
907
- ud.adults,
908
- ud.youth
909
- FROM unit_diners ud
910
- WHERE ud.diner_unit_id = p_unit_id;
911
- ```
912
-
913
- ### Table Alias Naming Conventions
914
-
915
- Use short, descriptive aliases:
916
- - `d` for `cake_dish`
917
- - `r` for `cake_recipe`
918
- - `m` for `cake_meal`
919
- - `mt` for `cake_mealtype`
920
- - `i` for `cake_item`
921
- - `dt` for `cake_diettype`
922
- - `e` for `event`
923
- - `u` for `cake_unit`
924
- - `mp` for `cake_mealplan`
925
-
926
- ### UPDATE Statements
927
-
928
- For UPDATE statements, the WHERE clause should reference the table being updated:
929
-
930
- ```sql
931
- -- ✅ CORRECT: WHERE clause uses table name or alias
932
- UPDATE cake_dish
933
- SET dish_name = p_dish_name,
934
- updated_by = p_user_id,
935
- updated_at = now()
936
- WHERE dish_id = p_dish_id; -- dish_id is unambiguous (primary key)
937
-
938
- -- ✅ CORRECT: When updating with JOIN, qualify all columns
939
- UPDATE cake_dish d
940
- SET d.dish_name = p_dish_name
941
- FROM cake_mealtype mt
942
- WHERE d.dish_mealtype_id = mt.mealtype_id
943
- AND d.dish_id = p_dish_id;
944
- ```
945
-
946
- ### Testing for Ambiguous References
947
-
948
- Before deploying, test your function:
949
- 1. Call the function with valid parameters
950
- 2. Check PostgreSQL logs for "ambiguous column reference" errors
951
- 3. Verify all column references are prefixed in JOINs
952
- 4. Test with multiple tables that share column names
953
-
954
- ## Common Patterns
955
-
956
- ### Pattern 1: Simple Data Retrieval
957
-
958
- ```sql
959
- CREATE OR REPLACE FUNCTION data_entity_list(
960
- p_organisation_id UUID,
961
- p_user_id UUID DEFAULT auth.uid()
962
- )
963
- RETURNS TABLE(id UUID, name TEXT)
964
- LANGUAGE plpgsql
965
- SECURITY DEFINER
966
- SET search_path TO 'public'
967
- AS $$
968
- BEGIN
969
- -- Super admin check
970
- IF EXISTS(SELECT 1 FROM rbac_global_roles WHERE user_id = p_user_id AND role = 'super_admin') THEN
971
- RETURN QUERY SELECT id, name FROM entity;
972
- RETURN;
973
- END IF;
974
-
975
- -- Organisation check
976
- IF NOT EXISTS(SELECT 1 FROM rbac_organisation_roles WHERE user_id = p_user_id AND organisation_id = p_organisation_id) THEN
977
- RETURN;
978
- END IF;
979
-
980
- -- Return data
981
- RETURN QUERY
982
- SELECT id, name
983
- FROM entity
984
- WHERE organisation_id = p_organisation_id;
985
- END;
986
- $$;
987
- ```
988
-
989
- ### Pattern 2: Permission Check
990
-
991
- ```sql
992
- CREATE OR REPLACE FUNCTION rbac_check_permission(
993
- p_user_id UUID,
994
- p_permission TEXT,
995
- p_organisation_id UUID
996
- )
997
- RETURNS BOOLEAN
998
- LANGUAGE plpgsql
999
- SECURITY DEFINER
1000
- SET search_path TO 'public'
1001
- AS $$
1002
- DECLARE
1003
- v_has_permission BOOLEAN := false;
1004
- BEGIN
1005
- -- Super admin has all permissions
1006
- IF EXISTS(SELECT 1 FROM rbac_global_roles WHERE user_id = p_user_id AND role = 'super_admin') THEN
1007
- RETURN true;
1008
- END IF;
1009
-
1010
- -- Check permission
1011
- SELECT EXISTS(
1012
- SELECT 1 FROM rbac_page_permissions pp
1013
- JOIN rbac_organisation_roles ror ON pp.organisation_id = ror.organisation_id
1014
- WHERE ror.user_id = p_user_id
1015
- AND ror.organisation_id = p_organisation_id
1016
- AND pp.operation = split_part(p_permission, ':', 1)
1017
- AND pp.allowed = true
1018
- ) INTO v_has_permission;
1019
-
1020
- RETURN COALESCE(v_has_permission, false);
1021
- END;
1022
- $$;
1023
- ```
1024
-
1025
- ### Pattern 3: Complex Calculation
1026
-
1027
- ```sql
1028
- CREATE OR REPLACE FUNCTION app_cake_distribution_calculate(
1029
- p_event_id TEXT,
1030
- p_user_id UUID DEFAULT auth.uid(),
1031
- p_organisation_id UUID DEFAULT NULL
1032
- )
1033
- RETURNS TABLE(...)
1034
- LANGUAGE plpgsql
1035
- SECURITY DEFINER
1036
- SET search_path TO 'public'
1037
- AS $$
1038
- DECLARE
1039
- v_is_super_admin BOOLEAN;
1040
- BEGIN
1041
- -- Security checks
1042
- ...
1043
-
1044
- -- Use CTEs for complex logic
1045
- WITH event_units AS (
1046
- SELECT unit_id FROM cake_unit WHERE unit_event_id = p_event_id
1047
- ),
1048
- unit_diners AS (
1049
- SELECT ... FROM cake_diner WHERE diner_unit_id IN (SELECT unit_id FROM event_units)
1050
- )
1051
- SELECT ...;
1052
- END;
1053
- $$;
1054
- ```
1055
-
1056
- ## Summary Checklist
1057
-
1058
- When creating or reviewing an RPC function, ensure:
1059
-
1060
- ### Function Structure
1061
- - ✅ Follows naming convention: `<family>_<domain>_<verb>`
1062
- - ✅ Uses `SECURITY DEFINER`
1063
- - ✅ Sets `search_path TO 'public'`
1064
- - ✅ Validates all inputs
1065
- - ✅ Checks super_admin status (if applicable)
1066
- - ✅ Validates organisation membership (if applicable)
1067
- - ✅ Validates event access (if event-scoped)
1068
- - ✅ Uses proper error handling with `EXCEPTION WHEN OTHERS`
1069
- - ✅ Returns empty on error (fail-secure)
1070
- - ✅ Has documentation comments
1071
- - ✅ Uses descriptive parameter names (`p_` prefix)
1072
- - ✅ Uses descriptive variable names (`v_` prefix)
1073
- - ✅ Has appropriate return type
1074
- - ✅ Includes `GRANT EXECUTE` statement
1075
- - ✅ Tested with various scenarios
1076
-
1077
- ### ⚠️ Critical Parameter Type Requirements
1078
- - ✅ **String parameters use TEXT**: All string parameters MUST use `TEXT`, NOT `CHARACTER VARYING` or `VARCHAR`
1079
- - ✅ **No duplicate function versions**: Only one version of each function exists (TEXT version, not CHARACTER VARYING)
1080
- - ✅ **Numeric parameters use correct types**: `DOUBLE PRECISION` for decimals, `INTEGER` for whole numbers, `SMALLINT` for small integers
1081
- - ✅ **Why TEXT?**: Application code calls with TEXT parameters; having both TEXT and CHARACTER VARYING versions causes ambiguity errors
1082
-
1083
- ### ⚠️ Critical Permission Format
1084
- - ✅ **Permission format is correct**: `'operation:page.{pageName}'` (e.g., `'create:page.dishes'`, `'read:page.meals'`)
1085
- - ✅ **NOT using wrong format**: `'operation:resource'` (e.g., `'create:dishes'`, `'read:meals'`)
1086
- - ✅ **Page name parameter provided**: Last parameter is the page name (e.g., `'dishes'`, `'meals'`)
1087
- - ✅ **Permission format matches rbac_permissions_get output**: Verify by checking existing working migrations
1088
-
1089
- ### ⚠️ Migration File Requirements
1090
- - ✅ **New timestamp generated**: Run `date +%Y%m%d%H%M%S` to get current timestamp
1091
- - ✅ **New file created**: Never reuse timestamps from previous migrations
1092
- - ✅ **File naming**: `YYYYMMDDHHMMSS_descriptive_name.sql`
1093
- - ✅ **No ambiguous column references**: Fully qualify table names (e.g., `cake_mealtype.mealtype_name`)
1094
-
1095
- ### ⚠️ Column Reference Requirements
1096
- - ✅ **All column references in JOINs are fully qualified with table aliases**: Every column in SELECT, WHERE, ORDER BY, GROUP BY, HAVING must have table prefix
1097
- - ✅ **No ambiguous column references in WHERE, ORDER BY, GROUP BY, HAVING clauses**: All columns must be prefixed with table alias
1098
- - ✅ **Table aliases used consistently and meaningfully**: Use short, descriptive aliases (e.g., `d` for dish, `r` for recipe)
1099
- - ✅ **SELECT INTO statements match variable count**: Number of columns must match number of variables
1100
-
1101
- ## References
1102
-
1103
- - [RBAC System Documentation](../core-concepts/rbac-system.md)
1104
- - [Database Schema Requirements](./database-schema-requirements.md)
1105
- - [Security Architecture](./rbac-security-architecture.md)
1106
-