@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,41 +1,101 @@
1
+ import {
2
+ createLogger
3
+ } from "./chunk-PWLANIRT.js";
1
4
 
2
- /**
3
- * @file Secure Storage Utilities
4
- * @description Encrypted storage wrapper for sensitive data
5
- */
6
-
7
- export interface SecureStorageOptions {
8
- encrypt?: boolean;
9
- expiry?: number; // TTL in milliseconds
5
+ // src/utils/context/organisationContext.ts
6
+ var log = createLogger("organisationContext");
7
+ async function setOrganisationContext(supabase, organisationId) {
8
+ if (!supabase || !organisationId) {
9
+ return;
10
+ }
11
+ try {
12
+ const timeoutPromise = new Promise((_, reject) => {
13
+ setTimeout(() => reject(new Error("RPC timeout after 3 seconds")), 3e3);
14
+ });
15
+ const rpcPromise = supabase.rpc("set_organisation_context", {
16
+ org_id: organisationId
17
+ });
18
+ const { error } = await Promise.race([rpcPromise, timeoutPromise]);
19
+ if (error) {
20
+ log.debug("RPC function not available or failed, continuing without database context");
21
+ } else {
22
+ log.debug("Organisation context set in database successfully");
23
+ }
24
+ } catch (error) {
25
+ log.debug("Failed to set database context, continuing without it:", error);
26
+ }
27
+ }
28
+ async function clearOrganisationContext(supabase) {
29
+ if (!supabase) {
30
+ return;
31
+ }
32
+ try {
33
+ const { error } = await supabase.rpc("rbac_audit_log", {
34
+ p_event_type: "organisation_switched",
35
+ p_metadata: { action: "clear_context" }
36
+ });
37
+ if (error) {
38
+ } else {
39
+ }
40
+ } catch (error) {
41
+ }
42
+ }
43
+ async function getOrganisationContext(supabase) {
44
+ if (!supabase) {
45
+ return null;
46
+ }
47
+ try {
48
+ const data = null;
49
+ const error = null;
50
+ if (error) {
51
+ return null;
52
+ }
53
+ if (typeof data === "string") {
54
+ return data;
55
+ }
56
+ return null;
57
+ } catch (error) {
58
+ return null;
59
+ }
60
+ }
61
+ async function isOrganisationContextAvailable(supabase) {
62
+ if (!supabase) {
63
+ return false;
64
+ }
65
+ try {
66
+ const { error } = await supabase.rpc("get_organisation_context");
67
+ if (error) {
68
+ return false;
69
+ }
70
+ return true;
71
+ } catch (error) {
72
+ return false;
73
+ }
10
74
  }
11
75
 
12
- /**
13
- * Secure storage implementation with encryption support
14
- */
15
- class SecureStorageImpl {
16
- private encryptionKey: CryptoKey | null = null;
17
- private initialized = false;
18
-
76
+ // src/utils/security/secureStorage.ts
77
+ var SecureStorageImpl = class {
78
+ constructor() {
79
+ this.encryptionKey = null;
80
+ this.initialized = false;
81
+ }
19
82
  /**
20
83
  * Initialize secure storage with encryption
21
84
  */
22
- async init(): Promise<void> {
85
+ async init() {
23
86
  if (this.initialized) return;
24
-
25
87
  try {
26
- // Check if Web Crypto API is available
27
88
  if (window.crypto && window.crypto.subtle) {
28
- // Generate or retrieve encryption key
29
- const keyData = localStorage.getItem('_sec_key');
89
+ const keyData = localStorage.getItem("_sec_key");
30
90
  if (keyData) {
31
91
  try {
32
92
  const keyBuffer = this.base64ToArrayBuffer(keyData);
33
93
  this.encryptionKey = await window.crypto.subtle.importKey(
34
- 'raw',
94
+ "raw",
35
95
  keyBuffer,
36
- { name: 'AES-GCM' },
96
+ { name: "AES-GCM" },
37
97
  false,
38
- ['encrypt', 'decrypt']
98
+ ["encrypt", "decrypt"]
39
99
  );
40
100
  } catch (error) {
41
101
  await this.generateNewKey();
@@ -49,189 +109,146 @@ class SecureStorageImpl {
49
109
  this.initialized = true;
50
110
  }
51
111
  }
52
-
53
112
  /**
54
113
  * Store item securely
55
114
  */
56
- async setItem(
57
- key: string,
58
- value: string,
59
- options: SecureStorageOptions = {}
60
- ): Promise<void> {
115
+ async setItem(key, value, options = {}) {
61
116
  await this.init();
62
-
63
117
  const data = {
64
118
  value,
65
119
  timestamp: Date.now(),
66
- expiry: options.expiry ? Date.now() + options.expiry : undefined,
120
+ expiry: options.expiry ? Date.now() + options.expiry : void 0
67
121
  };
68
-
69
122
  const serialized = JSON.stringify(data);
70
-
71
123
  if (options.encrypt && this.encryptionKey) {
72
124
  try {
73
125
  const encrypted = await this.encrypt(serialized);
74
126
  localStorage.setItem(`_sec_${key}`, encrypted);
75
127
  return;
76
128
  } catch (error) {
77
- // Silent fail - store as plain text
78
129
  }
79
130
  }
80
-
81
131
  localStorage.setItem(key, serialized);
82
132
  }
83
-
84
133
  /**
85
134
  * Retrieve item securely
86
135
  */
87
- async getItem(key: string): Promise<string | null> {
136
+ async getItem(key) {
88
137
  await this.init();
89
-
90
- // Try encrypted storage first
91
138
  const encryptedData = localStorage.getItem(`_sec_${key}`);
92
139
  if (encryptedData && this.encryptionKey) {
93
140
  try {
94
141
  const decrypted = await this.decrypt(encryptedData);
95
142
  const parsed = JSON.parse(decrypted);
96
-
97
- // Check expiry
98
143
  if (parsed.expiry && Date.now() > parsed.expiry) {
99
144
  await this.removeItem(key);
100
145
  return null;
101
146
  }
102
-
103
147
  return parsed.value;
104
148
  } catch (error) {
105
- // Silent fail - try plain storage
106
149
  }
107
150
  }
108
-
109
- // Fallback to plain storage
110
151
  const plainData = localStorage.getItem(key);
111
152
  if (!plainData) return null;
112
-
113
153
  try {
114
154
  const parsed = JSON.parse(plainData);
115
-
116
- // Check expiry
117
155
  if (parsed.expiry && Date.now() > parsed.expiry) {
118
156
  await this.removeItem(key);
119
157
  return null;
120
158
  }
121
-
122
159
  return parsed.value || plainData;
123
160
  } catch (error) {
124
- // If parsing fails, return as-is (backward compatibility)
125
161
  return plainData;
126
162
  }
127
163
  }
128
-
129
164
  /**
130
165
  * Remove item
131
166
  */
132
- async removeItem(key: string): Promise<void> {
167
+ async removeItem(key) {
133
168
  localStorage.removeItem(key);
134
169
  localStorage.removeItem(`_sec_${key}`);
135
170
  }
136
-
137
171
  /**
138
172
  * Clear all secure storage
139
173
  */
140
- async clear(): Promise<void> {
174
+ async clear() {
141
175
  const keys = Object.keys(localStorage);
142
176
  for (const key of keys) {
143
- if (key.startsWith('_sec_')) {
177
+ if (key.startsWith("_sec_")) {
144
178
  localStorage.removeItem(key);
145
179
  }
146
180
  }
147
181
  }
148
-
149
182
  /**
150
183
  * Generate new encryption key
151
184
  */
152
- private async generateNewKey(): Promise<void> {
185
+ async generateNewKey() {
153
186
  if (!window.crypto?.subtle) return;
154
-
155
187
  try {
156
188
  this.encryptionKey = await window.crypto.subtle.generateKey(
157
- { name: 'AES-GCM', length: 256 },
189
+ { name: "AES-GCM", length: 256 },
158
190
  true,
159
- ['encrypt', 'decrypt']
191
+ ["encrypt", "decrypt"]
160
192
  );
161
-
162
- // Export and store key
163
- const exportedKey = await window.crypto.subtle.exportKey('raw', this.encryptionKey);
193
+ const exportedKey = await window.crypto.subtle.exportKey("raw", this.encryptionKey);
164
194
  const keyData = this.arrayBufferToBase64(exportedKey);
165
- localStorage.setItem('_sec_key', keyData);
195
+ localStorage.setItem("_sec_key", keyData);
166
196
  } catch (error) {
167
- // Silent fail - encryption not available
168
197
  }
169
198
  }
170
-
171
199
  /**
172
200
  * Encrypt data
173
201
  */
174
- private async encrypt(data: string): Promise<string> {
202
+ async encrypt(data) {
175
203
  if (!this.encryptionKey || !window.crypto?.subtle) {
176
- throw new Error('Encryption not available');
204
+ throw new Error("Encryption not available");
177
205
  }
178
-
179
206
  const encoder = new TextEncoder();
180
207
  const dataBuffer = encoder.encode(data);
181
208
  const iv = window.crypto.getRandomValues(new Uint8Array(12));
182
-
183
209
  const encrypted = await window.crypto.subtle.encrypt(
184
- { name: 'AES-GCM', iv },
210
+ { name: "AES-GCM", iv },
185
211
  this.encryptionKey,
186
212
  dataBuffer
187
213
  );
188
-
189
- // Combine IV and encrypted data
190
214
  const combined = new Uint8Array(iv.length + encrypted.byteLength);
191
215
  combined.set(iv);
192
216
  combined.set(new Uint8Array(encrypted), iv.length);
193
-
194
217
  return this.arrayBufferToBase64(combined.buffer);
195
218
  }
196
-
197
219
  /**
198
220
  * Decrypt data
199
221
  */
200
- private async decrypt(encryptedData: string): Promise<string> {
222
+ async decrypt(encryptedData) {
201
223
  if (!this.encryptionKey || !window.crypto?.subtle) {
202
- throw new Error('Decryption not available');
224
+ throw new Error("Decryption not available");
203
225
  }
204
-
205
226
  const combined = this.base64ToArrayBuffer(encryptedData);
206
227
  const iv = combined.slice(0, 12);
207
228
  const encrypted = combined.slice(12);
208
-
209
229
  const decrypted = await window.crypto.subtle.decrypt(
210
- { name: 'AES-GCM', iv },
230
+ { name: "AES-GCM", iv },
211
231
  this.encryptionKey,
212
232
  encrypted
213
233
  );
214
-
215
234
  const decoder = new TextDecoder();
216
235
  return decoder.decode(decrypted);
217
236
  }
218
-
219
237
  /**
220
238
  * Convert ArrayBuffer to base64
221
239
  */
222
- private arrayBufferToBase64(buffer: ArrayBuffer): string {
240
+ arrayBufferToBase64(buffer) {
223
241
  const bytes = new Uint8Array(buffer);
224
- let binary = '';
242
+ let binary = "";
225
243
  for (let i = 0; i < bytes.byteLength; i++) {
226
244
  binary += String.fromCharCode(bytes[i]);
227
245
  }
228
246
  return btoa(binary);
229
247
  }
230
-
231
248
  /**
232
249
  * Convert base64 to ArrayBuffer
233
250
  */
234
- private base64ToArrayBuffer(base64: string): ArrayBuffer {
251
+ base64ToArrayBuffer(base64) {
235
252
  const binary = atob(base64);
236
253
  const bytes = new Uint8Array(binary.length);
237
254
  for (let i = 0; i < binary.length; i++) {
@@ -239,6 +256,14 @@ class SecureStorageImpl {
239
256
  }
240
257
  return bytes.buffer;
241
258
  }
242
- }
259
+ };
260
+ var secureStorage = new SecureStorageImpl();
243
261
 
244
- export const secureStorage = new SecureStorageImpl();
262
+ export {
263
+ setOrganisationContext,
264
+ clearOrganisationContext,
265
+ getOrganisationContext,
266
+ isOrganisationContextAvailable,
267
+ secureStorage
268
+ };
269
+ //# sourceMappingURL=chunk-VBXEHIUJ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/context/organisationContext.ts","../src/utils/security/secureStorage.ts"],"sourcesContent":["/**\n * @file Organisation Context Utility\n * @package @jmruthers/pace-core\n * @module Utils/OrganisationContext\n * @since 0.4.0\n *\n * Utility functions for managing organisation context in database sessions.\n * Provides fallback mechanisms for when database functions are not available.\n */\n\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport { createLogger } from '../core/logger';\n\nconst log = createLogger('organisationContext');\n\n/**\n * Set organisation context in the database session\n * \n * This function attempts to set the organisation context using a database function.\n * If the function is not available, it falls back gracefully without throwing errors.\n * \n * @param supabase - Supabase client instance\n * @param organisationId - The organisation ID to set as context\n * @returns Promise that resolves when context is set (or falls back gracefully)\n */\nexport async function setOrganisationContext(\n supabase: SupabaseClient,\n organisationId: string\n): Promise<void> {\n if (!supabase || !organisationId) {\n // TODO: Replace with proper logging service integration\n return;\n }\n\n try {\n // Add timeout to prevent hanging RPC calls\n const timeoutPromise = new Promise((_, reject) => {\n setTimeout(() => reject(new Error('RPC timeout after 3 seconds')), 3000);\n });\n \n // Call the database function to set organisation context\n const rpcPromise = supabase.rpc('set_organisation_context', {\n org_id: organisationId\n });\n\n const { error } = await Promise.race([rpcPromise, timeoutPromise]) as any;\n\n if (error) {\n // Function might not exist yet - this is expected during migration\n // Silent fail - will fall back to client-side filtering\n log.debug('RPC function not available or failed, continuing without database context');\n } else {\n log.debug('Organisation context set in database successfully');\n }\n } catch (error) {\n // Handle any other errors gracefully\n // Silent fail - will fall back to client-side filtering\n log.debug('Failed to set database context, continuing without it:', error);\n }\n}\n\n/**\n * Clear organisation context from the database session\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves when context is cleared\n */\nexport async function clearOrganisationContext(\n supabase: SupabaseClient\n): Promise<void> {\n if (!supabase) {\n // TODO: Replace with proper logging service integration\n return;\n }\n\n try {\n const { error } = await supabase.rpc('rbac_audit_log', {\n p_event_type: 'organisation_switched',\n p_metadata: { action: 'clear_context' }\n });\n \n if (error) {\n // Silent fail - function not available\n // TODO: Replace with proper logging service integration\n } else {\n // TODO: Replace with proper logging service integration\n }\n } catch (error) {\n // Silent fail - error occurred\n // TODO: Replace with proper logging service integration\n }\n}\n\n/**\n * Get current organisation context from the database session\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves to the current organisation ID or null\n */\nexport async function getOrganisationContext(\n supabase: SupabaseClient\n): Promise<string | null> {\n if (!supabase) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n\n try {\n // For now, return null since we're not using database context\n // This will be replaced with proper context management\n const data = null;\n const error = null;\n \n if (error) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n \n // Validate that data is a string (allow empty strings)\n if (typeof data === 'string') {\n return data;\n }\n \n // Return null for invalid data formats\n return null;\n } catch (error) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n}\n\n/**\n * Check if organisation context functions are available in the database\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves to true if functions are available\n */\nexport async function isOrganisationContextAvailable(\n supabase: SupabaseClient\n): Promise<boolean> {\n if (!supabase) {\n return false;\n }\n\n try {\n const { error } = await supabase.rpc('get_organisation_context');\n \n if (error) {\n return false;\n }\n \n return true;\n } catch (error) {\n return false;\n }\n} ","\n/**\n * @file Secure Storage Utilities\n * @description Encrypted storage wrapper for sensitive data\n */\n\nexport interface SecureStorageOptions {\n encrypt?: boolean;\n expiry?: number; // TTL in milliseconds\n}\n\n/**\n * Secure storage implementation with encryption support\n */\nclass SecureStorageImpl {\n private encryptionKey: CryptoKey | null = null;\n private initialized = false;\n\n /**\n * Initialize secure storage with encryption\n */\n async init(): Promise<void> {\n if (this.initialized) return;\n\n try {\n // Check if Web Crypto API is available\n if (window.crypto && window.crypto.subtle) {\n // Generate or retrieve encryption key\n const keyData = localStorage.getItem('_sec_key');\n if (keyData) {\n try {\n const keyBuffer = this.base64ToArrayBuffer(keyData);\n this.encryptionKey = await window.crypto.subtle.importKey(\n 'raw',\n keyBuffer,\n { name: 'AES-GCM' },\n false,\n ['encrypt', 'decrypt']\n );\n } catch (error) {\n await this.generateNewKey();\n }\n } else {\n await this.generateNewKey();\n }\n }\n this.initialized = true;\n } catch (error) {\n this.initialized = true;\n }\n }\n\n /**\n * Store item securely\n */\n async setItem(\n key: string,\n value: string,\n options: SecureStorageOptions = {}\n ): Promise<void> {\n await this.init();\n\n const data = {\n value,\n timestamp: Date.now(),\n expiry: options.expiry ? Date.now() + options.expiry : undefined,\n };\n\n const serialized = JSON.stringify(data);\n \n if (options.encrypt && this.encryptionKey) {\n try {\n const encrypted = await this.encrypt(serialized);\n localStorage.setItem(`_sec_${key}`, encrypted);\n return;\n } catch (error) {\n // Silent fail - store as plain text\n }\n }\n\n localStorage.setItem(key, serialized);\n }\n\n /**\n * Retrieve item securely\n */\n async getItem(key: string): Promise<string | null> {\n await this.init();\n\n // Try encrypted storage first\n const encryptedData = localStorage.getItem(`_sec_${key}`);\n if (encryptedData && this.encryptionKey) {\n try {\n const decrypted = await this.decrypt(encryptedData);\n const parsed = JSON.parse(decrypted);\n \n // Check expiry\n if (parsed.expiry && Date.now() > parsed.expiry) {\n await this.removeItem(key);\n return null;\n }\n \n return parsed.value;\n } catch (error) {\n // Silent fail - try plain storage\n }\n }\n\n // Fallback to plain storage\n const plainData = localStorage.getItem(key);\n if (!plainData) return null;\n\n try {\n const parsed = JSON.parse(plainData);\n \n // Check expiry\n if (parsed.expiry && Date.now() > parsed.expiry) {\n await this.removeItem(key);\n return null;\n }\n \n return parsed.value || plainData;\n } catch (error) {\n // If parsing fails, return as-is (backward compatibility)\n return plainData;\n }\n }\n\n /**\n * Remove item\n */\n async removeItem(key: string): Promise<void> {\n localStorage.removeItem(key);\n localStorage.removeItem(`_sec_${key}`);\n }\n\n /**\n * Clear all secure storage\n */\n async clear(): Promise<void> {\n const keys = Object.keys(localStorage);\n for (const key of keys) {\n if (key.startsWith('_sec_')) {\n localStorage.removeItem(key);\n }\n }\n }\n\n /**\n * Generate new encryption key\n */\n private async generateNewKey(): Promise<void> {\n if (!window.crypto?.subtle) return;\n\n try {\n this.encryptionKey = await window.crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n true,\n ['encrypt', 'decrypt']\n );\n\n // Export and store key\n const exportedKey = await window.crypto.subtle.exportKey('raw', this.encryptionKey);\n const keyData = this.arrayBufferToBase64(exportedKey);\n localStorage.setItem('_sec_key', keyData);\n } catch (error) {\n // Silent fail - encryption not available\n }\n }\n\n /**\n * Encrypt data\n */\n private async encrypt(data: string): Promise<string> {\n if (!this.encryptionKey || !window.crypto?.subtle) {\n throw new Error('Encryption not available');\n }\n\n const encoder = new TextEncoder();\n const dataBuffer = encoder.encode(data);\n const iv = window.crypto.getRandomValues(new Uint8Array(12));\n\n const encrypted = await window.crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n this.encryptionKey,\n dataBuffer\n );\n\n // Combine IV and encrypted data\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\n combined.set(iv);\n combined.set(new Uint8Array(encrypted), iv.length);\n\n return this.arrayBufferToBase64(combined.buffer);\n }\n\n /**\n * Decrypt data\n */\n private async decrypt(encryptedData: string): Promise<string> {\n if (!this.encryptionKey || !window.crypto?.subtle) {\n throw new Error('Decryption not available');\n }\n\n const combined = this.base64ToArrayBuffer(encryptedData);\n const iv = combined.slice(0, 12);\n const encrypted = combined.slice(12);\n\n const decrypted = await window.crypto.subtle.decrypt(\n { name: 'AES-GCM', iv },\n this.encryptionKey,\n encrypted\n );\n\n const decoder = new TextDecoder();\n return decoder.decode(decrypted);\n }\n\n /**\n * Convert ArrayBuffer to base64\n */\n private arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n\n /**\n * Convert base64 to ArrayBuffer\n */\n private base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n }\n}\n\nexport const secureStorage = new SecureStorageImpl();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/utils/context/organisationContext.ts","../src/utils/security/secureStorage.ts"],"sourcesContent":["/**\n * @file Organisation Context Utility\n * @package @jmruthers/pace-core\n * @module Utils/OrganisationContext\n * @since 0.4.0\n *\n * Utility functions for managing organisation context in database sessions.\n * Provides fallback mechanisms for when database functions are not available.\n */\n\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport { createLogger } from '../core/logger';\n\nconst log = createLogger('organisationContext');\n\n/**\n * Set organisation context in the database session\n * \n * This function attempts to set the organisation context using a database function.\n * If the function is not available, it falls back gracefully without throwing errors.\n * \n * @param supabase - Supabase client instance\n * @param organisationId - The organisation ID to set as context\n * @returns Promise that resolves when context is set (or falls back gracefully)\n */\nexport async function setOrganisationContext(\n supabase: SupabaseClient,\n organisationId: string\n): Promise<void> {\n if (!supabase || !organisationId) {\n // TODO: Replace with proper logging service integration\n return;\n }\n\n try {\n // Add timeout to prevent hanging RPC calls\n const timeoutPromise = new Promise((_, reject) => {\n setTimeout(() => reject(new Error('RPC timeout after 3 seconds')), 3000);\n });\n \n // Call the database function to set organisation context\n const rpcPromise = supabase.rpc('set_organisation_context', {\n org_id: organisationId\n });\n\n const { error } = await Promise.race([rpcPromise, timeoutPromise]) as any;\n\n if (error) {\n // Function might not exist yet - this is expected during migration\n // Silent fail - will fall back to client-side filtering\n log.debug('RPC function not available or failed, continuing without database context');\n } else {\n log.debug('Organisation context set in database successfully');\n }\n } catch (error) {\n // Handle any other errors gracefully\n // Silent fail - will fall back to client-side filtering\n log.debug('Failed to set database context, continuing without it:', error);\n }\n}\n\n/**\n * Clear organisation context from the database session\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves when context is cleared\n */\nexport async function clearOrganisationContext(\n supabase: SupabaseClient\n): Promise<void> {\n if (!supabase) {\n // TODO: Replace with proper logging service integration\n return;\n }\n\n try {\n const { error } = await supabase.rpc('rbac_audit_log', {\n p_event_type: 'organisation_switched',\n p_metadata: { action: 'clear_context' }\n });\n \n if (error) {\n // Silent fail - function not available\n // TODO: Replace with proper logging service integration\n } else {\n // TODO: Replace with proper logging service integration\n }\n } catch (error) {\n // Silent fail - error occurred\n // TODO: Replace with proper logging service integration\n }\n}\n\n/**\n * Get current organisation context from the database session\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves to the current organisation ID or null\n */\nexport async function getOrganisationContext(\n supabase: SupabaseClient\n): Promise<string | null> {\n if (!supabase) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n\n try {\n // For now, return null since we're not using database context\n // This will be replaced with proper context management\n const data = null;\n const error = null;\n \n if (error) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n \n // Validate that data is a string (allow empty strings)\n if (typeof data === 'string') {\n return data;\n }\n \n // Return null for invalid data formats\n return null;\n } catch (error) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n}\n\n/**\n * Check if organisation context functions are available in the database\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves to true if functions are available\n */\nexport async function isOrganisationContextAvailable(\n supabase: SupabaseClient\n): Promise<boolean> {\n if (!supabase) {\n return false;\n }\n\n try {\n const { error } = await supabase.rpc('get_organisation_context');\n \n if (error) {\n return false;\n }\n \n return true;\n } catch (error) {\n return false;\n }\n} ","\n/**\n * @file Secure Storage Utilities\n * @description Encrypted storage wrapper for sensitive data\n */\n\nexport interface SecureStorageOptions {\n encrypt?: boolean;\n expiry?: number; // TTL in milliseconds\n}\n\n/**\n * Secure storage implementation with encryption support\n */\nclass SecureStorageImpl {\n private encryptionKey: CryptoKey | null = null;\n private initialized = false;\n\n /**\n * Initialize secure storage with encryption\n */\n async init(): Promise<void> {\n if (this.initialized) return;\n\n try {\n // Check if Web Crypto API is available\n if (window.crypto && window.crypto.subtle) {\n // Generate or retrieve encryption key\n const keyData = localStorage.getItem('_sec_key');\n if (keyData) {\n try {\n const keyBuffer = this.base64ToArrayBuffer(keyData);\n this.encryptionKey = await window.crypto.subtle.importKey(\n 'raw',\n keyBuffer,\n { name: 'AES-GCM' },\n false,\n ['encrypt', 'decrypt']\n );\n } catch (error) {\n await this.generateNewKey();\n }\n } else {\n await this.generateNewKey();\n }\n }\n this.initialized = true;\n } catch (error) {\n this.initialized = true;\n }\n }\n\n /**\n * Store item securely\n */\n async setItem(\n key: string,\n value: string,\n options: SecureStorageOptions = {}\n ): Promise<void> {\n await this.init();\n\n const data = {\n value,\n timestamp: Date.now(),\n expiry: options.expiry ? Date.now() + options.expiry : undefined,\n };\n\n const serialized = JSON.stringify(data);\n \n if (options.encrypt && this.encryptionKey) {\n try {\n const encrypted = await this.encrypt(serialized);\n localStorage.setItem(`_sec_${key}`, encrypted);\n return;\n } catch (error) {\n // Silent fail - store as plain text\n }\n }\n\n localStorage.setItem(key, serialized);\n }\n\n /**\n * Retrieve item securely\n */\n async getItem(key: string): Promise<string | null> {\n await this.init();\n\n // Try encrypted storage first\n const encryptedData = localStorage.getItem(`_sec_${key}`);\n if (encryptedData && this.encryptionKey) {\n try {\n const decrypted = await this.decrypt(encryptedData);\n const parsed = JSON.parse(decrypted);\n \n // Check expiry\n if (parsed.expiry && Date.now() > parsed.expiry) {\n await this.removeItem(key);\n return null;\n }\n \n return parsed.value;\n } catch (error) {\n // Silent fail - try plain storage\n }\n }\n\n // Fallback to plain storage\n const plainData = localStorage.getItem(key);\n if (!plainData) return null;\n\n try {\n const parsed = JSON.parse(plainData);\n \n // Check expiry\n if (parsed.expiry && Date.now() > parsed.expiry) {\n await this.removeItem(key);\n return null;\n }\n \n return parsed.value || plainData;\n } catch (error) {\n // If parsing fails, return as-is (backward compatibility)\n return plainData;\n }\n }\n\n /**\n * Remove item\n */\n async removeItem(key: string): Promise<void> {\n localStorage.removeItem(key);\n localStorage.removeItem(`_sec_${key}`);\n }\n\n /**\n * Clear all secure storage\n */\n async clear(): Promise<void> {\n const keys = Object.keys(localStorage);\n for (const key of keys) {\n if (key.startsWith('_sec_')) {\n localStorage.removeItem(key);\n }\n }\n }\n\n /**\n * Generate new encryption key\n */\n private async generateNewKey(): Promise<void> {\n if (!window.crypto?.subtle) return;\n\n try {\n this.encryptionKey = await window.crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n true,\n ['encrypt', 'decrypt']\n );\n\n // Export and store key\n const exportedKey = await window.crypto.subtle.exportKey('raw', this.encryptionKey);\n const keyData = this.arrayBufferToBase64(exportedKey);\n localStorage.setItem('_sec_key', keyData);\n } catch (error) {\n // Silent fail - encryption not available\n }\n }\n\n /**\n * Encrypt data\n */\n private async encrypt(data: string): Promise<string> {\n if (!this.encryptionKey || !window.crypto?.subtle) {\n throw new Error('Encryption not available');\n }\n\n const encoder = new TextEncoder();\n const dataBuffer = encoder.encode(data);\n const iv = window.crypto.getRandomValues(new Uint8Array(12));\n\n const encrypted = await window.crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n this.encryptionKey,\n dataBuffer\n );\n\n // Combine IV and encrypted data\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\n combined.set(iv);\n combined.set(new Uint8Array(encrypted), iv.length);\n\n return this.arrayBufferToBase64(combined.buffer);\n }\n\n /**\n * Decrypt data\n */\n private async decrypt(encryptedData: string): Promise<string> {\n if (!this.encryptionKey || !window.crypto?.subtle) {\n throw new Error('Decryption not available');\n }\n\n const combined = this.base64ToArrayBuffer(encryptedData);\n const iv = combined.slice(0, 12);\n const encrypted = combined.slice(12);\n\n const decrypted = await window.crypto.subtle.decrypt(\n { name: 'AES-GCM', iv },\n this.encryptionKey,\n encrypted\n );\n\n const decoder = new TextDecoder();\n return decoder.decode(decrypted);\n }\n\n /**\n * Convert ArrayBuffer to base64\n */\n private arrayBufferToBase64(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n\n /**\n * Convert base64 to ArrayBuffer\n */\n private base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n }\n}\n\nexport const secureStorage = new SecureStorageImpl();\n"],"mappings":"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","names":[]}
@@ -1,27 +1,19 @@
1
1
  import {
2
- init_useOrganisations,
3
2
  useOrganisations
4
- } from "./chunk-LIMSTKYD.js";
3
+ } from "./chunk-QCDXODCA.js";
5
4
  import {
6
5
  EventServiceContext,
7
- init_EventServiceProvider,
8
6
  useUnifiedAuth
9
- } from "./chunk-3JI76CYK.js";
7
+ } from "./chunk-FUEYYMX5.js";
10
8
  import {
11
- init_organisationContext,
12
9
  setOrganisationContext
13
- } from "./chunk-7QCC6MCP.js";
10
+ } from "./chunk-VBXEHIUJ.js";
14
11
  import {
15
- init_logger,
16
12
  logger
17
- } from "./chunk-XDNLUEXI.js";
13
+ } from "./chunk-PWLANIRT.js";
18
14
 
19
15
  // src/hooks/useSecureDataAccess.ts
20
16
  import { useCallback, useState, useContext } from "react";
21
- init_useOrganisations();
22
- init_EventServiceProvider();
23
- init_organisationContext();
24
- init_logger();
25
17
  function useSecureDataAccess() {
26
18
  const { supabase, user, session } = useUnifiedAuth();
27
19
  const { ensureOrganisationContext } = useOrganisations();
@@ -394,4 +386,4 @@ function useSecureDataAccess() {
394
386
  export {
395
387
  useSecureDataAccess
396
388
  };
397
- //# sourceMappingURL=chunk-VZ4VDGTB.js.map
389
+ //# sourceMappingURL=chunk-W22JP75J.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/useSecureDataAccess.ts"],"sourcesContent":["/**\n * @file useSecureDataAccess Hook\n * @package @jmruthers/pace-core\n * @module Hooks/useSecureDataAccess\n * @since 0.4.0\n *\n * Hook for secure database operations with mandatory organisation context.\n * Ensures all data access is properly scoped to the user's current organisation.\n *\n * @example\n * ```tsx\n * function DataComponent() {\n * const { secureQuery, secureInsert, secureUpdate, secureDelete } = useSecureDataAccess();\n * \n * const loadData = async () => {\n * try {\n * // Automatically includes organisation_id filter\n * const events = await secureQuery('event', '*', { is_visible: true });\n * console.log('Organisation events:', events);\n * } catch (error) {\n * console.error('Failed to load data:', error);\n * }\n * };\n * \n * const createEvent = async (eventData) => {\n * try {\n * // Automatically sets organisation_id\n * const newEvent = await secureInsert('event', eventData);\n * console.log('Created event:', newEvent);\n * } catch (error) {\n * console.error('Failed to create event:', error);\n * }\n * };\n * \n * return (\n * <div>\n * <button onClick={loadData}>Load Data</button>\n * <button onClick={() => createEvent({ event_name: 'New Event' })}>\n * Create Event\n * </button>\n * </div>\n * );\n * }\n * ```\n *\n * @security\n * - All queries automatically include organisation_id filter\n * - Validates organisation context before any operation\n * - Prevents data leaks between organisations\n * - Error handling for security violations\n * - Type-safe database operations\n */\n\nimport { useCallback, useState, useContext } from 'react';\nimport { useUnifiedAuth } from '../providers';\nimport { useOrganisations } from './useOrganisations';\nimport { EventServiceContext } from '../providers/services/EventServiceProvider';\nimport { setOrganisationContext } from '../utils/context/organisationContext';\nimport { logger } from '../utils/core/logger';\nimport type { Permission } from '../rbac/types';\nimport type { OrganisationSecurityError } from '../types/organisation';\n\nexport interface SecureDataAccessReturn {\n /** Execute a secure query with organisation filtering */\n secureQuery: <T = any>(\n table: string,\n columns: string,\n filters?: Record<string, any>,\n options?: {\n orderBy?: string;\n ascending?: boolean;\n limit?: number;\n offset?: number;\n }\n ) => Promise<T[]>;\n \n /** Execute a secure insert with organisation context */\n secureInsert: <T = any>(\n table: string,\n data: Record<string, any>\n ) => Promise<T>;\n \n /** Execute a secure update with organisation filtering */\n secureUpdate: <T = any>(\n table: string,\n data: Record<string, any>,\n filters: Record<string, any>\n ) => Promise<T[]>;\n \n /** Execute a secure delete with organisation filtering */\n secureDelete: (\n table: string,\n filters: Record<string, any>\n ) => Promise<void>;\n \n /** Execute a secure RPC call with organisation context */\n secureRpc: <T = any>(\n functionName: string,\n params?: Record<string, any>\n ) => Promise<T>;\n \n /** Get current organisation ID */\n getCurrentOrganisationId: () => string;\n \n /** Validate organisation context */\n validateContext: () => void;\n \n // NEW: Phase 1 - Enhanced Security Features\n /** Check if data access is allowed for a table and operation */\n isDataAccessAllowed: (table: string, operation: string) => boolean;\n \n /** Get all data access permissions for current user */\n getDataAccessPermissions: () => Record<string, string[]>;\n \n /** Check if strict mode is enabled */\n isStrictMode: boolean;\n \n /** Check if audit logging is enabled */\n isAuditLogEnabled: boolean;\n \n /** Get data access history */\n getDataAccessHistory: () => DataAccessRecord[];\n \n /** Clear data access history */\n clearDataAccessHistory: () => void;\n \n /** Validate data access attempt */\n validateDataAccess: (table: string, operation: string) => boolean;\n}\n\nexport interface DataAccessRecord {\n table: string;\n operation: string;\n userId: string;\n organisationId: string;\n allowed: boolean;\n timestamp: string;\n query?: string;\n filters?: Record<string, any>;\n}\n\n/**\n * Hook for secure data access with automatic organisation filtering\n * \n * All database operations automatically include organisation context:\n * - Queries filter by organisation_id\n * - Inserts include organisation_id\n * - Updates/deletes are scoped to organisation\n * - RPC calls include organisation_id parameter\n */\nexport function useSecureDataAccess(): SecureDataAccessReturn {\n const { supabase, user, session } = useUnifiedAuth();\n const { ensureOrganisationContext } = useOrganisations();\n \n // Get selected event for event-scoped RPC calls\n // Use useContext directly to safely check if EventServiceProvider is available\n const eventServiceContext = useContext(EventServiceContext);\n const selectedEvent = eventServiceContext?.eventService?.getSelectedEvent() || null;\n\n const validateContext = useCallback((): void => {\n if (!supabase) {\n throw new Error('No Supabase client available') as OrganisationSecurityError;\n }\n if (!user || !session) {\n throw new Error('User must be authenticated with valid session') as OrganisationSecurityError;\n }\n \n try {\n ensureOrganisationContext();\n } catch (error) {\n throw new Error('Organisation context is required for data access') as OrganisationSecurityError;\n }\n }, [supabase, user, session, ensureOrganisationContext]);\n\n const getCurrentOrganisationId = useCallback((): string => {\n validateContext();\n const currentOrg = ensureOrganisationContext();\n return currentOrg.id;\n }, [validateContext, ensureOrganisationContext]);\n\n // Set organisation context in database session\n const setOrganisationContextInSession = useCallback(async (organisationId: string): Promise<void> => {\n if (!supabase) {\n throw new Error('No Supabase client available') as OrganisationSecurityError;\n }\n\n await setOrganisationContext(supabase, organisationId);\n }, [supabase]);\n\n const secureQuery = useCallback(async <T = any>(\n table: string,\n columns: string,\n filters: Record<string, any> = {},\n options: {\n orderBy?: string;\n ascending?: boolean;\n limit?: number;\n offset?: number;\n } = {}\n ): Promise<T[]> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Build query with organisation filter\n let query = supabase!\n .from(table)\n .select(columns);\n\n // Add organisation filter only if table has organisation_id column\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member',\n // SECURITY: Phase 3A additions - medical and personal data\n 'medi_profile', 'medi_condition', 'medi_diet', 'medi_action_plan', 'medi_profile_versions',\n 'pace_consent', 'pace_contact', 'pace_id_documents', 'pace_qualifications',\n 'form_responses', 'form_response_values', 'forms',\n // SECURITY: Phase 3B additions - remaining critical tables\n 'invoice', 'line_item', 'credit_balance', 'payment_method',\n 'form_contexts', 'form_field_config', 'form_fields',\n 'cake_delivery', 'cake_diettype', 'cake_diner', 'cake_dish', 'cake_item', \n 'cake_logistics', 'cake_mealplan', 'cake_package', 'cake_recipe', 'cake_supplier', \n 'cake_supply', 'cake_unit', 'event_app_access', 'base_application', 'base_questions'\n ];\n \n if (tablesWithOrganisation.includes(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n\n // Apply additional filters\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n // Handle qualified column names (e.g., 'users.role')\n const columnName = key.includes('.') ? key.split('.').pop()! : key;\n query = query.eq(columnName, value);\n }\n });\n\n // Apply options\n if (options.orderBy) {\n // Only use the column name, not a qualified name\n const orderByColumn = options.orderBy.split('.').pop();\n if (orderByColumn) {\n query = query.order(orderByColumn, { ascending: options.ascending ?? true });\n }\n }\n \n if (options.limit) {\n query = query.limit(options.limit);\n }\n \n if (options.offset) {\n query = query.range(options.offset, options.offset + (options.limit || 100) - 1);\n }\n\n const { data, error } = await query;\n \n if (error) {\n logger.error('useSecureDataAccess', 'Query failed', { table, columns, filters, error });\n // NEW: Phase 1 - Record failed data access attempt\n recordDataAccess(table, 'read', false, `SELECT ${columns} FROM ${table}`, filters);\n throw error;\n }\n\n // NEW: Phase 1 - Record successful data access attempt\n recordDataAccess(table, 'read', true, `SELECT ${columns} FROM ${table}`, filters);\n\n return (data as T[]) || [];\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureInsert = useCallback(async <T = any>(\n table: string,\n data: Record<string, any>\n ): Promise<T> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Ensure organisation_id is set\n const secureData = {\n ...data,\n organisation_id: organisationId\n };\n\n const { data: insertData, error } = await supabase!\n .from(table)\n .insert(secureData)\n .select()\n .single();\n\n if (error) {\n logger.error('useSecureDataAccess', 'Insert failed', { table, data: secureData, error });\n throw error;\n }\n\n return insertData as T;\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureUpdate = useCallback(async <T = any>(\n table: string,\n data: Record<string, any>,\n filters: Record<string, any>\n ): Promise<T[]> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Filter out organisation_id from data to prevent manipulation\n const { organisation_id, ...secureData } = data;\n \n // Build update query with organisation filter\n let query = supabase!\n .from(table)\n .update(secureData);\n\n // Add organisation filter only if table has organisation_id column\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member'\n ];\n \n if (tablesWithOrganisation.includes(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n\n // Apply filters\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n query = query.eq(key, value);\n }\n });\n\n const { data: updateData, error } = await query.select();\n\n if (error) {\n logger.error('useSecureDataAccess', 'Update failed', { table, data: secureData, filters, error });\n throw error;\n }\n\n return (updateData as T[]) || [];\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureDelete = useCallback(async (\n table: string,\n filters: Record<string, any>\n ): Promise<void> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Build delete query with organisation filter\n let query = supabase!\n .from(table)\n .delete();\n\n // Add organisation filter only if table has organisation_id column\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member',\n // SECURITY: Phase 3A additions - medical and personal data\n 'medi_profile', 'medi_condition', 'medi_diet', 'medi_action_plan', 'medi_profile_versions',\n 'pace_consent', 'pace_contact', 'pace_id_documents', 'pace_qualifications',\n 'form_responses', 'form_response_values', 'forms',\n // SECURITY: Phase 3B additions - remaining critical tables\n 'invoice', 'line_item', 'credit_balance', 'payment_method',\n 'form_contexts', 'form_field_config', 'form_fields',\n 'cake_delivery', 'cake_diettype', 'cake_diner', 'cake_dish', 'cake_item', \n 'cake_logistics', 'cake_mealplan', 'cake_package', 'cake_recipe', 'cake_supplier', \n 'cake_supply', 'cake_unit', 'event_app_access', 'base_application', 'base_questions'\n ];\n \n if (tablesWithOrganisation.includes(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n\n // Apply filters\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n query = query.eq(key, value);\n }\n });\n\n const { error } = await query;\n\n if (error) {\n logger.error('useSecureDataAccess', 'Delete failed', { table, filters, error });\n throw error;\n }\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureRpc = useCallback(async <T = any>(\n functionName: string,\n params: Record<string, any> = {}\n ): Promise<T> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Include organisation_id in RPC parameters\n // Some functions use p_organisation_id instead of organisation_id (to avoid conflicts with RETURNS TABLE columns)\n const functionsWithPOrganisationId = [\n 'data_cake_diners_list',\n 'data_cake_mealplans_list'\n ];\n \n const paramName = functionsWithPOrganisationId.includes(functionName) \n ? 'p_organisation_id' \n : 'organisation_id';\n \n // Functions that need p_event_id for event-app role permission checks\n // Note: Even org-scoped functions (like items, packages, suppliers) need event_id\n // for permission checks when users have event-app roles\n const functionsNeedingEventId = [\n 'data_cake_items_list',\n 'data_cake_packages_list',\n 'data_cake_suppliers_list',\n 'data_cake_diettypes_list',\n 'data_cake_mealtypes_list',\n 'data_cake_diners_list',\n 'data_cake_mealplans_list',\n 'data_cake_dishes_list',\n 'data_cake_recipes_list',\n 'data_cake_meals_list',\n 'data_cake_units_list',\n 'data_cake_orders_list',\n 'app_cake_item_create',\n 'app_cake_item_update',\n 'app_cake_package_create',\n 'app_cake_package_update',\n 'app_cake_supplier_create',\n 'app_cake_supplier_update',\n 'app_cake_supplier_delete',\n 'app_cake_meal_create',\n 'app_cake_meal_update',\n 'app_cake_meal_delete',\n 'app_cake_unit_create',\n 'app_cake_unit_update',\n 'app_cake_unit_delete',\n 'app_cake_delivery_upsert'\n ];\n \n // Build secureParams with correct parameter order\n // For functions that require p_event_id as first parameter, ensure it's first\n const secureParams: Record<string, any> = {};\n \n // Functions where p_event_id is the FIRST required parameter (no default)\n const functionsWithEventIdFirst = [\n 'data_cake_meals_list',\n 'data_cake_units_list'\n ];\n \n // Add p_user_id explicitly for functions that need it (even though it has a default)\n // This ensures parameter matching works correctly\n if (user?.id) {\n secureParams.p_user_id = user.id;\n }\n \n // Add organisation_id parameter\n secureParams[paramName] = organisationId;\n \n // Add p_event_id if function needs it and event is selected\n // CRITICAL: This must be added AFTER organisation_id but BEFORE caller params\n // to ensure it's not overwritten. For data_cake_items_list, p_event_id is the 3rd param.\n if (functionsNeedingEventId.includes(functionName) && selectedEvent?.event_id) {\n secureParams.p_event_id = selectedEvent.event_id;\n }\n \n // Add any other params passed by caller (limit, offset, etc.)\n // NOTE: This will NOT overwrite p_event_id if caller passes it, but we want to ensure\n // our value takes precedence if event is selected\n Object.assign(secureParams, params);\n \n // Ensure p_event_id is set if needed (after Object.assign, so it overrides caller params)\n if (functionsNeedingEventId.includes(functionName) && selectedEvent?.event_id) {\n secureParams.p_event_id = selectedEvent.event_id;\n }\n\n const { data, error } = await supabase!.rpc(functionName, secureParams);\n\n if (error) {\n logger.error('useSecureDataAccess', 'RPC failed', { functionName, params: secureParams, error });\n throw error;\n }\n\n return data as T;\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase, selectedEvent?.event_id, user?.id]);\n\n // NEW: Phase 1 - Enhanced Security Features\n const [dataAccessHistory, setDataAccessHistory] = useState<DataAccessRecord[]>([]);\n const [isStrictMode] = useState(true); // Always enabled in Phase 1\n const [isAuditLogEnabled] = useState(true); // Always enabled in Phase 1\n\n // Check if data access is allowed for a table and operation\n const isDataAccessAllowed = useCallback((table: string, operation: string): boolean => {\n if (!user?.id) return false;\n \n // Use the existing RBAC system to check data access permissions\n // This is a synchronous check for the context - actual permission checking\n // happens in the secure data operations using the RBAC engine\n const permission = `${operation}:data.${table}` as Permission;\n \n // For now, we'll return true and let the secure data operations\n // handle the actual permission checking asynchronously\n // This context is mainly for tracking and audit purposes\n return true;\n }, [user?.id]);\n\n // Get all data access permissions for current user\n const getDataAccessPermissions = useCallback((): Record<string, string[]> => {\n if (!user?.id) return {};\n \n // For now, return empty object - this will be enhanced with actual permission checking\n // when we integrate with the existing RBAC system\n return {};\n }, [user?.id]);\n\n // Get data access history\n const getDataAccessHistory = useCallback((): DataAccessRecord[] => {\n return [...dataAccessHistory];\n }, [dataAccessHistory]);\n\n // Clear data access history\n const clearDataAccessHistory = useCallback(() => {\n setDataAccessHistory([]);\n }, []);\n\n // Validate data access attempt\n const validateDataAccess = useCallback((table: string, operation: string): boolean => {\n if (!user?.id) return false;\n \n // Validate organisation context\n try {\n validateContext();\n } catch (error) {\n logger.error('useSecureDataAccess', 'Organisation context validation failed', { table, operation, error });\n return false;\n }\n \n return isDataAccessAllowed(table, operation);\n }, [user?.id, validateContext, isDataAccessAllowed]);\n\n // Record data access attempt\n const recordDataAccess = useCallback((\n table: string,\n operation: string,\n allowed: boolean,\n query?: string,\n filters?: Record<string, any>\n ) => {\n if (!isAuditLogEnabled || !user?.id) return;\n \n const record: DataAccessRecord = {\n table,\n operation,\n userId: user.id,\n organisationId: getCurrentOrganisationId(),\n allowed,\n timestamp: new Date().toISOString(),\n query,\n filters\n };\n \n setDataAccessHistory(prev => {\n const newHistory = [record, ...prev];\n return newHistory.slice(0, 1000); // Keep last 1000 records\n });\n \n if (isStrictMode && !allowed) {\n logger.error('useSecureDataAccess', 'STRICT MODE VIOLATION: User attempted data access without permission', {\n table,\n operation,\n userId: user.id,\n organisationId: getCurrentOrganisationId(),\n timestamp: new Date().toISOString()\n });\n }\n }, [isAuditLogEnabled, isStrictMode, user?.id, getCurrentOrganisationId]);\n\n return {\n secureQuery,\n secureInsert,\n secureUpdate,\n secureDelete,\n secureRpc,\n getCurrentOrganisationId,\n validateContext,\n // NEW: Phase 1 - Enhanced Security Features\n isDataAccessAllowed,\n getDataAccessPermissions,\n isStrictMode,\n isAuditLogEnabled,\n getDataAccessHistory,\n clearDataAccessHistory,\n validateDataAccess\n };\n} "],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/hooks/useSecureDataAccess.ts"],"sourcesContent":["/**\n * @file useSecureDataAccess Hook\n * @package @jmruthers/pace-core\n * @module Hooks/useSecureDataAccess\n * @since 0.4.0\n *\n * Hook for secure database operations with mandatory organisation context.\n * Ensures all data access is properly scoped to the user's current organisation.\n *\n * @example\n * ```tsx\n * function DataComponent() {\n * const { secureQuery, secureInsert, secureUpdate, secureDelete } = useSecureDataAccess();\n * \n * const loadData = async () => {\n * try {\n * // Automatically includes organisation_id filter\n * const events = await secureQuery('event', '*', { is_visible: true });\n * console.log('Organisation events:', events);\n * } catch (error) {\n * console.error('Failed to load data:', error);\n * }\n * };\n * \n * const createEvent = async (eventData) => {\n * try {\n * // Automatically sets organisation_id\n * const newEvent = await secureInsert('event', eventData);\n * console.log('Created event:', newEvent);\n * } catch (error) {\n * console.error('Failed to create event:', error);\n * }\n * };\n * \n * return (\n * <div>\n * <button onClick={loadData}>Load Data</button>\n * <button onClick={() => createEvent({ event_name: 'New Event' })}>\n * Create Event\n * </button>\n * </div>\n * );\n * }\n * ```\n *\n * @security\n * - All queries automatically include organisation_id filter\n * - Validates organisation context before any operation\n * - Prevents data leaks between organisations\n * - Error handling for security violations\n * - Type-safe database operations\n */\n\nimport { useCallback, useState, useContext } from 'react';\nimport { useUnifiedAuth } from '../providers';\nimport { useOrganisations } from './useOrganisations';\nimport { EventServiceContext } from '../providers/services/EventServiceProvider';\nimport { setOrganisationContext } from '../utils/context/organisationContext';\nimport { logger } from '../utils/core/logger';\nimport type { Permission } from '../rbac/types';\nimport type { OrganisationSecurityError } from '../types/organisation';\n\nexport interface SecureDataAccessReturn {\n /** Execute a secure query with organisation filtering */\n secureQuery: <T = any>(\n table: string,\n columns: string,\n filters?: Record<string, any>,\n options?: {\n orderBy?: string;\n ascending?: boolean;\n limit?: number;\n offset?: number;\n }\n ) => Promise<T[]>;\n \n /** Execute a secure insert with organisation context */\n secureInsert: <T = any>(\n table: string,\n data: Record<string, any>\n ) => Promise<T>;\n \n /** Execute a secure update with organisation filtering */\n secureUpdate: <T = any>(\n table: string,\n data: Record<string, any>,\n filters: Record<string, any>\n ) => Promise<T[]>;\n \n /** Execute a secure delete with organisation filtering */\n secureDelete: (\n table: string,\n filters: Record<string, any>\n ) => Promise<void>;\n \n /** Execute a secure RPC call with organisation context */\n secureRpc: <T = any>(\n functionName: string,\n params?: Record<string, any>\n ) => Promise<T>;\n \n /** Get current organisation ID */\n getCurrentOrganisationId: () => string;\n \n /** Validate organisation context */\n validateContext: () => void;\n \n // NEW: Phase 1 - Enhanced Security Features\n /** Check if data access is allowed for a table and operation */\n isDataAccessAllowed: (table: string, operation: string) => boolean;\n \n /** Get all data access permissions for current user */\n getDataAccessPermissions: () => Record<string, string[]>;\n \n /** Check if strict mode is enabled */\n isStrictMode: boolean;\n \n /** Check if audit logging is enabled */\n isAuditLogEnabled: boolean;\n \n /** Get data access history */\n getDataAccessHistory: () => DataAccessRecord[];\n \n /** Clear data access history */\n clearDataAccessHistory: () => void;\n \n /** Validate data access attempt */\n validateDataAccess: (table: string, operation: string) => boolean;\n}\n\nexport interface DataAccessRecord {\n table: string;\n operation: string;\n userId: string;\n organisationId: string;\n allowed: boolean;\n timestamp: string;\n query?: string;\n filters?: Record<string, any>;\n}\n\n/**\n * Hook for secure data access with automatic organisation filtering\n * \n * All database operations automatically include organisation context:\n * - Queries filter by organisation_id\n * - Inserts include organisation_id\n * - Updates/deletes are scoped to organisation\n * - RPC calls include organisation_id parameter\n */\nexport function useSecureDataAccess(): SecureDataAccessReturn {\n const { supabase, user, session } = useUnifiedAuth();\n const { ensureOrganisationContext } = useOrganisations();\n \n // Get selected event for event-scoped RPC calls\n // Use useContext directly to safely check if EventServiceProvider is available\n const eventServiceContext = useContext(EventServiceContext);\n const selectedEvent = eventServiceContext?.eventService?.getSelectedEvent() || null;\n\n const validateContext = useCallback((): void => {\n if (!supabase) {\n throw new Error('No Supabase client available') as OrganisationSecurityError;\n }\n if (!user || !session) {\n throw new Error('User must be authenticated with valid session') as OrganisationSecurityError;\n }\n \n try {\n ensureOrganisationContext();\n } catch (error) {\n throw new Error('Organisation context is required for data access') as OrganisationSecurityError;\n }\n }, [supabase, user, session, ensureOrganisationContext]);\n\n const getCurrentOrganisationId = useCallback((): string => {\n validateContext();\n const currentOrg = ensureOrganisationContext();\n return currentOrg.id;\n }, [validateContext, ensureOrganisationContext]);\n\n // Set organisation context in database session\n const setOrganisationContextInSession = useCallback(async (organisationId: string): Promise<void> => {\n if (!supabase) {\n throw new Error('No Supabase client available') as OrganisationSecurityError;\n }\n\n await setOrganisationContext(supabase, organisationId);\n }, [supabase]);\n\n const secureQuery = useCallback(async <T = any>(\n table: string,\n columns: string,\n filters: Record<string, any> = {},\n options: {\n orderBy?: string;\n ascending?: boolean;\n limit?: number;\n offset?: number;\n } = {}\n ): Promise<T[]> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Build query with organisation filter\n let query = supabase!\n .from(table)\n .select(columns);\n\n // Add organisation filter only if table has organisation_id column\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member',\n // SECURITY: Phase 3A additions - medical and personal data\n 'medi_profile', 'medi_condition', 'medi_diet', 'medi_action_plan', 'medi_profile_versions',\n 'pace_consent', 'pace_contact', 'pace_id_documents', 'pace_qualifications',\n 'form_responses', 'form_response_values', 'forms',\n // SECURITY: Phase 3B additions - remaining critical tables\n 'invoice', 'line_item', 'credit_balance', 'payment_method',\n 'form_contexts', 'form_field_config', 'form_fields',\n 'cake_delivery', 'cake_diettype', 'cake_diner', 'cake_dish', 'cake_item', \n 'cake_logistics', 'cake_mealplan', 'cake_package', 'cake_recipe', 'cake_supplier', \n 'cake_supply', 'cake_unit', 'event_app_access', 'base_application', 'base_questions'\n ];\n \n if (tablesWithOrganisation.includes(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n\n // Apply additional filters\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n // Handle qualified column names (e.g., 'users.role')\n const columnName = key.includes('.') ? key.split('.').pop()! : key;\n query = query.eq(columnName, value);\n }\n });\n\n // Apply options\n if (options.orderBy) {\n // Only use the column name, not a qualified name\n const orderByColumn = options.orderBy.split('.').pop();\n if (orderByColumn) {\n query = query.order(orderByColumn, { ascending: options.ascending ?? true });\n }\n }\n \n if (options.limit) {\n query = query.limit(options.limit);\n }\n \n if (options.offset) {\n query = query.range(options.offset, options.offset + (options.limit || 100) - 1);\n }\n\n const { data, error } = await query;\n \n if (error) {\n logger.error('useSecureDataAccess', 'Query failed', { table, columns, filters, error });\n // NEW: Phase 1 - Record failed data access attempt\n recordDataAccess(table, 'read', false, `SELECT ${columns} FROM ${table}`, filters);\n throw error;\n }\n\n // NEW: Phase 1 - Record successful data access attempt\n recordDataAccess(table, 'read', true, `SELECT ${columns} FROM ${table}`, filters);\n\n return (data as T[]) || [];\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureInsert = useCallback(async <T = any>(\n table: string,\n data: Record<string, any>\n ): Promise<T> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Ensure organisation_id is set\n const secureData = {\n ...data,\n organisation_id: organisationId\n };\n\n const { data: insertData, error } = await supabase!\n .from(table)\n .insert(secureData)\n .select()\n .single();\n\n if (error) {\n logger.error('useSecureDataAccess', 'Insert failed', { table, data: secureData, error });\n throw error;\n }\n\n return insertData as T;\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureUpdate = useCallback(async <T = any>(\n table: string,\n data: Record<string, any>,\n filters: Record<string, any>\n ): Promise<T[]> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Filter out organisation_id from data to prevent manipulation\n const { organisation_id, ...secureData } = data;\n \n // Build update query with organisation filter\n let query = supabase!\n .from(table)\n .update(secureData);\n\n // Add organisation filter only if table has organisation_id column\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member'\n ];\n \n if (tablesWithOrganisation.includes(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n\n // Apply filters\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n query = query.eq(key, value);\n }\n });\n\n const { data: updateData, error } = await query.select();\n\n if (error) {\n logger.error('useSecureDataAccess', 'Update failed', { table, data: secureData, filters, error });\n throw error;\n }\n\n return (updateData as T[]) || [];\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureDelete = useCallback(async (\n table: string,\n filters: Record<string, any>\n ): Promise<void> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Build delete query with organisation filter\n let query = supabase!\n .from(table)\n .delete();\n\n // Add organisation filter only if table has organisation_id column\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member',\n // SECURITY: Phase 3A additions - medical and personal data\n 'medi_profile', 'medi_condition', 'medi_diet', 'medi_action_plan', 'medi_profile_versions',\n 'pace_consent', 'pace_contact', 'pace_id_documents', 'pace_qualifications',\n 'form_responses', 'form_response_values', 'forms',\n // SECURITY: Phase 3B additions - remaining critical tables\n 'invoice', 'line_item', 'credit_balance', 'payment_method',\n 'form_contexts', 'form_field_config', 'form_fields',\n 'cake_delivery', 'cake_diettype', 'cake_diner', 'cake_dish', 'cake_item', \n 'cake_logistics', 'cake_mealplan', 'cake_package', 'cake_recipe', 'cake_supplier', \n 'cake_supply', 'cake_unit', 'event_app_access', 'base_application', 'base_questions'\n ];\n \n if (tablesWithOrganisation.includes(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n\n // Apply filters\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n query = query.eq(key, value);\n }\n });\n\n const { error } = await query;\n\n if (error) {\n logger.error('useSecureDataAccess', 'Delete failed', { table, filters, error });\n throw error;\n }\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureRpc = useCallback(async <T = any>(\n functionName: string,\n params: Record<string, any> = {}\n ): Promise<T> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Include organisation_id in RPC parameters\n // Some functions use p_organisation_id instead of organisation_id (to avoid conflicts with RETURNS TABLE columns)\n const functionsWithPOrganisationId = [\n 'data_cake_diners_list',\n 'data_cake_mealplans_list'\n ];\n \n const paramName = functionsWithPOrganisationId.includes(functionName) \n ? 'p_organisation_id' \n : 'organisation_id';\n \n // Functions that need p_event_id for event-app role permission checks\n // Note: Even org-scoped functions (like items, packages, suppliers) need event_id\n // for permission checks when users have event-app roles\n const functionsNeedingEventId = [\n 'data_cake_items_list',\n 'data_cake_packages_list',\n 'data_cake_suppliers_list',\n 'data_cake_diettypes_list',\n 'data_cake_mealtypes_list',\n 'data_cake_diners_list',\n 'data_cake_mealplans_list',\n 'data_cake_dishes_list',\n 'data_cake_recipes_list',\n 'data_cake_meals_list',\n 'data_cake_units_list',\n 'data_cake_orders_list',\n 'app_cake_item_create',\n 'app_cake_item_update',\n 'app_cake_package_create',\n 'app_cake_package_update',\n 'app_cake_supplier_create',\n 'app_cake_supplier_update',\n 'app_cake_supplier_delete',\n 'app_cake_meal_create',\n 'app_cake_meal_update',\n 'app_cake_meal_delete',\n 'app_cake_unit_create',\n 'app_cake_unit_update',\n 'app_cake_unit_delete',\n 'app_cake_delivery_upsert'\n ];\n \n // Build secureParams with correct parameter order\n // For functions that require p_event_id as first parameter, ensure it's first\n const secureParams: Record<string, any> = {};\n \n // Functions where p_event_id is the FIRST required parameter (no default)\n const functionsWithEventIdFirst = [\n 'data_cake_meals_list',\n 'data_cake_units_list'\n ];\n \n // Add p_user_id explicitly for functions that need it (even though it has a default)\n // This ensures parameter matching works correctly\n if (user?.id) {\n secureParams.p_user_id = user.id;\n }\n \n // Add organisation_id parameter\n secureParams[paramName] = organisationId;\n \n // Add p_event_id if function needs it and event is selected\n // CRITICAL: This must be added AFTER organisation_id but BEFORE caller params\n // to ensure it's not overwritten. For data_cake_items_list, p_event_id is the 3rd param.\n if (functionsNeedingEventId.includes(functionName) && selectedEvent?.event_id) {\n secureParams.p_event_id = selectedEvent.event_id;\n }\n \n // Add any other params passed by caller (limit, offset, etc.)\n // NOTE: This will NOT overwrite p_event_id if caller passes it, but we want to ensure\n // our value takes precedence if event is selected\n Object.assign(secureParams, params);\n \n // Ensure p_event_id is set if needed (after Object.assign, so it overrides caller params)\n if (functionsNeedingEventId.includes(functionName) && selectedEvent?.event_id) {\n secureParams.p_event_id = selectedEvent.event_id;\n }\n\n const { data, error } = await supabase!.rpc(functionName, secureParams);\n\n if (error) {\n logger.error('useSecureDataAccess', 'RPC failed', { functionName, params: secureParams, error });\n throw error;\n }\n\n return data as T;\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase, selectedEvent?.event_id, user?.id]);\n\n // NEW: Phase 1 - Enhanced Security Features\n const [dataAccessHistory, setDataAccessHistory] = useState<DataAccessRecord[]>([]);\n const [isStrictMode] = useState(true); // Always enabled in Phase 1\n const [isAuditLogEnabled] = useState(true); // Always enabled in Phase 1\n\n // Check if data access is allowed for a table and operation\n const isDataAccessAllowed = useCallback((table: string, operation: string): boolean => {\n if (!user?.id) return false;\n \n // Use the existing RBAC system to check data access permissions\n // This is a synchronous check for the context - actual permission checking\n // happens in the secure data operations using the RBAC engine\n const permission = `${operation}:data.${table}` as Permission;\n \n // For now, we'll return true and let the secure data operations\n // handle the actual permission checking asynchronously\n // This context is mainly for tracking and audit purposes\n return true;\n }, [user?.id]);\n\n // Get all data access permissions for current user\n const getDataAccessPermissions = useCallback((): Record<string, string[]> => {\n if (!user?.id) return {};\n \n // For now, return empty object - this will be enhanced with actual permission checking\n // when we integrate with the existing RBAC system\n return {};\n }, [user?.id]);\n\n // Get data access history\n const getDataAccessHistory = useCallback((): DataAccessRecord[] => {\n return [...dataAccessHistory];\n }, [dataAccessHistory]);\n\n // Clear data access history\n const clearDataAccessHistory = useCallback(() => {\n setDataAccessHistory([]);\n }, []);\n\n // Validate data access attempt\n const validateDataAccess = useCallback((table: string, operation: string): boolean => {\n if (!user?.id) return false;\n \n // Validate organisation context\n try {\n validateContext();\n } catch (error) {\n logger.error('useSecureDataAccess', 'Organisation context validation failed', { table, operation, error });\n return false;\n }\n \n return isDataAccessAllowed(table, operation);\n }, [user?.id, validateContext, isDataAccessAllowed]);\n\n // Record data access attempt\n const recordDataAccess = useCallback((\n table: string,\n operation: string,\n allowed: boolean,\n query?: string,\n filters?: Record<string, any>\n ) => {\n if (!isAuditLogEnabled || !user?.id) return;\n \n const record: DataAccessRecord = {\n table,\n operation,\n userId: user.id,\n organisationId: getCurrentOrganisationId(),\n allowed,\n timestamp: new Date().toISOString(),\n query,\n filters\n };\n \n setDataAccessHistory(prev => {\n const newHistory = [record, ...prev];\n return newHistory.slice(0, 1000); // Keep last 1000 records\n });\n \n if (isStrictMode && !allowed) {\n logger.error('useSecureDataAccess', 'STRICT MODE VIOLATION: User attempted data access without permission', {\n table,\n operation,\n userId: user.id,\n organisationId: getCurrentOrganisationId(),\n timestamp: new Date().toISOString()\n });\n }\n }, [isAuditLogEnabled, isStrictMode, user?.id, getCurrentOrganisationId]);\n\n return {\n secureQuery,\n secureInsert,\n secureUpdate,\n secureDelete,\n secureRpc,\n getCurrentOrganisationId,\n validateContext,\n // NEW: Phase 1 - Enhanced Security Features\n isDataAccessAllowed,\n getDataAccessPermissions,\n isStrictMode,\n isAuditLogEnabled,\n getDataAccessHistory,\n clearDataAccessHistory,\n validateDataAccess\n };\n} "],"mappings":"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","names":[]}