@jmruthers/pace-core 0.6.10 → 0.6.12

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 (1500) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/audit-tool/00-dependencies.cjs +46 -13
  3. package/audit-tool/audits/01-pace-core-compliance.cjs +96 -21
  4. package/audit-tool/audits/02-project-structure.cjs +13 -3
  5. package/audit-tool/audits/03-architecture.cjs +78 -4
  6. package/audit-tool/audits/04-code-quality.cjs +9 -2
  7. package/audit-tool/audits/05-styling.cjs +19 -7
  8. package/audit-tool/audits/06-security-rbac.cjs +105 -14
  9. package/audit-tool/audits/07-api-tech-stack.cjs +31 -15
  10. package/audit-tool/audits/08-testing-documentation.cjs +11 -3
  11. package/audit-tool/audits/09-operations.cjs +19 -7
  12. package/audit-tool/index.cjs +22 -11
  13. package/audit-tool/utils/report-utils.cjs +4 -0
  14. package/cursor-rules/01-pace-core-compliance.mdc +1 -0
  15. package/cursor-rules/02-project-structure.mdc +1 -0
  16. package/cursor-rules/03-architecture.mdc +3 -1
  17. package/cursor-rules/04-code-quality.mdc +1 -0
  18. package/cursor-rules/05-styling.mdc +41 -7
  19. package/cursor-rules/06-security-rbac.mdc +2 -1
  20. package/cursor-rules/07-api-tech-stack.mdc +1 -0
  21. package/cursor-rules/08-testing-documentation.mdc +1 -0
  22. package/cursor-rules/09-operations.mdc +1 -0
  23. package/dist/DataTable-AQAHSFLM.js +17 -0
  24. package/dist/InactivityServiceProvider-BbxwwDz1.d.ts +308 -0
  25. package/dist/UnifiedAuthProvider-Bkt_tzdS.d.ts +183 -0
  26. package/dist/api-6OQXYT67.js +6 -0
  27. package/dist/api-result-USV1Czr-.d.ts +51 -0
  28. package/dist/audit-HI2DHUVU.js +4 -0
  29. package/dist/auth-JvdRVaud.d.ts +49 -0
  30. package/dist/chunk-2DL2WSOE.js +327 -0
  31. package/dist/chunk-2GBDPPUC.js +61 -0
  32. package/dist/chunk-44CNXN4P.js +15 -0
  33. package/dist/chunk-AP5FG7W4.js +2159 -0
  34. package/dist/chunk-CU2BU2MQ.js +2 -0
  35. package/dist/chunk-D6BMFMQZ.js +200 -0
  36. package/dist/chunk-ENLXB7GP.js +721 -0
  37. package/dist/chunk-GHCUP64P.js +105 -0
  38. package/dist/chunk-H6RTU4DZ.js +1098 -0
  39. package/dist/chunk-HQTYP6BX.js +6468 -0
  40. package/dist/chunk-M7QE7XOA.js +529 -0
  41. package/dist/chunk-MVVWZ7JV.js +1329 -0
  42. package/dist/chunk-NJ7FGQWB.js +811 -0
  43. package/dist/chunk-QRYSEPHB.js +429 -0
  44. package/dist/chunk-QWIG36BZ.js +264 -0
  45. package/dist/chunk-S57OLCLO.js +2946 -0
  46. package/dist/chunk-VFLR5K2H.js +23 -0
  47. package/dist/chunk-XOJME5T7.js +407 -0
  48. package/dist/chunk-XPFVT3GN.js +492 -0
  49. package/dist/chunk-Y2LWSLLB.js +9614 -0
  50. package/dist/chunk-YFGNMB67.js +2390 -0
  51. package/dist/components.d.ts +10 -9
  52. package/dist/components.js +20 -17
  53. package/dist/database.generated-qkdoiVrJ.d.ts +9441 -0
  54. package/dist/eslint-rules/index.cjs +3 -0
  55. package/dist/eslint-rules/rules/03-architecture.cjs +74 -0
  56. package/dist/eslint-rules/rules/06-security-rbac.cjs +74 -0
  57. package/dist/event-BfCox3N2.d.ts +265 -0
  58. package/dist/file-reference-DU1hcawx.d.ts +164 -0
  59. package/dist/functions-hF5ImHCr.d.ts +208 -0
  60. package/dist/hooks.d.ts +22 -9
  61. package/dist/hooks.js +35 -25
  62. package/dist/icons/index.d.ts +1 -0
  63. package/dist/icons/index.js +1 -0
  64. package/dist/index.d.ts +69 -180
  65. package/dist/index.js +319 -342
  66. package/dist/pagination-BW1mqywp.d.ts +201 -0
  67. package/dist/providers.d.ts +6 -5
  68. package/dist/providers.js +6 -3
  69. package/dist/rbac/index.d.ts +133 -148
  70. package/dist/rbac/index.js +12 -9
  71. package/dist/theming/runtime.d.ts +19 -2
  72. package/dist/theming/runtime.js +1 -1
  73. package/dist/timezone-BTWWXKVY.d.ts +696 -0
  74. package/dist/types-Besvoyzb.d.ts +55 -0
  75. package/dist/types-CGHrxfqc.d.ts +114 -0
  76. package/dist/types.d.ts +19 -12
  77. package/dist/types.js +1 -0
  78. package/dist/usePublicPageContext-BQrHf95t.d.ts +4367 -0
  79. package/dist/usePublicRouteParams-BgV6VhMi.d.ts +946 -0
  80. package/dist/utils.d.ts +163 -145
  81. package/dist/utils.js +45 -27
  82. package/docs/api/@jmruthers/namespaces/DialogPortal/README.md +14 -0
  83. package/docs/api/@jmruthers/namespaces/DialogPortal/variables/displayName.md +11 -0
  84. package/docs/api/README.md +6 -2
  85. package/docs/api/_media/README.md +186 -0
  86. package/docs/api/classes/ColumnFactory.md +225 -0
  87. package/docs/api/classes/Logger.md +246 -0
  88. package/docs/api/classes/RBACAuditManager.md +299 -0
  89. package/docs/api/classes/RBACCache.md +389 -0
  90. package/docs/api/classes/RBACEngine.md +181 -0
  91. package/docs/api/classes/SecureSupabaseClient.md +168 -0
  92. package/docs/api/classes/StorageUtils.md +324 -0
  93. package/docs/api/enumerations/FileCategory.md +137 -0
  94. package/docs/api/enumerations/LogLevel.md +43 -0
  95. package/docs/api/enumerations/RBACErrorCode.md +169 -0
  96. package/docs/api/enumerations/RPCFunction.md +89 -0
  97. package/docs/api/functions/AccessDenied.md +30 -0
  98. package/docs/api/functions/AppSwitcher.md +21 -0
  99. package/docs/api/functions/Badge.md +42 -0
  100. package/docs/api/functions/ContextSelector.md +43 -0
  101. package/docs/api/functions/DataTable.md +36 -0
  102. package/docs/api/functions/DatePickerWithTimezone.md +28 -0
  103. package/docs/api/functions/DialogBody.md +24 -0
  104. package/docs/api/functions/DialogFooter.md +24 -0
  105. package/docs/api/functions/DialogHeader.md +24 -0
  106. package/docs/api/functions/ErrorBoundaryProvider.md +28 -0
  107. package/docs/api/functions/EventServiceProvider.md +28 -0
  108. package/docs/api/functions/FileDisplay.md +25 -0
  109. package/docs/api/functions/FileUpload.md +21 -0
  110. package/docs/api/functions/Form.md +50 -0
  111. package/docs/api/functions/FormField.md +102 -0
  112. package/docs/api/functions/Header.md +21 -0
  113. package/docs/api/functions/InactivityServiceProvider.md +28 -0
  114. package/docs/api/functions/InactivityWarningModal.md +21 -0
  115. package/docs/api/functions/Input.md +49 -0
  116. package/docs/api/functions/NavigationGuard.md +31 -0
  117. package/docs/api/functions/OrganisationServiceProvider.md +28 -0
  118. package/docs/api/functions/PaceAppLayout.md +169 -0
  119. package/docs/api/functions/PasswordChangeForm.md +21 -0
  120. package/docs/api/functions/ProtectedRoute.md +37 -0
  121. package/docs/api/functions/PublicPageFooter.md +21 -0
  122. package/docs/api/functions/PublicPageHeader.md +21 -0
  123. package/docs/api/functions/PublicPageLayout.md +33 -0
  124. package/docs/api/functions/PublicPageProvider.md +30 -0
  125. package/docs/api/functions/Textarea.md +49 -0
  126. package/docs/api/functions/Toaster.md +34 -0
  127. package/docs/api/functions/UnifiedAuthProvider.md +28 -0
  128. package/docs/api/functions/applyPalette.md +33 -0
  129. package/docs/api/functions/archiveFile.md +47 -0
  130. package/docs/api/functions/average.md +63 -0
  131. package/docs/api/functions/buildAppUrl.md +46 -0
  132. package/docs/api/functions/clearInFlightRequests.md +17 -0
  133. package/docs/api/functions/clearPalette.md +18 -0
  134. package/docs/api/functions/clearPublicEventCache.md +18 -0
  135. package/docs/api/functions/clearPublicFileDisplayCache.md +18 -0
  136. package/docs/api/functions/clearPublicLogoCache.md +18 -0
  137. package/docs/api/functions/cn.md +21 -0
  138. package/docs/api/functions/count.md +56 -0
  139. package/docs/api/functions/createAuditManager.md +45 -0
  140. package/docs/api/functions/createBaseClient.md +75 -0
  141. package/docs/api/functions/createLogger.md +95 -0
  142. package/docs/api/functions/createRBACConfig.md +21 -0
  143. package/docs/api/functions/createRBACEngine.md +33 -0
  144. package/docs/api/functions/createRBACExpressMiddleware.md +84 -0
  145. package/docs/api/functions/createRBACMiddleware.md +88 -0
  146. package/docs/api/functions/createSecureClient.md +80 -0
  147. package/docs/api/functions/createSecureDataAccess.md +39 -0
  148. package/docs/api/functions/deleteFile.md +33 -0
  149. package/docs/api/functions/disablePerformanceMonitoring.md +17 -0
  150. package/docs/api/functions/downloadFile.md +33 -0
  151. package/docs/api/functions/emitAuditEvent.md +27 -0
  152. package/docs/api/functions/enablePerformanceMonitoring.md +17 -0
  153. package/docs/api/functions/err.md +23 -0
  154. package/docs/api/functions/exportToCSV.md +56 -0
  155. package/docs/api/functions/exportToCSVWithTableRows.md +46 -0
  156. package/docs/api/functions/extractEventCodeFromPath.md +24 -0
  157. package/docs/api/functions/extractFileMetadata.md +33 -0
  158. package/docs/api/functions/formatCompactNumber.md +27 -0
  159. package/docs/api/functions/formatCurrency.md +31 -0
  160. package/docs/api/functions/formatDate.md +23 -0
  161. package/docs/api/functions/formatDateTime.md +24 -0
  162. package/docs/api/functions/formatFileSize.md +23 -0
  163. package/docs/api/functions/formatInTimeZone.md +46 -0
  164. package/docs/api/functions/formatNumber.md +31 -0
  165. package/docs/api/functions/formatPercent.md +64 -0
  166. package/docs/api/functions/formatTime.md +24 -0
  167. package/docs/api/functions/formatTimeInTimeZone.md +40 -0
  168. package/docs/api/functions/fromSupabaseClient.md +49 -0
  169. package/docs/api/functions/fromZonedTime.md +41 -0
  170. package/docs/api/functions/generateCSVContent.md +55 -0
  171. package/docs/api/functions/generateFilePath.md +29 -0
  172. package/docs/api/functions/generateFileUrlsBatch.md +33 -0
  173. package/docs/api/functions/generatePublicRoutePath.md +27 -0
  174. package/docs/api/functions/generateUniqueFileName.md +24 -0
  175. package/docs/api/functions/getAccessLevel.md +48 -0
  176. package/docs/api/functions/getAllAppPorts.md +19 -0
  177. package/docs/api/functions/getAllStylePaths.md +15 -0
  178. package/docs/api/functions/getAppConfig.md +17 -0
  179. package/docs/api/functions/getAppPort.md +34 -0
  180. package/docs/api/functions/getBucketName.md +27 -0
  181. package/docs/api/functions/getCurrentAppId.md +17 -0
  182. package/docs/api/functions/getCurrentAppName.md +17 -0
  183. package/docs/api/functions/getFileSizeLimit.md +23 -0
  184. package/docs/api/functions/getGlobalAuditManager.md +19 -0
  185. package/docs/api/functions/getInFlightRequestCount.md +19 -0
  186. package/docs/api/functions/getPerformanceMetrics.md +17 -0
  187. package/docs/api/functions/getPerformanceSummary.md +17 -0
  188. package/docs/api/functions/getPermissionMap.md +52 -0
  189. package/docs/api/functions/getPublicEventCacheStats.md +25 -0
  190. package/docs/api/functions/getPublicFileDisplayCacheStats.md +25 -0
  191. package/docs/api/functions/getPublicLogoCacheStats.md +25 -0
  192. package/docs/api/functions/getPublicUrl.md +39 -0
  193. package/docs/api/functions/getRBACConfig.md +15 -0
  194. package/docs/api/functions/getRBACLogger.md +15 -0
  195. package/docs/api/functions/getRoleContext.md +31 -0
  196. package/docs/api/functions/getSignedUrl.md +34 -0
  197. package/docs/api/functions/getStylePath.md +21 -0
  198. package/docs/api/functions/getTimeZoneDifference.md +40 -0
  199. package/docs/api/functions/getTimezoneAbbreviation.md +40 -0
  200. package/docs/api/functions/getUserTimeZone.md +26 -0
  201. package/docs/api/functions/hasAllPermissions.md +41 -0
  202. package/docs/api/functions/hasAnyPermission.md +41 -0
  203. package/docs/api/functions/isDebugMode.md +15 -0
  204. package/docs/api/functions/isDevelopmentMode.md +15 -0
  205. package/docs/api/functions/isErr.md +29 -0
  206. package/docs/api/functions/isOk.md +29 -0
  207. package/docs/api/functions/isPerformanceMonitoringEnabled.md +17 -0
  208. package/docs/api/functions/isPermitted.md +58 -0
  209. package/docs/api/functions/isPermittedCached.md +36 -0
  210. package/docs/api/functions/isRBACInitialized.md +19 -0
  211. package/docs/api/functions/isSecureClient.md +38 -0
  212. package/docs/api/functions/isValidPermission.md +27 -0
  213. package/docs/api/functions/listFiles.md +29 -0
  214. package/docs/api/functions/max.md +63 -0
  215. package/docs/api/functions/min.md +63 -0
  216. package/docs/api/functions/ok.md +29 -0
  217. package/docs/api/functions/parseAndNormalizeEventColours.md +105 -0
  218. package/docs/api/functions/recordAuditEvent.md +23 -0
  219. package/docs/api/functions/recordPermissionCheck.md +31 -0
  220. package/docs/api/functions/resetPerformanceMetrics.md +17 -0
  221. package/docs/api/functions/resolveAppContext.md +27 -0
  222. package/docs/api/functions/roundToNearestMinutes.md +41 -0
  223. package/docs/api/functions/sanitizeFormData.md +49 -0
  224. package/docs/api/functions/sanitizeHtml.md +39 -0
  225. package/docs/api/functions/sanitizeUserInput.md +27 -0
  226. package/docs/api/functions/setAppConfig.md +23 -0
  227. package/docs/api/functions/setGlobalAuditManager.md +25 -0
  228. package/docs/api/functions/setupRBAC.md +31 -0
  229. package/docs/api/functions/sum.md +63 -0
  230. package/docs/api/functions/toZonedTime.md +41 -0
  231. package/docs/api/functions/uploadFile.md +32 -0
  232. package/docs/api/functions/useAccessLevel.md +71 -0
  233. package/docs/api/functions/useAccessibleApps.md +55 -0
  234. package/docs/api/functions/useAppConfig.md +20 -0
  235. package/docs/api/functions/useAuthService.md +15 -0
  236. package/docs/api/functions/useCan.md +99 -0
  237. package/docs/api/functions/useEventService.md +15 -0
  238. package/docs/api/functions/useEventTheme.md +26 -0
  239. package/docs/api/functions/useEvents.md +45 -0
  240. package/docs/api/functions/useFileReference.md +264 -0
  241. package/docs/api/functions/useFileReferenceById.md +63 -0
  242. package/docs/api/functions/useFileReferenceForRecord.md +129 -0
  243. package/docs/api/functions/useFilesByCategory.md +80 -0
  244. package/docs/api/functions/useFormDialog.md +62 -0
  245. package/docs/api/functions/useInactivityService.md +15 -0
  246. package/docs/api/functions/useInactivityTracker.md +21 -0
  247. package/docs/api/functions/useIsPublicPage.md +19 -0
  248. package/docs/api/functions/useMultiplePermissions.md +88 -0
  249. package/docs/api/functions/useOptionalEvents.md +31 -0
  250. package/docs/api/functions/useOrganisationPermissions.md +27 -0
  251. package/docs/api/functions/useOrganisationSecurity.md +15 -0
  252. package/docs/api/functions/useOrganisationService.md +15 -0
  253. package/docs/api/functions/useOrganisations.md +48 -0
  254. package/docs/api/functions/usePermissions.md +130 -0
  255. package/docs/api/functions/usePublicEvent.md +36 -0
  256. package/docs/api/functions/usePublicEventCode.md +32 -0
  257. package/docs/api/functions/usePublicEventLogo.md +48 -0
  258. package/docs/api/functions/usePublicFileDisplay.md +54 -0
  259. package/docs/api/functions/usePublicPageContext.md +19 -0
  260. package/docs/api/functions/usePublicRouteParams.md +31 -0
  261. package/docs/api/functions/useRBAC.md +21 -0
  262. package/docs/api/functions/useResolvedScope.md +46 -0
  263. package/docs/api/functions/useResourcePermissions.md +25 -0
  264. package/docs/api/functions/useRoleManagement.md +121 -0
  265. package/docs/api/functions/useSecureSupabase.md +51 -0
  266. package/docs/api/functions/useSessionRestoration.md +15 -0
  267. package/docs/api/functions/useSessionTracking.md +62 -0
  268. package/docs/api/functions/useToast.md +83 -0
  269. package/docs/api/functions/useUnifiedAuth.md +24 -0
  270. package/docs/api/functions/useZodForm.md +27 -0
  271. package/docs/api/functions/validateFileSize.md +31 -0
  272. package/docs/api/functions/warnIfInsecureClient.md +40 -0
  273. package/docs/api/functions/withAccessLevelGuard.md +67 -0
  274. package/docs/api/functions/withPermissionGuard.md +73 -0
  275. package/docs/api/functions/withRoleGuard.md +86 -0
  276. package/docs/api/globals.md +502 -0
  277. package/docs/api/interfaces/AccessDeniedProps.md +87 -0
  278. package/docs/api/interfaces/AccessibleApp.md +41 -0
  279. package/docs/api/interfaces/AddressFieldProps.md +195 -0
  280. package/docs/api/interfaces/AddressFieldRef.md +67 -0
  281. package/docs/api/interfaces/AggregateConfig.md +35 -0
  282. package/docs/api/interfaces/AppSwitcherProps.md +51 -0
  283. package/docs/api/interfaces/AuthSessionData.md +27 -0
  284. package/docs/api/interfaces/AutocompleteOptions.md +61 -0
  285. package/docs/api/interfaces/AvatarProps.md +97 -0
  286. package/docs/api/interfaces/BadgeProps.md +30 -0
  287. package/docs/api/interfaces/BuildAppUrlOptions.md +41 -0
  288. package/docs/api/interfaces/ButtonProps.md +46 -0
  289. package/docs/api/interfaces/CalendarProps.md +60 -0
  290. package/docs/api/interfaces/CardProps.md +56 -0
  291. package/docs/api/interfaces/ColorPalette.md +13 -0
  292. package/docs/api/interfaces/ColorShade.md +58 -0
  293. package/docs/api/interfaces/ContextSelectorProps.md +131 -0
  294. package/docs/api/interfaces/DataRecord.md +16 -0
  295. package/docs/api/interfaces/DataTableAction.md +198 -0
  296. package/docs/api/interfaces/DataTableColumn.md +422 -0
  297. package/docs/api/interfaces/DataTableProps.md +511 -0
  298. package/docs/api/interfaces/DataTableToolbarButton.md +75 -0
  299. package/docs/api/interfaces/DatePickerWithTimezoneProps.md +75 -0
  300. package/docs/api/interfaces/DialogBodyProps.md +55 -0
  301. package/docs/api/interfaces/DialogCloseProps.md +25 -0
  302. package/docs/api/interfaces/DialogContentProps.md +160 -0
  303. package/docs/api/interfaces/DialogFooterProps.md +25 -0
  304. package/docs/api/interfaces/DialogHeaderProps.md +25 -0
  305. package/docs/api/interfaces/DialogPortalProps.md +19 -0
  306. package/docs/api/interfaces/DialogProps.md +53 -0
  307. package/docs/api/interfaces/DialogTriggerProps.md +53 -0
  308. package/docs/api/interfaces/EmptyStateConfig.md +55 -0
  309. package/docs/api/interfaces/ErrorBoundaryProps.md +131 -0
  310. package/docs/api/interfaces/ErrorBoundaryProviderProps.md +31 -0
  311. package/docs/api/interfaces/ErrorBoundaryState.md +61 -0
  312. package/docs/api/interfaces/EventAppRoleData.md +54 -0
  313. package/docs/api/interfaces/ExportColumn.md +69 -0
  314. package/docs/api/interfaces/ExportOptions.md +109 -0
  315. package/docs/api/interfaces/FileDisplayProps.md +192 -0
  316. package/docs/api/interfaces/FileMetadata.md +97 -0
  317. package/docs/api/interfaces/FileReference.md +89 -0
  318. package/docs/api/interfaces/FileSizeLimits.md +13 -0
  319. package/docs/api/interfaces/FileUploadOptions.md +107 -0
  320. package/docs/api/interfaces/FooterProps.md +37 -0
  321. package/docs/api/interfaces/FormFieldProps.md +171 -0
  322. package/docs/api/interfaces/FormProps.md +93 -0
  323. package/docs/api/interfaces/GrantEventAppRoleParams.md +97 -0
  324. package/docs/api/interfaces/ImportSummary.md +49 -0
  325. package/docs/api/interfaces/InactivityWarningModalProps.md +87 -0
  326. package/docs/api/interfaces/InputProps.md +46 -0
  327. package/docs/api/interfaces/InvalidScopeError.md +37 -0
  328. package/docs/api/interfaces/LabelProps.md +85 -0
  329. package/docs/api/interfaces/LoggerConfig.md +51 -0
  330. package/docs/api/interfaces/LoginFormProps.md +146 -0
  331. package/docs/api/interfaces/MissingUserContextError.md +37 -0
  332. package/docs/api/interfaces/NavigationGuardProps.md +109 -0
  333. package/docs/api/interfaces/NavigationItem.md +91 -0
  334. package/docs/api/interfaces/NavigationMenuProps.md +169 -0
  335. package/docs/api/interfaces/Organisation.md +105 -0
  336. package/docs/api/interfaces/OrganisationContextRequiredError.md +37 -0
  337. package/docs/api/interfaces/OrganisationMembership.md +105 -0
  338. package/docs/api/interfaces/OrganisationSecurityError.md +49 -0
  339. package/docs/api/interfaces/PaceAppLayoutPermissionConfig.md +127 -0
  340. package/docs/api/interfaces/PaceAppLayoutRouteConfigItem.md +91 -0
  341. package/docs/api/interfaces/PaceAppLayoutRoutingConfig.md +79 -0
  342. package/docs/api/interfaces/PaceLoginPageProps.md +41 -0
  343. package/docs/api/interfaces/PagePermissionGuardProps.md +143 -0
  344. package/docs/api/interfaces/PaletteData.md +33 -0
  345. package/docs/api/interfaces/ParsedAddress.md +91 -0
  346. package/docs/api/interfaces/PermissionDeniedError.md +37 -0
  347. package/docs/api/interfaces/ProgressProps.md +35 -0
  348. package/docs/api/interfaces/ProtectedRouteProps.md +67 -0
  349. package/docs/api/interfaces/PublicPageFooterProps.md +97 -0
  350. package/docs/api/interfaces/PublicPageHeaderProps.md +99 -0
  351. package/docs/api/interfaces/PublicPageLayoutProps.md +153 -0
  352. package/docs/api/interfaces/RBACAccessValidateParams.md +41 -0
  353. package/docs/api/interfaces/RBACAccessValidateResult.md +33 -0
  354. package/docs/api/interfaces/RBACAuditLogParams.md +65 -0
  355. package/docs/api/interfaces/RBACAuditLogResult.md +41 -0
  356. package/docs/api/interfaces/RBACContext.md +41 -0
  357. package/docs/api/interfaces/RBACError.md +37 -0
  358. package/docs/api/interfaces/RBACLogger.md +97 -0
  359. package/docs/api/interfaces/RBACNotInitializedError.md +37 -0
  360. package/docs/api/interfaces/RBACPageAccessCheckParams.md +57 -0
  361. package/docs/api/interfaces/RBACPerformanceMetrics.md +109 -0
  362. package/docs/api/interfaces/RBACPermissionCheckParams.md +57 -0
  363. package/docs/api/interfaces/RBACPermissionCheckResult.md +41 -0
  364. package/docs/api/interfaces/RBACPermissionsGetParams.md +49 -0
  365. package/docs/api/interfaces/RBACPermissionsGetResult.md +49 -0
  366. package/docs/api/interfaces/RBACResult.md +47 -0
  367. package/docs/api/interfaces/RBACRoleGrantParams.md +49 -0
  368. package/docs/api/interfaces/RBACRoleGrantResult.md +41 -0
  369. package/docs/api/interfaces/RBACRoleRevokeParams.md +49 -0
  370. package/docs/api/interfaces/RBACRoleRevokeResult.md +41 -0
  371. package/docs/api/interfaces/RBACRoleValidateParams.md +41 -0
  372. package/docs/api/interfaces/RBACRoleValidateResult.md +49 -0
  373. package/docs/api/interfaces/RBACRolesListParams.md +41 -0
  374. package/docs/api/interfaces/RBACRolesListResult.md +57 -0
  375. package/docs/api/interfaces/RBACSessionTrackParams.md +57 -0
  376. package/docs/api/interfaces/RBACSessionTrackResult.md +41 -0
  377. package/docs/api/interfaces/ResourcePermissions.md +119 -0
  378. package/docs/api/interfaces/RevokeEventAppRoleParams.md +81 -0
  379. package/docs/api/interfaces/RoleManagementResult.md +41 -0
  380. package/docs/api/interfaces/SessionRestorationLoaderProps.md +29 -0
  381. package/docs/api/interfaces/StorageConfig.md +33 -0
  382. package/docs/api/interfaces/StorageFileInfo.md +57 -0
  383. package/docs/api/interfaces/StorageFileMetadata.md +113 -0
  384. package/docs/api/interfaces/StorageListOptions.md +79 -0
  385. package/docs/api/interfaces/StorageListResult.md +33 -0
  386. package/docs/api/interfaces/StorageUploadOptions.md +81 -0
  387. package/docs/api/interfaces/StorageUploadResult.md +49 -0
  388. package/docs/api/interfaces/StorageUploadSuccess.md +35 -0
  389. package/docs/api/interfaces/StorageUrlOptions.md +49 -0
  390. package/docs/api/interfaces/StyleImport.md +17 -0
  391. package/docs/api/interfaces/SwitchProps.md +30 -0
  392. package/docs/api/interfaces/TabsContentProps.md +13 -0
  393. package/docs/api/interfaces/TabsListProps.md +13 -0
  394. package/docs/api/interfaces/TabsProps.md +13 -0
  395. package/docs/api/interfaces/TabsTriggerProps.md +41 -0
  396. package/docs/api/interfaces/TextareaProps.md +43 -0
  397. package/docs/api/interfaces/ToastActionElement.md +16 -0
  398. package/docs/api/interfaces/ToastProps.md +13 -0
  399. package/docs/api/interfaces/UnifiedAuthProviderProps.md +129 -0
  400. package/docs/api/interfaces/UseAccessibleAppsReturn.md +55 -0
  401. package/docs/api/interfaces/UseFormDialogOptions.md +49 -0
  402. package/docs/api/interfaces/UseFormDialogReturn.md +95 -0
  403. package/docs/api/interfaces/UseInactivityTrackerOptions.md +103 -0
  404. package/docs/api/interfaces/UseInactivityTrackerReturn.md +91 -0
  405. package/docs/api/interfaces/UsePublicEventLogoOptions.md +69 -0
  406. package/docs/api/interfaces/UsePublicEventLogoReturn.md +66 -0
  407. package/docs/api/interfaces/UsePublicEventOptions.md +29 -0
  408. package/docs/api/interfaces/UsePublicEventReturn.md +56 -0
  409. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +39 -0
  410. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +96 -0
  411. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +76 -0
  412. package/docs/api/interfaces/UseResolvedScopeOptions.md +49 -0
  413. package/docs/api/interfaces/UseResolvedScopeReturn.md +39 -0
  414. package/docs/api/interfaces/UseResourcePermissionsOptions.md +29 -0
  415. package/docs/api/interfaces/UserEventAccess.md +92 -0
  416. package/docs/api/interfaces/UserMenuProps.md +69 -0
  417. package/docs/api/interfaces/UserProfile.md +49 -0
  418. package/docs/api/type-aliases/AccessLevel.md +11 -0
  419. package/docs/api/type-aliases/AccessLevelContext.md +14 -0
  420. package/docs/api/type-aliases/AllPermissions.md +11 -0
  421. package/docs/api/type-aliases/ApiError.md +37 -0
  422. package/docs/api/type-aliases/ApiResult.md +19 -0
  423. package/docs/api/type-aliases/AuditEventType.md +11 -0
  424. package/docs/api/type-aliases/BadgeVariant.md +18 -0
  425. package/docs/api/type-aliases/DataTableFeatureConfig.md +14 -0
  426. package/docs/api/type-aliases/DialogSize.md +13 -0
  427. package/docs/api/type-aliases/EventAppRole.md +11 -0
  428. package/docs/api/type-aliases/FileUploadProps.md +15 -0
  429. package/docs/api/type-aliases/GetRowId.md +33 -0
  430. package/docs/api/type-aliases/GlobalErrorHandler.md +35 -0
  431. package/docs/api/type-aliases/GlobalRole.md +11 -0
  432. package/docs/api/type-aliases/ImportHandlerResult.md +13 -0
  433. package/docs/api/type-aliases/NavigationMode.md +13 -0
  434. package/docs/api/type-aliases/Operation.md +11 -0
  435. package/docs/api/type-aliases/OrganisationContextType.md +13 -0
  436. package/docs/api/type-aliases/OrganisationRole.md +11 -0
  437. package/docs/api/type-aliases/PaceAppLayoutProps.md +14 -0
  438. package/docs/api/type-aliases/Permission.md +11 -0
  439. package/docs/api/type-aliases/PermissionCheck.md +46 -0
  440. package/docs/api/type-aliases/PermissionMap.md +11 -0
  441. package/docs/api/type-aliases/PermissionSource.md +13 -0
  442. package/docs/api/type-aliases/RBACConfig.md +13 -0
  443. package/docs/api/type-aliases/RBACFunctionResponse.md +57 -0
  444. package/docs/api/type-aliases/Scope.md +41 -0
  445. package/docs/api/type-aliases/SessionType.md +11 -0
  446. package/docs/api/type-aliases/UUID.md +11 -0
  447. package/docs/api/type-aliases/UnifiedAuthContextType.md +13 -0
  448. package/docs/api/type-aliases/UseFileReferenceForRecordReturn.md +161 -0
  449. package/docs/api/type-aliases/UseFileReferenceOptions.md +35 -0
  450. package/docs/api/type-aliases/UseFileReferenceReturn.md +13 -0
  451. package/docs/api/variables/ALL_PERMISSIONS.md +281 -0
  452. package/docs/api/variables/APP_PATH_MAPPING.md +14 -0
  453. package/docs/api/variables/AddressField.md +41 -0
  454. package/docs/api/variables/Alert.md +11 -0
  455. package/docs/api/variables/AlertDescription.md +11 -0
  456. package/docs/api/variables/AlertTitle.md +11 -0
  457. package/docs/api/variables/Avatar.md +13 -0
  458. package/docs/api/variables/Button.md +31 -0
  459. package/docs/api/variables/CACHE_PATTERNS.md +89 -0
  460. package/docs/api/variables/Calendar.md +74 -0
  461. package/docs/api/variables/Card.md +11 -0
  462. package/docs/api/variables/CardActions.md +11 -0
  463. package/docs/api/variables/CardContent.md +11 -0
  464. package/docs/api/variables/CardDescription.md +11 -0
  465. package/docs/api/variables/CardFooter.md +11 -0
  466. package/docs/api/variables/CardHeader.md +11 -0
  467. package/docs/api/variables/CardTitle.md +11 -0
  468. package/docs/api/variables/Checkbox.md +11 -0
  469. package/docs/api/variables/DEFAULT_APP_PORT_MAP.md +14 -0
  470. package/docs/api/variables/DEFAULT_FILE_SIZE_LIMIT.md +13 -0
  471. package/docs/api/variables/Dialog.md +14 -0
  472. package/docs/api/variables/DialogClose.md +14 -0
  473. package/docs/api/variables/DialogContent.md +28 -0
  474. package/docs/api/variables/DialogDescription.md +14 -0
  475. package/docs/api/variables/DialogPortal.md +14 -0
  476. package/docs/api/variables/DialogTitle.md +14 -0
  477. package/docs/api/variables/DialogTrigger.md +14 -0
  478. package/docs/api/variables/EVENT_APP_PERMISSIONS.md +109 -0
  479. package/docs/api/variables/ErrorBoundary.md +15 -0
  480. package/docs/api/variables/FILE_SIZE_LIMITS.md +13 -0
  481. package/docs/api/variables/Footer.md +11 -0
  482. package/docs/api/variables/GLOBAL_PERMISSIONS.md +29 -0
  483. package/docs/api/variables/Label.md +34 -0
  484. package/docs/api/variables/LoadingSpinner.md +28 -0
  485. package/docs/api/variables/LoginForm.md +34 -0
  486. package/docs/api/variables/NavigationMenu.md +203 -0
  487. package/docs/api/variables/ORGANISATION_PERMISSIONS.md +89 -0
  488. package/docs/api/variables/PAGE_PERMISSIONS.md +93 -0
  489. package/docs/api/variables/PaceLoginPage.md +40 -0
  490. package/docs/api/variables/PagePermissionGuard.md +11 -0
  491. package/docs/api/variables/Progress.md +32 -0
  492. package/docs/api/variables/SECURE_CLIENT_SYMBOL.md +14 -0
  493. package/docs/api/variables/STORAGE_CONFIG.md +13 -0
  494. package/docs/api/variables/Select.md +26 -0
  495. package/docs/api/variables/SelectContent.md +26 -0
  496. package/docs/api/variables/SelectGroup.md +26 -0
  497. package/docs/api/variables/SelectItem.md +26 -0
  498. package/docs/api/variables/SelectLabel.md +26 -0
  499. package/docs/api/variables/SelectSeparator.md +26 -0
  500. package/docs/api/variables/SelectTrigger.md +26 -0
  501. package/docs/api/variables/SelectValue.md +26 -0
  502. package/docs/api/variables/SessionRestorationLoader.md +11 -0
  503. package/docs/api/variables/Switch.md +23 -0
  504. package/docs/api/variables/Table.md +35 -0
  505. package/docs/api/variables/TableBody.md +11 -0
  506. package/docs/api/variables/TableCaption.md +11 -0
  507. package/docs/api/variables/TableCell.md +11 -0
  508. package/docs/api/variables/TableFooter.md +11 -0
  509. package/docs/api/variables/TableHead.md +11 -0
  510. package/docs/api/variables/TableHeader.md +11 -0
  511. package/docs/api/variables/TableRow.md +11 -0
  512. package/docs/api/variables/Tabs.md +25 -0
  513. package/docs/api/variables/TabsContent.md +24 -0
  514. package/docs/api/variables/TabsList.md +25 -0
  515. package/docs/api/variables/TabsTrigger.md +34 -0
  516. package/docs/api/variables/Toast.md +36 -0
  517. package/docs/api/variables/ToastAction.md +32 -0
  518. package/docs/api/variables/ToastClose.md +32 -0
  519. package/docs/api/variables/ToastDescription.md +32 -0
  520. package/docs/api/variables/ToastProvider.md +11 -0
  521. package/docs/api/variables/ToastTitle.md +32 -0
  522. package/docs/api/variables/ToastViewport.md +26 -0
  523. package/docs/api/variables/Tooltip.md +34 -0
  524. package/docs/api/variables/TooltipContent.md +34 -0
  525. package/docs/api/variables/TooltipProvider.md +11 -0
  526. package/docs/api/variables/TooltipRoot.md +11 -0
  527. package/docs/api/variables/TooltipTrigger.md +11 -0
  528. package/docs/api/variables/UserMenu.md +11 -0
  529. package/docs/api/variables/emailSchema.md +13 -0
  530. package/docs/api/variables/logger.md +203 -0
  531. package/docs/api/variables/nameSchema.md +13 -0
  532. package/docs/api/variables/passwordSchema.md +13 -0
  533. package/docs/api/variables/phoneSchema.md +13 -0
  534. package/docs/api/variables/rbacCache.md +16 -0
  535. package/docs/api/variables/styleConfig.md +25 -0
  536. package/docs/api/variables/urlSchema.md +13 -0
  537. package/docs/api-reference/hooks.md +2 -0
  538. package/docs/api-reference/rpc-functions.md +12 -3
  539. package/docs/core-concepts/rbac-system.md +8 -0
  540. package/docs/getting-started/cursor-rules.md +17 -20
  541. package/docs/getting-started/dependencies.md +1 -1
  542. package/docs/getting-started/setup.md +235 -0
  543. package/docs/implementation-guides/authentication.md +27 -0
  544. package/docs/implementation-guides/data-tables.md +184 -3
  545. package/docs/migration/ApiResult-migration.md +25 -0
  546. package/docs/rbac/api-reference.md +33 -31
  547. package/docs/rbac/getting-started.md +7 -0
  548. package/docs/rbac/troubleshooting.md +5 -1
  549. package/docs/standards/0-standards-overview.md +50 -15
  550. package/docs/standards/1-pace-core-compliance-standards.md +62 -57
  551. package/docs/standards/2-project-structure-standards.md +33 -16
  552. package/docs/standards/3-architecture-standards.md +41 -1
  553. package/docs/standards/4-code-quality-standards.md +26 -6
  554. package/docs/standards/5-styling-standards.md +35 -1
  555. package/docs/standards/6-security-rbac-standards.md +66 -0
  556. package/docs/standards/7-api-tech-stack-standards.md +25 -14
  557. package/docs/standards/8-testing-documentation-standards.md +31 -0
  558. package/docs/standards/9-operations-standards.md +19 -0
  559. package/docs/standards/README.md +20 -201
  560. package/docs/testing/test-setup-for-consumers.md +2 -0
  561. package/docs/troubleshooting/common-issues.md +17 -1
  562. package/docs/troubleshooting/organisation-context-setup.md +8 -0
  563. package/docs/troubleshooting/print-event-name-css-variable-analysis.md +217 -0
  564. package/eslint-config-pace-core.cjs +20 -0
  565. package/package.json +16 -22
  566. package/scripts/build-docs.js +180 -0
  567. package/scripts/setup.cjs +536 -0
  568. package/scripts/validate.cjs +480 -0
  569. package/src/__tests__/helpers/component-test-utils.test.tsx +260 -0
  570. package/src/__tests__/helpers/optimized-test-setup.test.ts +224 -0
  571. package/src/__tests__/helpers/supabaseMock.test.ts +273 -0
  572. package/src/__tests__/helpers/test-providers.test.tsx +99 -0
  573. package/src/__tests__/helpers/test-providers.tsx +37 -39
  574. package/src/__tests__/helpers/test-utils.test.tsx +447 -0
  575. package/src/__tests__/helpers/timer-utils.test.ts +371 -0
  576. package/src/assets/app-icons/index.test.ts +304 -0
  577. package/src/components/AddressField/AddressField.test.tsx +1 -1
  578. package/src/components/AddressField/AddressField.tsx +238 -212
  579. package/src/components/Button/Button.tsx +1 -1
  580. package/src/components/Card/Card.test.tsx +172 -17
  581. package/src/components/Card/Card.tsx +19 -10
  582. package/src/components/ContextSelector/ContextSelector.internals.tsx +204 -0
  583. package/src/components/ContextSelector/ContextSelector.test.tsx +360 -0
  584. package/src/components/ContextSelector/ContextSelector.tsx +66 -280
  585. package/src/components/ContextSelector/ContextSelector.types.ts +35 -0
  586. package/src/components/ContextSelector/useContextSelectorState.tsx +195 -0
  587. package/src/components/DataTable/AUDIT_REPORT.md +59 -44
  588. package/src/components/DataTable/DataTable.comprehensive.test.tsx +759 -0
  589. package/src/components/DataTable/DataTable.default-state.test.tsx +524 -0
  590. package/src/components/DataTable/DataTable.export.test.tsx +705 -0
  591. package/src/components/DataTable/DataTable.grouping-aggregation.test.tsx +658 -0
  592. package/src/components/DataTable/DataTable.hooks.test.tsx +192 -0
  593. package/src/components/DataTable/DataTable.select-label-display.test.tsx +485 -0
  594. package/src/components/DataTable/DataTable.test.tsx +787 -416
  595. package/src/components/DataTable/DataTable.tsx +12 -12
  596. package/src/components/DataTable/DataTableCore.integration.test.tsx +458 -0
  597. package/src/components/DataTable/DataTableCore.test-setup.ts +221 -0
  598. package/src/components/DataTable/DataTableCore.test.tsx +970 -0
  599. package/src/components/DataTable/README.md +155 -0
  600. package/src/components/DataTable/TESTING.md +101 -0
  601. package/src/components/DataTable/a11y.basic.test.tsx +788 -0
  602. package/src/components/DataTable/components/DataTableCore.tsx +104 -864
  603. package/src/components/DataTable/components/GroupingDropdown.test.tsx +621 -0
  604. package/src/components/DataTable/components/GroupingDropdown.tsx +2 -2
  605. package/src/components/DataTable/components/ImportModal.tsx +61 -559
  606. package/src/components/DataTable/components/ImportModalFileSection.tsx +148 -0
  607. package/src/components/DataTable/context/DataTableContext.test.tsx +328 -0
  608. package/src/components/DataTable/context/DataTableContext.tsx +7 -6
  609. package/src/components/DataTable/core/ColumnFactory.test.ts +403 -0
  610. package/src/components/DataTable/hooks/useColumnOrderPersistence.test.ts +516 -0
  611. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.test.ts +256 -0
  612. package/src/components/DataTable/hooks/useDataTableConfiguration.test.ts +297 -0
  613. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +14 -2
  614. package/src/components/DataTable/hooks/useDataTableDataPipeline.test.ts +270 -0
  615. package/src/components/DataTable/hooks/useDataTableDeletionBatching.test.ts +127 -0
  616. package/src/components/DataTable/hooks/useDataTableDeletionBatching.ts +106 -0
  617. package/src/components/DataTable/hooks/useDataTableEffectiveActions.test.ts +461 -0
  618. package/src/components/DataTable/hooks/useDataTableEffectiveActions.ts +248 -0
  619. package/src/components/DataTable/hooks/useDataTableLayoutHandlers.test.ts +296 -0
  620. package/src/components/DataTable/hooks/useDataTableLayoutHandlers.ts +175 -0
  621. package/src/components/DataTable/hooks/useDataTablePaginationSync.test.ts +203 -0
  622. package/src/components/DataTable/hooks/useDataTablePaginationSync.ts +109 -0
  623. package/src/components/DataTable/hooks/useDataTablePermissions.test.ts +280 -0
  624. package/src/components/DataTable/hooks/useDataTablePermissions.ts +79 -247
  625. package/src/components/DataTable/hooks/useDataTablePipeline.test.tsx +219 -0
  626. package/src/components/DataTable/hooks/useDataTablePipeline.tsx +239 -0
  627. package/src/components/DataTable/hooks/useDataTableRenderGuard.test.tsx +316 -0
  628. package/src/components/DataTable/hooks/useDataTableRenderGuard.tsx +195 -0
  629. package/src/components/DataTable/hooks/useDataTableScope.test.ts +102 -0
  630. package/src/components/DataTable/hooks/useDataTableScope.ts +125 -0
  631. package/src/components/DataTable/hooks/useDataTableState.test.ts +733 -0
  632. package/src/components/DataTable/hooks/useDataTableState.ts +145 -94
  633. package/src/components/DataTable/hooks/useDataTableStateAndPersistence.test.ts +277 -0
  634. package/src/components/DataTable/hooks/useDataTableStateAndPersistence.ts +222 -0
  635. package/src/components/DataTable/hooks/useDataTableSuperAdmin.test.ts +93 -0
  636. package/src/components/DataTable/hooks/useDataTableSuperAdmin.ts +86 -0
  637. package/src/components/DataTable/hooks/useDataTableTableInstance.test.ts +185 -0
  638. package/src/components/DataTable/hooks/useDataTableTableInstance.ts +178 -0
  639. package/src/components/DataTable/hooks/useEffectiveColumnOrder.test.ts +183 -0
  640. package/src/components/DataTable/hooks/useHierarchicalState.test.ts +294 -0
  641. package/src/components/DataTable/hooks/useImportModalFocus.test.ts +184 -0
  642. package/src/components/DataTable/hooks/useImportModalFocus.ts +53 -0
  643. package/src/components/DataTable/hooks/useImportModalState.test.ts +390 -0
  644. package/src/components/DataTable/hooks/useImportModalState.ts +345 -0
  645. package/src/components/DataTable/hooks/useKeyboardNavigation.test.ts +787 -0
  646. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +309 -269
  647. package/src/components/DataTable/hooks/usePermissionTracking.test.ts +381 -0
  648. package/src/components/DataTable/hooks/usePermissionTracking.ts +122 -0
  649. package/src/components/DataTable/hooks/useServerSideDataEffect.test.ts +258 -0
  650. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +14 -3
  651. package/src/components/DataTable/hooks/useTableColumns.test.ts +499 -0
  652. package/src/components/DataTable/hooks/useTableHandlers.test.ts +461 -0
  653. package/src/components/DataTable/hooks/useTableHandlers.ts +5 -2
  654. package/src/components/DataTable/index.ts +18 -17
  655. package/src/components/DataTable/keyboard.test.tsx +734 -0
  656. package/src/components/DataTable/mocks/MockRBACProvider.tsx +66 -0
  657. package/src/components/DataTable/pagination.modes.test.tsx +728 -0
  658. package/src/components/DataTable/ssr.strict-mode.test.tsx +319 -0
  659. package/src/components/DataTable/styles.test.ts +379 -0
  660. package/src/components/DataTable/styles.ts +0 -1
  661. package/src/components/DataTable/test-utils/MockDataTableComponents.tsx +55 -0
  662. package/src/components/DataTable/test-utils/dataFactories.ts +103 -0
  663. package/src/components/DataTable/test-utils/featureConfig.ts +10 -0
  664. package/src/components/DataTable/test-utils/sharedTestUtils.ts +419 -0
  665. package/src/components/DataTable/test-utils.ts +94 -0
  666. package/src/components/DataTable/types/actions.ts +71 -0
  667. package/src/components/DataTable/types/base.ts +39 -0
  668. package/src/components/DataTable/types/columns.ts +125 -0
  669. package/src/components/DataTable/types/export.ts +32 -0
  670. package/src/components/DataTable/types/features.ts +81 -0
  671. package/src/components/DataTable/types/hierarchical.ts +44 -0
  672. package/src/components/DataTable/types/index.ts +43 -0
  673. package/src/components/DataTable/types/pagination.ts +85 -0
  674. package/src/components/DataTable/types/performance.ts +47 -0
  675. package/src/components/DataTable/types/props.ts +62 -0
  676. package/src/components/DataTable/types/rbac.ts +45 -0
  677. package/src/components/DataTable/ui/layout/DataTableCore.test.tsx +1194 -0
  678. package/src/components/DataTable/ui/layout/DataTableCore.tsx +345 -0
  679. package/src/components/DataTable/ui/layout/DataTableErrorBoundary.test.tsx +438 -0
  680. package/src/components/DataTable/ui/layout/DataTableErrorBoundary.tsx +225 -0
  681. package/src/components/DataTable/ui/layout/DataTableLayout.test.tsx +1352 -0
  682. package/src/components/DataTable/ui/layout/DataTableLayout.tsx +661 -0
  683. package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.test.tsx +91 -0
  684. package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.tsx +43 -0
  685. package/src/components/DataTable/ui/modals/DataTableModals.test.tsx +749 -0
  686. package/src/components/DataTable/ui/modals/DataTableModals.tsx +341 -0
  687. package/src/components/DataTable/ui/modals/ImportModal.test.tsx +1834 -0
  688. package/src/components/DataTable/ui/modals/ImportModal.tsx +197 -0
  689. package/src/components/DataTable/ui/modals/ImportModalFailedRowsSection.tsx +60 -0
  690. package/src/components/DataTable/ui/modals/ImportModalFileSection.tsx +148 -0
  691. package/src/components/DataTable/ui/modals/ImportModalPreviewSection.tsx +60 -0
  692. package/src/components/DataTable/ui/modals/ImportModalSummarySection.tsx +59 -0
  693. package/src/components/DataTable/ui/modals/importModalPersistence.ts +73 -0
  694. package/src/components/DataTable/ui/shared/AccessDeniedPage.test.tsx +245 -0
  695. package/src/components/DataTable/ui/shared/AccessDeniedPage.tsx +159 -0
  696. package/src/components/DataTable/ui/shared/ActionButtons.test.tsx +921 -0
  697. package/src/components/DataTable/ui/shared/ActionButtons.tsx +195 -0
  698. package/src/components/DataTable/ui/shared/ColumnFilter.test.tsx +497 -0
  699. package/src/components/DataTable/ui/shared/ColumnFilter.tsx +113 -0
  700. package/src/components/DataTable/ui/shared/PaginationControls.test.tsx +451 -0
  701. package/src/components/DataTable/ui/shared/PaginationControls.tsx +291 -0
  702. package/src/components/DataTable/ui/shared/SortIndicator.test.tsx +135 -0
  703. package/src/components/DataTable/ui/shared/SortIndicator.tsx +50 -0
  704. package/src/components/DataTable/ui/table/EditFields.test.tsx +526 -0
  705. package/src/components/DataTable/ui/table/EditFields.tsx +355 -0
  706. package/src/components/DataTable/ui/table/EditableRow.test.tsx +1003 -0
  707. package/src/components/DataTable/ui/table/EditableRow.tsx +444 -0
  708. package/src/components/DataTable/ui/table/EmptyState.test.tsx +360 -0
  709. package/src/components/DataTable/ui/table/EmptyState.tsx +74 -0
  710. package/src/components/DataTable/ui/table/FilterRow.test.tsx +416 -0
  711. package/src/components/DataTable/ui/table/FilterRow.tsx +148 -0
  712. package/src/components/DataTable/ui/table/LoadingState.test.tsx +77 -0
  713. package/src/components/DataTable/ui/table/LoadingState.tsx +17 -0
  714. package/src/components/DataTable/ui/table/RowComponent.test.tsx +1024 -0
  715. package/src/components/DataTable/ui/table/RowComponent.tsx +429 -0
  716. package/src/components/DataTable/ui/table/UnifiedTableBody.test.tsx +1273 -0
  717. package/src/components/DataTable/ui/table/UnifiedTableBody.tsx +440 -0
  718. package/src/components/DataTable/ui/table/cellValueUtils.test.ts +453 -0
  719. package/src/components/DataTable/ui/table/cellValueUtils.ts +40 -0
  720. package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.test.tsx +551 -0
  721. package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.tsx +160 -0
  722. package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.test.tsx +751 -0
  723. package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.tsx +114 -0
  724. package/src/components/DataTable/ui/toolbar/DataTableToolbar.test.tsx +629 -0
  725. package/src/components/DataTable/ui/toolbar/DataTableToolbar.tsx +271 -0
  726. package/src/components/DataTable/ui/toolbar/GroupingDropdown.test.tsx +621 -0
  727. package/src/components/DataTable/ui/toolbar/GroupingDropdown.tsx +107 -0
  728. package/src/components/DataTable/utils/a11yUtils.test.ts +548 -0
  729. package/src/components/DataTable/utils/aggregationUtils.test.ts +288 -0
  730. package/src/components/DataTable/utils/columnUtils.test.ts +94 -0
  731. package/src/components/DataTable/utils/csvParse.test.ts +74 -0
  732. package/src/components/DataTable/utils/csvParse.ts +65 -0
  733. package/src/components/DataTable/utils/errorHandling.test.ts +209 -0
  734. package/src/components/DataTable/utils/exportUtils.test.ts +954 -0
  735. package/src/components/DataTable/utils/flexibleImport.test.ts +573 -0
  736. package/src/components/DataTable/utils/flexibleImport.ts +3 -186
  737. package/src/components/DataTable/utils/hierarchicalSorting.test.ts +235 -0
  738. package/src/components/DataTable/utils/hierarchicalUtils.test.ts +586 -0
  739. package/src/components/DataTable/utils/importDateParser.test.ts +162 -0
  740. package/src/components/DataTable/utils/importDateParser.ts +114 -0
  741. package/src/components/DataTable/utils/importValueParser.test.ts +138 -0
  742. package/src/components/DataTable/utils/importValueParser.ts +91 -0
  743. package/src/components/DataTable/utils/paginationUtils.test.ts +593 -0
  744. package/src/components/DataTable/utils/paginationUtils.ts +6 -3
  745. package/src/components/DataTable/utils/performanceUtils.test.ts +470 -0
  746. package/src/components/DataTable/utils/rowUtils.test.ts +235 -0
  747. package/src/components/DataTable/utils/selectFieldUtils.test.ts +271 -0
  748. package/src/components/DataTable/utils/selectFieldUtils.ts +97 -60
  749. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
  750. package/src/components/DateTimeField/DateTimeField.test.tsx +1 -1
  751. package/src/components/Dialog/Dialog.test-utils.ts +49 -0
  752. package/src/components/Dialog/Dialog.test.tsx +896 -89
  753. package/src/components/Dialog/Dialog.tsx +174 -882
  754. package/src/components/Dialog/dialogLock.test.ts +238 -0
  755. package/src/components/Dialog/dialogLock.ts +98 -0
  756. package/src/components/Dialog/index.ts +2 -0
  757. package/src/components/Dialog/useDialogDimensions.test.ts +163 -0
  758. package/src/components/Dialog/useDialogDimensions.ts +140 -0
  759. package/src/components/Dialog/useDialogLifecycle.test.ts +361 -0
  760. package/src/components/Dialog/useDialogLifecycle.ts +135 -0
  761. package/src/components/Dialog/useDialogPersistence.test.ts +381 -0
  762. package/src/components/Dialog/useDialogPersistence.ts +357 -0
  763. package/src/components/FileDisplay/FileDisplay.test.tsx +40 -40
  764. package/src/components/FileDisplay/FileDisplay.tsx +24 -656
  765. package/src/components/FileDisplay/FileDisplayContent.test.tsx +395 -0
  766. package/src/components/FileDisplay/FileDisplayContent.tsx +242 -0
  767. package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.test.tsx +74 -0
  768. package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.tsx +38 -0
  769. package/src/components/FileDisplay/FileDisplayEmptyView.test.tsx +33 -0
  770. package/src/components/FileDisplay/FileDisplayEmptyView.tsx +33 -0
  771. package/src/components/FileDisplay/FileDisplayErrorView.test.tsx +71 -0
  772. package/src/components/FileDisplay/FileDisplayErrorView.tsx +50 -0
  773. package/src/components/FileDisplay/FileDisplayLoadingFallbackView.test.tsx +22 -0
  774. package/src/components/FileDisplay/FileDisplayLoadingFallbackView.tsx +22 -0
  775. package/src/components/FileDisplay/FileDisplayLoadingView.test.tsx +21 -0
  776. package/src/components/FileDisplay/FileDisplayLoadingView.tsx +23 -0
  777. package/src/components/FileDisplay/FileDisplayMultipleFilesView.test.tsx +101 -0
  778. package/src/components/FileDisplay/FileDisplayMultipleFilesView.tsx +109 -0
  779. package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.test.tsx +58 -0
  780. package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.tsx +48 -0
  781. package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.test.tsx +111 -0
  782. package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.tsx +270 -0
  783. package/src/components/FileDisplay/FileDisplaySingleImageView.test.tsx +78 -0
  784. package/src/components/FileDisplay/FileDisplaySingleImageView.tsx +67 -0
  785. package/src/components/FileDisplay/fallbackUtils.test.ts +50 -0
  786. package/src/components/FileDisplay/fallbackUtils.ts +44 -0
  787. package/src/components/FileDisplay/fetchFileDisplayData.ts +24 -0
  788. package/src/components/FileDisplay/fetchFileDisplayData.unit.test.ts +183 -0
  789. package/src/components/FileDisplay/fileDisplayUtils.test.ts +58 -0
  790. package/src/components/FileDisplay/fileDisplayUtils.ts +24 -0
  791. package/src/components/FileDisplay/useFileDisplay.test.ts +538 -0
  792. package/src/components/FileDisplay/useFileDisplay.ts +515 -0
  793. package/src/components/FileDisplay/useFileDisplay.unit.test.ts +1442 -0
  794. package/src/components/FileDisplay/useFileDisplayData.ts +126 -0
  795. package/src/components/FileDisplay/usePublicFileDisplay.test.ts +729 -0
  796. package/src/components/FileDisplay/usePublicFileDisplay.ts +579 -0
  797. package/src/components/FileUpload/FileUpload.test.tsx +16 -10
  798. package/src/components/FileUpload/FileUpload.tsx +107 -525
  799. package/src/components/FileUpload/FileUploadDropZone.tsx +112 -0
  800. package/src/components/FileUpload/FileUploadProgressItem.tsx +86 -0
  801. package/src/components/FileUpload/FileUploadProgressList.tsx +40 -0
  802. package/src/components/FileUpload/useFileUploadManager.test.ts +308 -0
  803. package/src/components/FileUpload/useFileUploadManager.ts +454 -0
  804. package/src/components/FileUpload/useResolvedAppId.test.ts +102 -0
  805. package/src/components/FileUpload/useResolvedAppId.ts +77 -0
  806. package/src/components/Footer/Footer.test.tsx +6 -292
  807. package/src/components/Footer/Footer.tsx +8 -125
  808. package/src/components/Form/Form.test.tsx +44 -27
  809. package/src/components/Form/Form.tsx +64 -287
  810. package/src/components/Form/useFormPersistence.ts +257 -0
  811. package/src/components/Header/Header.test.tsx +17 -18
  812. package/src/components/Header/Header.tsx +10 -1
  813. package/src/components/Input/Input.tsx +1 -1
  814. package/src/components/Label/Label.test.tsx +1 -1
  815. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +1 -1
  816. package/src/components/NavigationMenu/HierarchicalNavItem.tsx +104 -0
  817. package/src/components/NavigationMenu/NavigationMenu.test.tsx +1029 -26
  818. package/src/components/NavigationMenu/NavigationMenu.tsx +61 -361
  819. package/src/components/NavigationMenu/index.ts +6 -1
  820. package/src/components/NavigationMenu/navigationPermissionHelper.ts +188 -0
  821. package/src/components/NavigationMenu/useNavigationFiltering.test.ts +1949 -0
  822. package/src/components/NavigationMenu/useNavigationFiltering.ts +197 -296
  823. package/src/components/NavigationMenu/useNavigationScope.ts +125 -0
  824. package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +109 -70
  825. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +3 -3
  826. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +16 -19
  827. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +529 -5
  828. package/src/components/PaceAppLayout/PaceAppLayout.tsx +280 -756
  829. package/src/components/PaceAppLayout/useFilteredNavItems.ts +319 -0
  830. package/src/components/PaceAppLayout/usePaceAppLayoutConfig.ts +163 -0
  831. package/src/components/PaceAppLayout/usePaceAppLayoutGate.tsx +150 -0
  832. package/src/components/PaceAppLayout/usePaceAppLayoutPermissions.ts +162 -0
  833. package/src/components/PaceAppLayout/usePaceAppLayoutScope.ts +81 -0
  834. package/src/components/PaceAppLayout/useRoleBasedRouteAccess.ts +157 -0
  835. package/src/components/PaceAppLayout/useSuperAdminFallback.ts +58 -0
  836. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +31 -25
  837. package/src/components/PaceLoginPage/PaceLoginPage.tsx +31 -122
  838. package/src/components/PaceLoginPage/useLoginAppAccess.ts +153 -0
  839. package/src/components/Progress/Progress.tsx +1 -2
  840. package/src/components/ProtectedRoute/ProtectedRoute.tsx +29 -235
  841. package/src/components/ProtectedRoute/useProtectedRouteState.ts +128 -0
  842. package/src/components/ProtectedRoute/useVisibilityRedirectGrace.ts +89 -0
  843. package/src/components/PublicLayout/PublicLayout.test.tsx +217 -36
  844. package/src/components/PublicLayout/PublicPageLayout.tsx +132 -73
  845. package/src/components/PublicLayout/PublicPageProvider.tsx +5 -1
  846. package/src/components/Select/Select.test.tsx +1 -1
  847. package/src/components/Select/Select.tsx +28 -18
  848. package/src/components/Select/context.test.tsx +56 -0
  849. package/src/components/Select/text.test.tsx +104 -0
  850. package/src/components/Select/text.ts +26 -0
  851. package/src/components/Select/useSelectEvents.test.ts +279 -0
  852. package/src/components/Select/useSelectEvents.ts +87 -0
  853. package/src/components/Select/useSelectSearch.test.tsx +295 -0
  854. package/src/components/Select/useSelectSearch.ts +91 -0
  855. package/src/components/Select/useSelectState.test.ts +268 -0
  856. package/src/components/Select/useSelectState.ts +104 -0
  857. package/src/components/Table/Table.test.tsx +348 -0
  858. package/src/components/Tabs/Tabs.test.tsx +270 -0
  859. package/src/components/Tabs/Tabs.tsx +1 -1
  860. package/src/components/Toast/Toast.test.tsx +420 -0
  861. package/src/components/index.test.ts +346 -0
  862. package/src/constants/performance.test.ts +91 -0
  863. package/src/hooks/ServiceHooks.test.tsx +725 -0
  864. package/src/hooks/hooks.integration.test.tsx +608 -0
  865. package/src/hooks/index.ts +7 -4
  866. package/src/hooks/index.unit.test.ts +220 -0
  867. package/src/hooks/public/usePublicEvent.test.ts +1 -1
  868. package/src/hooks/public/usePublicEventLogo.test.ts +1 -1
  869. package/src/hooks/public/usePublicRouteParams.test.ts +1 -1
  870. package/src/hooks/services/useAuth.ts +9 -7
  871. package/src/hooks/useAddressAutocomplete.test.ts +22 -22
  872. package/src/hooks/useAddressAutocomplete.ts +90 -75
  873. package/src/hooks/useAppConfig.unit.test.ts +720 -0
  874. package/src/hooks/useComponentPerformance.unit.test.tsx +316 -0
  875. package/src/hooks/useDataTablePerformance.ts +100 -120
  876. package/src/hooks/useDataTablePerformance.unit.test.ts +720 -0
  877. package/src/hooks/useDataTableState.test.ts +170 -0
  878. package/src/hooks/useDebounce.unit.test.ts +157 -0
  879. package/src/hooks/useEventTheme.test.ts +4 -1
  880. package/src/hooks/useEventTheme.ts +49 -21
  881. package/src/hooks/useEvents.ts +41 -1
  882. package/src/hooks/useEvents.unit.test.ts +227 -0
  883. package/src/hooks/useFileReference.test.ts +44 -41
  884. package/src/hooks/useFileReference.ts +182 -173
  885. package/src/hooks/useFileUrl.ts +1 -1
  886. package/src/hooks/useFileUrl.unit.test.ts +684 -0
  887. package/src/hooks/useFileUrlCache.test.ts +319 -0
  888. package/src/hooks/useFileUrlCache.ts +1 -1
  889. package/src/hooks/useFocusManagement.unit.test.ts +604 -0
  890. package/src/hooks/useFocusTrap.unit.test.tsx +613 -0
  891. package/src/hooks/useFormDialog.test.ts +307 -0
  892. package/src/hooks/useInactivityTracker.ts +138 -131
  893. package/src/hooks/useInactivityTracker.unit.test.ts +450 -0
  894. package/src/hooks/useIsMobile.unit.test.ts +317 -0
  895. package/src/hooks/useIsPrint.ts +62 -0
  896. package/src/hooks/useIsPrint.unit.test.ts +545 -0
  897. package/src/hooks/useKeyboardShortcuts.unit.test.ts +907 -0
  898. package/src/hooks/useOrganisationPermissions.unit.test.tsx +293 -0
  899. package/src/hooks/useOrganisationSecurity.test.ts +3 -3
  900. package/src/hooks/useOrganisationSecurity.ts +190 -201
  901. package/src/hooks/useOrganisationSecurity.unit.test.tsx +959 -0
  902. package/src/hooks/useOrganisations.unit.test.ts +369 -0
  903. package/src/hooks/usePerformanceMonitor.unit.test.ts +683 -0
  904. package/src/hooks/usePermissionCache.test.ts +505 -0
  905. package/src/hooks/usePermissionCache.ts +276 -271
  906. package/src/hooks/usePreventTabReload.test.ts +307 -0
  907. package/src/hooks/usePublicEvent.simple.test.ts +779 -0
  908. package/src/hooks/usePublicEvent.test.ts +664 -0
  909. package/src/hooks/usePublicEvent.unit.test.ts +638 -0
  910. package/src/hooks/usePublicFileDisplay.test.ts +948 -0
  911. package/src/hooks/usePublicRouteParams.unit.test.ts +442 -0
  912. package/src/hooks/useQueryCache.test.ts +391 -0
  913. package/src/hooks/useQueryCache.ts +0 -2
  914. package/src/hooks/useRBAC.unit.test.ts +253 -0
  915. package/src/hooks/useSessionDraft.test.ts +556 -0
  916. package/src/hooks/useSessionRestoration.unit.test.tsx +381 -0
  917. package/src/hooks/useStorage.ts +21 -16
  918. package/src/hooks/useStorage.unit.test.ts +684 -0
  919. package/src/hooks/useToast.test.ts +413 -0
  920. package/src/hooks/useToast.unit.test.tsx +481 -0
  921. package/src/hooks/useZodForm.unit.test.tsx +191 -0
  922. package/src/icons/index.test.ts +133 -0
  923. package/src/icons/index.ts +2 -0
  924. package/src/index.test.ts +528 -0
  925. package/src/index.ts +15 -7
  926. package/src/providers/AuthProvider.test.tsx +218 -0
  927. package/src/providers/EventProvider.test.tsx +487 -0
  928. package/src/providers/InactivityProvider.test-helper.tsx +40 -0
  929. package/src/providers/InactivityProvider.test.tsx +421 -0
  930. package/src/providers/ProviderLifecycle.test.tsx +308 -0
  931. package/src/providers/UnifiedAuthProvider.test.tsx +503 -0
  932. package/src/providers/index.test.ts +138 -0
  933. package/src/providers/services/AuthServiceProvider.integration.test.tsx +229 -0
  934. package/src/providers/services/AuthServiceProvider.test.tsx +643 -0
  935. package/src/providers/services/EventServiceProvider.test.tsx +844 -0
  936. package/src/providers/services/InactivityServiceProvider.test.tsx +667 -0
  937. package/src/providers/services/OrganisationServiceProvider.test.tsx +445 -0
  938. package/src/providers/services/UnifiedAuthContext.ts +30 -27
  939. package/src/providers/services/UnifiedAuthProvider.advanced.test.tsx +434 -0
  940. package/src/providers/services/UnifiedAuthProvider.appId.test.tsx +408 -0
  941. package/src/providers/services/UnifiedAuthProvider.integration.test.tsx +304 -0
  942. package/src/providers/services/UnifiedAuthProvider.tsx +115 -360
  943. package/src/providers/services/contexts.test.tsx +281 -0
  944. package/src/providers/services/useUnifiedAuth.test.tsx +251 -0
  945. package/src/providers/services/useUnifiedAuthContextValue.ts +279 -0
  946. package/src/providers/useInactivity.test-helper.ts +27 -0
  947. package/src/rbac/README.md +7 -5
  948. package/src/rbac/adapters.comprehensive.test.tsx +429 -0
  949. package/src/rbac/adapters.test.tsx +22 -22
  950. package/src/rbac/adapters.tsx +29 -29
  951. package/src/rbac/api.test.ts +1075 -87
  952. package/src/rbac/api.ts +300 -255
  953. package/src/rbac/audit-batched.test.ts +550 -0
  954. package/src/rbac/audit.ts +4 -1
  955. package/src/rbac/auth-rbac-security.integration.test.tsx +300 -0
  956. package/src/rbac/auth-rbac.e2e.test.tsx +510 -0
  957. package/src/rbac/cache-invalidation.test.ts +715 -0
  958. package/src/rbac/components/AccessDenied.test.tsx +324 -0
  959. package/src/rbac/components/NavigationGuard.test.tsx +1148 -0
  960. package/src/rbac/components/NavigationGuard.tsx +2 -1
  961. package/src/rbac/components/PagePermissionGuard.guard.test.tsx +236 -0
  962. package/src/rbac/components/PagePermissionGuard.performance.test.tsx +252 -0
  963. package/src/rbac/components/PagePermissionGuard.race-condition.test.tsx +243 -0
  964. package/src/rbac/components/PagePermissionGuard.test.tsx +1443 -0
  965. package/src/rbac/components/PagePermissionGuard.tsx +177 -372
  966. package/src/rbac/components/PagePermissionGuard.verification.test.tsx +185 -0
  967. package/src/rbac/config.ts +58 -18
  968. package/src/rbac/engine.comprehensive.test.ts +808 -0
  969. package/src/rbac/engine.test.ts +494 -0
  970. package/src/rbac/engine.ts +23 -1
  971. package/src/rbac/errors.ts +89 -55
  972. package/src/rbac/hooks/permissions/runPermissionCheck.ts +91 -0
  973. package/src/rbac/hooks/permissions/useAccessLevel.test.ts +622 -0
  974. package/src/rbac/hooks/permissions/useAccessLevel.ts +16 -6
  975. package/src/rbac/hooks/permissions/useCan.test.ts +837 -0
  976. package/src/rbac/hooks/permissions/useCan.ts +177 -255
  977. package/src/rbac/hooks/permissions/useMultiplePermissions.test.ts +843 -0
  978. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +24 -11
  979. package/src/rbac/hooks/permissions/usePermissions.test.ts +543 -0
  980. package/src/rbac/hooks/permissions/usePermissions.ts +36 -65
  981. package/src/rbac/hooks/useCan.test.ts +44 -45
  982. package/src/rbac/hooks/usePageAccessLogging.ts +160 -0
  983. package/src/rbac/hooks/usePageGuardScope.ts +119 -0
  984. package/src/rbac/hooks/usePagePermissionCheck.ts +67 -0
  985. package/src/rbac/hooks/usePermissions.integration.test.ts +427 -0
  986. package/src/rbac/hooks/usePermissions.stability.test.ts +268 -0
  987. package/src/rbac/hooks/usePermissions.test.ts +54 -54
  988. package/src/rbac/hooks/useRBAC.test.ts +313 -217
  989. package/src/rbac/hooks/useRBAC.ts +145 -81
  990. package/src/rbac/hooks/useResolvedScope.ts +16 -10
  991. package/src/rbac/hooks/useResourcePermissions.test.ts +73 -83
  992. package/src/rbac/hooks/useResourcePermissions.ts +77 -152
  993. package/src/rbac/hooks/useResourcePermissionsSuperAdmin.ts +67 -0
  994. package/src/rbac/hooks/useRoleManagement.test.ts +27 -112
  995. package/src/rbac/hooks/useRoleManagement.ts +153 -585
  996. package/src/rbac/hooks/useSecureSupabase.test.ts +1179 -0
  997. package/src/rbac/hooks/useSecureSupabase.ts +10 -2
  998. package/src/rbac/hooks/useSuperAdminCheck.ts +80 -0
  999. package/src/rbac/performance.test.ts +451 -0
  1000. package/src/rbac/rbac-core.test.tsx +276 -0
  1001. package/src/rbac/rbac-engine-core-logic.test.ts +387 -0
  1002. package/src/rbac/rbac-engine-simplified.test.ts +252 -0
  1003. package/src/rbac/rbac-functions.test.ts +703 -0
  1004. package/src/rbac/rbac-role-isolation.test.ts +456 -0
  1005. package/src/rbac/request-deduplication.test.ts +14 -9
  1006. package/src/rbac/request-deduplication.ts +5 -4
  1007. package/src/rbac/scenarios.user-role.test.tsx +271 -0
  1008. package/src/rbac/secureClient.test.ts +514 -83
  1009. package/src/rbac/secureClient.ts +8 -2
  1010. package/src/rbac/security.test.ts +323 -0
  1011. package/src/rbac/types/roleManagement.ts +66 -0
  1012. package/src/rbac/types.ts +3 -0
  1013. package/src/rbac/utils/clientSecurity.test.ts +192 -0
  1014. package/src/rbac/utils/contextValidator.test.ts +126 -0
  1015. package/src/rbac/utils/contextValidator.ts +5 -1
  1016. package/src/rbac/utils/deep-equal.test.ts +76 -0
  1017. package/src/rbac/utils/eventContext.test.ts +401 -0
  1018. package/src/rbac/utils/eventContext.ts +37 -33
  1019. package/src/rbac/utils/fetchPermissionMap.ts +13 -0
  1020. package/src/rbac/utils/permissionMapHelpers.ts +34 -0
  1021. package/src/rbac/utils/roleManagementRpc.ts +303 -0
  1022. package/src/services/AuthService.edge-cases.test.ts +746 -0
  1023. package/src/services/AuthService.restoreSession.test.ts +59 -0
  1024. package/src/services/AuthService.test.ts +1362 -0
  1025. package/src/services/AuthService.ts +184 -205
  1026. package/src/services/BaseService.edge-cases.test.ts +506 -0
  1027. package/src/services/BaseService.test.ts +363 -0
  1028. package/src/services/EventService.edge-cases.test.ts +636 -0
  1029. package/src/services/EventService.eventColours.test.ts +64 -0
  1030. package/src/services/EventService.test.ts +1250 -0
  1031. package/src/services/EventService.ts +251 -316
  1032. package/src/services/InactivityService.edge-cases.test.ts +492 -0
  1033. package/src/services/InactivityService.lifecycle.test.ts +406 -0
  1034. package/src/services/InactivityService.test.ts +829 -0
  1035. package/src/services/InactivityService.ts +172 -213
  1036. package/src/services/OrganisationService.edge-cases.test.ts +633 -0
  1037. package/src/services/OrganisationService.pagination.test.ts +409 -0
  1038. package/src/services/OrganisationService.test.ts +1579 -0
  1039. package/src/services/OrganisationService.ts +184 -238
  1040. package/src/services/base/BaseService.test.ts +1 -1
  1041. package/src/services/interfaces/IAuthService.test.ts +184 -0
  1042. package/src/services/interfaces/IAuthService.ts +10 -9
  1043. package/src/services/interfaces/IEventService.test.ts +176 -0
  1044. package/src/services/interfaces/IInactivityService.test.ts +183 -0
  1045. package/src/services/interfaces/IOrganisationService.test.ts +207 -0
  1046. package/src/styles/core.css +243 -12
  1047. package/src/theming/parseEventColours.test.ts +321 -0
  1048. package/src/theming/runtime.test.ts +495 -0
  1049. package/src/theming/runtime.ts +71 -2
  1050. package/src/types/api-result.ts +53 -0
  1051. package/src/types/core.test.ts +397 -0
  1052. package/src/types/database-generated.test.ts +78 -0
  1053. package/src/types/database.generated.ts +45 -10
  1054. package/src/types/event.ts +38 -18
  1055. package/src/types/file-reference.test.ts +351 -0
  1056. package/src/types/file-reference.ts +37 -12
  1057. package/src/types/guards.test.ts +246 -0
  1058. package/src/types/index.test.ts +265 -0
  1059. package/src/types/index.ts +3 -0
  1060. package/src/types/organisation.roles.test.ts +55 -0
  1061. package/src/types/organisation.test.ts +1105 -0
  1062. package/src/types/organisation.ts +15 -15
  1063. package/src/types/supabase.ts +13 -4
  1064. package/src/types/theme.test.ts +830 -0
  1065. package/src/types/type-validation.test.ts +526 -0
  1066. package/src/types/validation.test.ts +729 -0
  1067. package/src/utils/app/appIdResolver.test.ts +98 -71
  1068. package/src/utils/app/appIdResolver.ts +31 -20
  1069. package/src/utils/appConfig.unit.test.ts +55 -0
  1070. package/src/utils/audit.unit.test.ts +69 -0
  1071. package/src/utils/auth-utils.unit.test.ts +69 -0
  1072. package/src/utils/bundleAnalysis.unit.test.ts +326 -0
  1073. package/src/utils/cn.unit.test.ts +34 -0
  1074. package/src/utils/context/organisationContext.test.ts +105 -91
  1075. package/src/utils/context/organisationContext.ts +29 -40
  1076. package/src/utils/core/cn.test.ts +66 -0
  1077. package/src/utils/core/debugLogger.test.ts +113 -0
  1078. package/src/utils/core/logger.test.ts +217 -0
  1079. package/src/utils/core/mergeRefs.ts +24 -0
  1080. package/src/utils/debugLogger.test.ts +417 -0
  1081. package/src/utils/deviceFingerprint.unit.test.ts +818 -0
  1082. package/src/utils/dynamic/createLazyComponent.tsx +9 -1
  1083. package/src/utils/dynamic/dynamicUtils.test.ts +185 -0
  1084. package/src/utils/dynamic/lazyLoad.test.tsx +156 -0
  1085. package/src/utils/dynamicUtils.unit.test.ts +331 -0
  1086. package/src/utils/file-reference/file-reference.test.ts +1249 -0
  1087. package/src/utils/file-reference/index.ts +330 -347
  1088. package/src/utils/formatDate.unit.test.ts +109 -0
  1089. package/src/utils/formatting/formatDateTimeTimezone.test.ts +1 -1
  1090. package/src/utils/formatting/formatNumber.test.ts +1 -1
  1091. package/src/utils/formatting.unit.test.ts +99 -0
  1092. package/src/utils/google-places/googlePlacesUtils.test.ts +70 -48
  1093. package/src/utils/google-places/googlePlacesUtils.ts +67 -99
  1094. package/src/utils/google-places/loadGoogleMapsScript.test.ts +25 -22
  1095. package/src/utils/google-places/loadGoogleMapsScript.ts +138 -117
  1096. package/src/utils/index.unit.test.ts +251 -0
  1097. package/src/utils/lazyLoad.unit.test.tsx +319 -0
  1098. package/src/utils/location/location.test.ts +1 -1
  1099. package/src/utils/logger.unit.test.ts +398 -0
  1100. package/src/utils/organisationContext.unit.test.ts +180 -0
  1101. package/src/utils/performance/bundleAnalysis.test.ts +148 -0
  1102. package/src/utils/performance/performanceBenchmark.test.ts +251 -0
  1103. package/src/utils/performance/performanceBudgets.test.ts +241 -0
  1104. package/src/utils/performanceBenchmark.test.ts +174 -0
  1105. package/src/utils/performanceBudgets.unit.test.ts +288 -0
  1106. package/src/utils/permissionTypes.unit.test.ts +250 -0
  1107. package/src/utils/permissionUtils.unit.test.ts +362 -0
  1108. package/src/utils/permissions/permissionTypes.test.ts +149 -0
  1109. package/src/utils/persistence/keyDerivation.test.ts +306 -0
  1110. package/src/utils/persistence/sensitiveFieldDetection.test.ts +271 -0
  1111. package/src/utils/request-deduplication.test.ts +349 -0
  1112. package/src/utils/sanitization.unit.test.ts +346 -0
  1113. package/src/utils/schemaUtils.unit.test.ts +441 -0
  1114. package/src/utils/secureDataAccess.unit.test.ts +334 -0
  1115. package/src/utils/secureErrors.unit.test.ts +390 -0
  1116. package/src/utils/secureStorage.unit.test.ts +289 -0
  1117. package/src/utils/security/auth-utils.ts +34 -23
  1118. package/src/utils/security/secureDataAccess.ts +241 -281
  1119. package/src/utils/security/secureErrors.test.ts +1 -1
  1120. package/src/utils/security/secureStorage.test.ts +1 -1
  1121. package/src/utils/security/security.test.ts +25 -17
  1122. package/src/utils/security/security.ts +15 -18
  1123. package/src/utils/security/securityMonitor.test.ts +1 -1
  1124. package/src/utils/security.unit.test.ts +155 -0
  1125. package/src/utils/securityMonitor.unit.test.ts +276 -0
  1126. package/src/utils/sessionTracking.unit.test.ts +218 -0
  1127. package/src/utils/storage/config.unit.test.ts +239 -0
  1128. package/src/utils/storage/helpers.test.ts +88 -102
  1129. package/src/utils/storage/helpers.ts +173 -251
  1130. package/src/utils/storage/index.unit.test.ts +68 -0
  1131. package/src/utils/storage/types.ts +7 -0
  1132. package/src/utils/supabase/createBaseClient.test.ts +31 -14
  1133. package/src/utils/timezone/timezone.test.ts +1 -1
  1134. package/src/utils/timezone.test.ts +345 -0
  1135. package/src/utils/validation/common.test.ts +115 -0
  1136. package/src/utils/validation/csrf.test.ts +198 -0
  1137. package/src/utils/validation/csrf.ts +42 -41
  1138. package/src/utils/validation/htmlSanitization.unit.test.ts +618 -0
  1139. package/src/utils/validation/passwordSchema.test.ts +164 -0
  1140. package/src/utils/validation/schema.test.ts +127 -0
  1141. package/src/utils/validation/sqlInjectionProtection.test.ts +165 -0
  1142. package/src/utils/validation/user.test.ts +173 -0
  1143. package/src/utils/validation/validation.test.ts +197 -0
  1144. package/src/utils/validation/validationUtils.test.ts +294 -0
  1145. package/src/utils/validation.unit.test.ts +307 -0
  1146. package/src/utils/validationUtils.unit.test.ts +558 -0
  1147. package/dist/DataTable-SAXFG4XI.js +0 -13
  1148. package/dist/InactivityServiceProvider-DHryoh6K.d.ts +0 -299
  1149. package/dist/UnifiedAuthProvider-BBD2PS3Q.js +0 -7
  1150. package/dist/UnifiedAuthProvider-CiBAl9-s.d.ts +0 -151
  1151. package/dist/api-F47QJ7FX.js +0 -4
  1152. package/dist/audit-Z6ZZBWLU.js +0 -3
  1153. package/dist/auth-BZOJqrdd.d.ts +0 -49
  1154. package/dist/chunk-3GWSPISD.js +0 -61
  1155. package/dist/chunk-66R6RLUZ.js +0 -529
  1156. package/dist/chunk-7YDC7LMU.js +0 -487
  1157. package/dist/chunk-BCTXBU6U.js +0 -704
  1158. package/dist/chunk-FBZ7U3ID.js +0 -2209
  1159. package/dist/chunk-FN52B75D.js +0 -246
  1160. package/dist/chunk-JJEYZ3DX.js +0 -165
  1161. package/dist/chunk-KPYQWGFQ.js +0 -183
  1162. package/dist/chunk-KSNLMI7N.js +0 -481
  1163. package/dist/chunk-KYURMOQM.js +0 -977
  1164. package/dist/chunk-LNHFAF4X.js +0 -2279
  1165. package/dist/chunk-MPY44PWB.js +0 -8510
  1166. package/dist/chunk-NIU6DPQV.js +0 -427
  1167. package/dist/chunk-TFIPNIPE.js +0 -5379
  1168. package/dist/chunk-UZNAFKGW.js +0 -125
  1169. package/dist/chunk-W46INAVW.js +0 -1216
  1170. package/dist/chunk-X5EAU5G7.js +0 -793
  1171. package/dist/chunk-Y4PF6HIM.js +0 -2862
  1172. package/dist/database.generated-DT8JTZiP.d.ts +0 -9406
  1173. package/dist/event-WTAQuGcq.d.ts +0 -239
  1174. package/dist/file-reference-BavO2eQj.d.ts +0 -148
  1175. package/dist/functions-DH45k8ec.d.ts +0 -208
  1176. package/dist/timezone-K-ptz3HO.d.ts +0 -696
  1177. package/dist/types-BE2sEHKd.d.ts +0 -55
  1178. package/dist/types-CvOPXWWZ.d.ts +0 -111
  1179. package/dist/types-D05dCGma.d.ts +0 -521
  1180. package/dist/usePublicPageContext-vxBlEHO9.d.ts +0 -4290
  1181. package/dist/usePublicRouteParams-G3Ks53mk.d.ts +0 -877
  1182. package/docs/api/modules.md +0 -9889
  1183. package/scripts/build-docs-incremental.js +0 -179
  1184. package/scripts/eslint-audit.cjs +0 -222
  1185. package/scripts/generate-docs.js +0 -157
  1186. package/scripts/install-cursor-rules.cjs +0 -255
  1187. package/scripts/install-eslint-config.cjs +0 -349
  1188. package/scripts/setup-build-cache.js +0 -73
  1189. package/scripts/validate-pre-publish.js +0 -145
  1190. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +0 -260
  1191. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +0 -224
  1192. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +0 -273
  1193. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +0 -99
  1194. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -446
  1195. package/src/__tests__/helpers/__tests__/timer-utils.test.ts +0 -371
  1196. package/src/__tests__/hooks/usePermissions.test.ts +0 -268
  1197. package/src/__tests__/index.test.ts +0 -532
  1198. package/src/__tests__/integration/UserProfile.test.tsx +0 -124
  1199. package/src/__tests__/public-recipe-view.test.ts +0 -228
  1200. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +0 -222
  1201. package/src/__tests__/rls-policies.test.ts +0 -472
  1202. package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +0 -360
  1203. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +0 -759
  1204. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +0 -524
  1205. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +0 -705
  1206. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +0 -658
  1207. package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +0 -192
  1208. package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +0 -485
  1209. package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -876
  1210. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +0 -220
  1211. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +0 -970
  1212. package/src/components/DataTable/__tests__/README.md +0 -145
  1213. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +0 -788
  1214. package/src/components/DataTable/__tests__/keyboard.test.tsx +0 -756
  1215. package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +0 -66
  1216. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +0 -728
  1217. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -319
  1218. package/src/components/DataTable/__tests__/styles.test.ts +0 -382
  1219. package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +0 -103
  1220. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +0 -388
  1221. package/src/components/DataTable/__tests__/test-utils.ts +0 -94
  1222. package/src/components/DataTable/components/AccessDeniedPage.tsx +0 -159
  1223. package/src/components/DataTable/components/ActionButtons.tsx +0 -195
  1224. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +0 -160
  1225. package/src/components/DataTable/components/ColumnFilter.tsx +0 -113
  1226. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +0 -114
  1227. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +0 -225
  1228. package/src/components/DataTable/components/DataTableLayout.tsx +0 -584
  1229. package/src/components/DataTable/components/DataTableModals.tsx +0 -333
  1230. package/src/components/DataTable/components/DataTableToolbar.tsx +0 -271
  1231. package/src/components/DataTable/components/EditFields.tsx +0 -286
  1232. package/src/components/DataTable/components/EditableRow.tsx +0 -462
  1233. package/src/components/DataTable/components/EmptyState.tsx +0 -82
  1234. package/src/components/DataTable/components/FilterRow.tsx +0 -148
  1235. package/src/components/DataTable/components/LoadingState.tsx +0 -17
  1236. package/src/components/DataTable/components/PaginationControls.tsx +0 -285
  1237. package/src/components/DataTable/components/RowComponent.tsx +0 -423
  1238. package/src/components/DataTable/components/SortIndicator.tsx +0 -50
  1239. package/src/components/DataTable/components/UnifiedTableBody.tsx +0 -395
  1240. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +0 -245
  1241. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +0 -919
  1242. package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +0 -544
  1243. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +0 -484
  1244. package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +0 -748
  1245. package/src/components/DataTable/components/__tests__/DataTableCore.test.tsx +0 -792
  1246. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +0 -438
  1247. package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +0 -467
  1248. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +0 -358
  1249. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +0 -629
  1250. package/src/components/DataTable/components/__tests__/EditFields.test.tsx +0 -526
  1251. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +0 -994
  1252. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +0 -420
  1253. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +0 -415
  1254. package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +0 -612
  1255. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +0 -957
  1256. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +0 -81
  1257. package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +0 -429
  1258. package/src/components/DataTable/components/__tests__/RowComponent.test.tsx +0 -629
  1259. package/src/components/DataTable/components/__tests__/SortIndicator.test.tsx +0 -135
  1260. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +0 -864
  1261. package/src/components/DataTable/components/__tests__/cellValueUtils.test.ts +0 -453
  1262. package/src/components/DataTable/components/cellValueUtils.ts +0 -40
  1263. package/src/components/DataTable/components/hooks/useImportModalFocus.test.ts +0 -184
  1264. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +0 -53
  1265. package/src/components/DataTable/components/hooks/usePermissionTracking.test.ts +0 -381
  1266. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -122
  1267. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +0 -328
  1268. package/src/components/DataTable/core/ActionManager.ts +0 -235
  1269. package/src/components/DataTable/core/ColumnManager.ts +0 -204
  1270. package/src/components/DataTable/core/DataManager.ts +0 -190
  1271. package/src/components/DataTable/core/LocalDataAdapter.ts +0 -274
  1272. package/src/components/DataTable/core/PluginRegistry.ts +0 -229
  1273. package/src/components/DataTable/core/StateManager.ts +0 -312
  1274. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -235
  1275. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +0 -403
  1276. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -141
  1277. package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -178
  1278. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +0 -133
  1279. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +0 -142
  1280. package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -158
  1281. package/src/components/DataTable/core/interfaces.ts +0 -338
  1282. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +0 -516
  1283. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +0 -256
  1284. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +0 -297
  1285. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +0 -270
  1286. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +0 -280
  1287. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +0 -691
  1288. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +0 -183
  1289. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +0 -294
  1290. package/src/components/DataTable/hooks/__tests__/useKeyboardNavigation.test.ts +0 -787
  1291. package/src/components/DataTable/hooks/__tests__/useServerSideDataEffect.test.ts +0 -258
  1292. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +0 -499
  1293. package/src/components/DataTable/hooks/__tests__/useTableHandlers.test.ts +0 -440
  1294. package/src/components/DataTable/types.ts +0 -764
  1295. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +0 -548
  1296. package/src/components/DataTable/utils/__tests__/aggregationUtils.test.ts +0 -288
  1297. package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +0 -94
  1298. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +0 -209
  1299. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +0 -954
  1300. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +0 -573
  1301. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +0 -235
  1302. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +0 -586
  1303. package/src/components/DataTable/utils/__tests__/paginationUtils.test.ts +0 -593
  1304. package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +0 -470
  1305. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +0 -235
  1306. package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +0 -208
  1307. package/src/components/NavigationMenu/__tests__/useNavigationFiltering.test.ts +0 -1934
  1308. package/src/components/Select/__tests__/context.test.tsx +0 -56
  1309. package/src/components/Select/hooks/__tests__/useSelectEvents.test.ts +0 -279
  1310. package/src/components/Select/hooks/__tests__/useSelectSearch.test.tsx +0 -295
  1311. package/src/components/Select/hooks/__tests__/useSelectState.test.ts +0 -254
  1312. package/src/components/Select/hooks/useSelectEvents.ts +0 -87
  1313. package/src/components/Select/hooks/useSelectSearch.ts +0 -91
  1314. package/src/components/Select/hooks/useSelectState.ts +0 -104
  1315. package/src/components/Select/utils/__tests__/text.test.tsx +0 -104
  1316. package/src/components/Select/utils/text.ts +0 -26
  1317. package/src/components/__tests__/index.test.ts +0 -346
  1318. package/src/constants/__tests__/performance.test.ts +0 -91
  1319. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -725
  1320. package/src/hooks/__tests__/hooks.integration.test.tsx +0 -608
  1321. package/src/hooks/__tests__/index.unit.test.ts +0 -220
  1322. package/src/hooks/__tests__/useAppConfig.unit.test.ts +0 -406
  1323. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +0 -328
  1324. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +0 -720
  1325. package/src/hooks/__tests__/useDataTableState.test.ts +0 -170
  1326. package/src/hooks/__tests__/useDebounce.unit.test.ts +0 -157
  1327. package/src/hooks/__tests__/useEvents.unit.test.ts +0 -227
  1328. package/src/hooks/__tests__/useFileDisplay.test.ts +0 -540
  1329. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +0 -1109
  1330. package/src/hooks/__tests__/useFileUrl.unit.test.ts +0 -696
  1331. package/src/hooks/__tests__/useFileUrlCache.test.ts +0 -319
  1332. package/src/hooks/__tests__/useFocusManagement.unit.test.ts +0 -604
  1333. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +0 -613
  1334. package/src/hooks/__tests__/useFormDialog.test.ts +0 -307
  1335. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +0 -446
  1336. package/src/hooks/__tests__/useIsMobile.unit.test.ts +0 -317
  1337. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +0 -907
  1338. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -293
  1339. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +0 -961
  1340. package/src/hooks/__tests__/useOrganisations.unit.test.ts +0 -369
  1341. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +0 -694
  1342. package/src/hooks/__tests__/usePermissionCache.test.ts +0 -506
  1343. package/src/hooks/__tests__/usePreventTabReload.test.ts +0 -307
  1344. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -794
  1345. package/src/hooks/__tests__/usePublicEvent.test.ts +0 -670
  1346. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +0 -638
  1347. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +0 -948
  1348. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +0 -442
  1349. package/src/hooks/__tests__/useQueryCache.test.ts +0 -391
  1350. package/src/hooks/__tests__/useRBAC.unit.test.ts +0 -236
  1351. package/src/hooks/__tests__/useSessionDraft.test.ts +0 -556
  1352. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +0 -390
  1353. package/src/hooks/__tests__/useStorage.unit.test.ts +0 -721
  1354. package/src/hooks/__tests__/useToast.test.ts +0 -413
  1355. package/src/hooks/__tests__/useToast.unit.test.tsx +0 -481
  1356. package/src/hooks/__tests__/useZodForm.unit.test.tsx +0 -191
  1357. package/src/hooks/public/usePublicFileDisplay.test.ts +0 -723
  1358. package/src/hooks/public/usePublicFileDisplay.ts +0 -534
  1359. package/src/hooks/useFileDisplay.ts +0 -748
  1360. package/src/icons/__tests__/index.test.ts +0 -133
  1361. package/src/providers/OrganisationProvider.test.tsx +0 -40
  1362. package/src/providers/OrganisationProvider.tsx +0 -92
  1363. package/src/providers/__tests__/AuthProvider.test.tsx +0 -218
  1364. package/src/providers/__tests__/EventProvider.test.tsx +0 -487
  1365. package/src/providers/__tests__/InactivityProvider.test-helper.tsx +0 -65
  1366. package/src/providers/__tests__/InactivityProvider.test.tsx +0 -428
  1367. package/src/providers/__tests__/OrganisationProvider.test.tsx +0 -616
  1368. package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +0 -591
  1369. package/src/providers/__tests__/ProviderLifecycle.test.tsx +0 -308
  1370. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +0 -503
  1371. package/src/providers/__tests__/index.test.ts +0 -138
  1372. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +0 -229
  1373. package/src/providers/services/__tests__/AuthServiceProvider.test.tsx +0 -638
  1374. package/src/providers/services/__tests__/EventServiceProvider.test.tsx +0 -839
  1375. package/src/providers/services/__tests__/InactivityServiceProvider.test.tsx +0 -662
  1376. package/src/providers/services/__tests__/OrganisationServiceProvider.test.tsx +0 -440
  1377. package/src/providers/services/__tests__/UnifiedAuthProvider.advanced.test.tsx +0 -435
  1378. package/src/providers/services/__tests__/UnifiedAuthProvider.appId.test.tsx +0 -408
  1379. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +0 -301
  1380. package/src/providers/services/__tests__/contexts.test.tsx +0 -281
  1381. package/src/providers/services/__tests__/useUnifiedAuth.test.tsx +0 -251
  1382. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +0 -429
  1383. package/src/rbac/__tests__/audit-batched.test.ts +0 -550
  1384. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +0 -300
  1385. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +0 -517
  1386. package/src/rbac/__tests__/cache-invalidation.test.ts +0 -393
  1387. package/src/rbac/__tests__/engine.comprehensive.test.ts +0 -808
  1388. package/src/rbac/__tests__/performance.test.ts +0 -451
  1389. package/src/rbac/__tests__/rbac-core.test.tsx +0 -276
  1390. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -387
  1391. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +0 -252
  1392. package/src/rbac/__tests__/rbac-functions.test.ts +0 -646
  1393. package/src/rbac/__tests__/rbac-role-isolation.test.ts +0 -456
  1394. package/src/rbac/__tests__/scenarios.user-role.test.tsx +0 -271
  1395. package/src/rbac/components/__tests__/AccessDenied.test.tsx +0 -324
  1396. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +0 -1146
  1397. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +0 -231
  1398. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +0 -243
  1399. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +0 -1430
  1400. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +0 -185
  1401. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -427
  1402. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +0 -1179
  1403. package/src/rbac/hooks/permissions/__tests__/useAccessLevel.test.ts +0 -622
  1404. package/src/rbac/hooks/permissions/__tests__/useCan.test.ts +0 -798
  1405. package/src/rbac/hooks/permissions/__tests__/useMultiplePermissions.test.ts +0 -843
  1406. package/src/rbac/hooks/permissions/__tests__/usePermissions.test.ts +0 -545
  1407. package/src/rbac/utils/__tests__/clientSecurity.test.ts +0 -192
  1408. package/src/rbac/utils/__tests__/contextValidator.test.ts +0 -126
  1409. package/src/rbac/utils/__tests__/deep-equal.test.ts +0 -76
  1410. package/src/rbac/utils/__tests__/eventContext.test.ts +0 -386
  1411. package/src/services/__tests__/AuthService.edge-cases.test.ts +0 -746
  1412. package/src/services/__tests__/AuthService.restoreSession.test.ts +0 -59
  1413. package/src/services/__tests__/AuthService.test.ts +0 -1328
  1414. package/src/services/__tests__/BaseService.edge-cases.test.ts +0 -506
  1415. package/src/services/__tests__/BaseService.test.ts +0 -363
  1416. package/src/services/__tests__/EventService.edge-cases.test.ts +0 -633
  1417. package/src/services/__tests__/EventService.eventColours.test.ts +0 -64
  1418. package/src/services/__tests__/EventService.test.ts +0 -1018
  1419. package/src/services/__tests__/InactivityService.edge-cases.test.ts +0 -492
  1420. package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -406
  1421. package/src/services/__tests__/InactivityService.test.ts +0 -654
  1422. package/src/services/__tests__/OrganisationService.edge-cases.test.ts +0 -633
  1423. package/src/services/__tests__/OrganisationService.pagination.test.ts +0 -409
  1424. package/src/services/__tests__/OrganisationService.test.ts +0 -1176
  1425. package/src/services/interfaces/__tests__/IAuthService.test.ts +0 -190
  1426. package/src/services/interfaces/__tests__/IEventService.test.ts +0 -176
  1427. package/src/services/interfaces/__tests__/IInactivityService.test.ts +0 -183
  1428. package/src/services/interfaces/__tests__/IOrganisationService.test.ts +0 -207
  1429. package/src/theming/__tests__/parseEventColours.test.ts +0 -321
  1430. package/src/theming/__tests__/runtime.test.ts +0 -504
  1431. package/src/types/__tests__/core.test.ts +0 -397
  1432. package/src/types/__tests__/database-generated.test.ts +0 -78
  1433. package/src/types/__tests__/file-reference.test.ts +0 -351
  1434. package/src/types/__tests__/guards.test.ts +0 -246
  1435. package/src/types/__tests__/index.test.ts +0 -265
  1436. package/src/types/__tests__/organisation.roles.test.ts +0 -55
  1437. package/src/types/__tests__/organisation.test.ts +0 -1133
  1438. package/src/types/__tests__/theme.test.ts +0 -830
  1439. package/src/types/__tests__/type-validation.test.ts +0 -526
  1440. package/src/types/__tests__/validation.test.ts +0 -729
  1441. package/src/utils/__tests__/appConfig.unit.test.ts +0 -55
  1442. package/src/utils/__tests__/audit.unit.test.ts +0 -69
  1443. package/src/utils/__tests__/auth-utils.unit.test.ts +0 -70
  1444. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +0 -326
  1445. package/src/utils/__tests__/cn.unit.test.ts +0 -34
  1446. package/src/utils/__tests__/debugLogger.test.ts +0 -417
  1447. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +0 -818
  1448. package/src/utils/__tests__/dynamicUtils.unit.test.ts +0 -331
  1449. package/src/utils/__tests__/formatDate.unit.test.ts +0 -109
  1450. package/src/utils/__tests__/formatting.unit.test.ts +0 -99
  1451. package/src/utils/__tests__/index.unit.test.ts +0 -251
  1452. package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -320
  1453. package/src/utils/__tests__/logger.unit.test.ts +0 -398
  1454. package/src/utils/__tests__/organisationContext.unit.test.ts +0 -191
  1455. package/src/utils/__tests__/performanceBenchmark.test.ts +0 -174
  1456. package/src/utils/__tests__/performanceBudgets.unit.test.ts +0 -288
  1457. package/src/utils/__tests__/permissionTypes.unit.test.ts +0 -250
  1458. package/src/utils/__tests__/permissionUtils.unit.test.ts +0 -362
  1459. package/src/utils/__tests__/request-deduplication.test.ts +0 -349
  1460. package/src/utils/__tests__/sanitization.unit.test.ts +0 -346
  1461. package/src/utils/__tests__/schemaUtils.unit.test.ts +0 -441
  1462. package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -334
  1463. package/src/utils/__tests__/secureErrors.unit.test.ts +0 -390
  1464. package/src/utils/__tests__/secureStorage.unit.test.ts +0 -289
  1465. package/src/utils/__tests__/security.unit.test.ts +0 -149
  1466. package/src/utils/__tests__/securityMonitor.unit.test.ts +0 -276
  1467. package/src/utils/__tests__/sessionTracking.unit.test.ts +0 -218
  1468. package/src/utils/__tests__/timezone.test.ts +0 -345
  1469. package/src/utils/__tests__/validation.unit.test.ts +0 -307
  1470. package/src/utils/__tests__/validationUtils.unit.test.ts +0 -555
  1471. package/src/utils/core/__tests__/cn.test.ts +0 -66
  1472. package/src/utils/core/__tests__/debugLogger.test.ts +0 -113
  1473. package/src/utils/core/__tests__/logger.test.ts +0 -217
  1474. package/src/utils/dynamic/__tests__/dynamicUtils.test.ts +0 -185
  1475. package/src/utils/dynamic/__tests__/lazyLoad.test.tsx +0 -156
  1476. package/src/utils/file-reference/__tests__/file-reference.test.ts +0 -1313
  1477. package/src/utils/performance/__tests__/bundleAnalysis.test.ts +0 -148
  1478. package/src/utils/performance/__tests__/performanceBenchmark.test.ts +0 -251
  1479. package/src/utils/performance/__tests__/performanceBudgets.test.ts +0 -241
  1480. package/src/utils/permissions/__tests__/permissionTypes.test.ts +0 -149
  1481. package/src/utils/persistence/__tests__/keyDerivation.test.ts +0 -306
  1482. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +0 -271
  1483. package/src/utils/storage/__tests__/config.unit.test.ts +0 -239
  1484. package/src/utils/storage/__tests__/index.unit.test.ts +0 -68
  1485. package/src/utils/validation/__tests__/common.test.ts +0 -115
  1486. package/src/utils/validation/__tests__/csrf.test.ts +0 -170
  1487. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +0 -618
  1488. package/src/utils/validation/__tests__/passwordSchema.test.ts +0 -164
  1489. package/src/utils/validation/__tests__/schema.test.ts +0 -127
  1490. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +0 -165
  1491. package/src/utils/validation/__tests__/user.test.ts +0 -173
  1492. package/src/utils/validation/__tests__/validation.test.ts +0 -197
  1493. package/src/utils/validation/__tests__/validationUtils.test.ts +0 -294
  1494. /package/src/components/DataTable/{components/__tests__ → ui}/COVERAGE_NOTE.md +0 -0
  1495. /package/src/components/DataTable/utils/{__tests__/COVERAGE_NOTE.md → COVERAGE_NOTE.md} +0 -0
  1496. /package/src/hooks/{__tests__/useApiFetch.unit.test.ts → useApiFetch.unit.test.ts} +0 -0
  1497. /package/src/providers/{__tests__/README.md → README.md} +0 -0
  1498. /package/src/rbac/{__tests__/index.test.ts → index.test.ts} +0 -0
  1499. /package/src/rbac/{__tests__/rbac-integration.test.ts → rbac-integration.test.ts} +0 -0
  1500. /package/src/types/{__tests__/README.md → README.md} +0 -0
@@ -0,0 +1,2390 @@
1
+ import { emitAuditEvent, createAuditManager, setGlobalAuditManager } from './chunk-QRYSEPHB.js';
2
+ import { getCurrentAppName } from './chunk-GHCUP64P.js';
3
+ import { createLogger } from './chunk-BTHN5MKC.js';
4
+ import { ok, err } from './chunk-44CNXN4P.js';
5
+
6
+ // src/rbac/types.ts
7
+ var RBACError = class extends Error {
8
+ constructor(message, code, context) {
9
+ super(message);
10
+ this.code = code;
11
+ this.context = context;
12
+ this.name = "RBACError";
13
+ }
14
+ };
15
+ var PermissionDeniedError = class extends RBACError {
16
+ constructor(permission, context) {
17
+ super(
18
+ `Permission denied: ${permission}`,
19
+ "PERMISSION_DENIED",
20
+ { permission, ...context }
21
+ );
22
+ this.name = "PermissionDeniedError";
23
+ }
24
+ };
25
+ var OrganisationContextRequiredError = class extends RBACError {
26
+ constructor() {
27
+ super(
28
+ "Organisation context is required for this operation",
29
+ "ORGANISATION_CONTEXT_REQUIRED"
30
+ );
31
+ this.name = "OrganisationContextRequiredError";
32
+ }
33
+ };
34
+ var EventContextRequiredError = class extends RBACError {
35
+ constructor() {
36
+ super(
37
+ "Event context is required for this operation",
38
+ "EVENT_CONTEXT_REQUIRED"
39
+ );
40
+ this.name = "EventContextRequiredError";
41
+ }
42
+ };
43
+ var RBACNotInitializedError = class extends RBACError {
44
+ constructor() {
45
+ super(
46
+ "RBAC system not initialized. Please call setupRBAC(supabase) before using any RBAC components or hooks. See: https://docs.pace-core.dev/rbac/setup",
47
+ "RBAC_NOT_INITIALIZED"
48
+ );
49
+ this.name = "RBACNotInitializedError";
50
+ }
51
+ };
52
+ var InvalidScopeError = class extends RBACError {
53
+ constructor(scope, reason) {
54
+ super(
55
+ `Invalid scope provided: ${JSON.stringify(scope)}. ${reason}`,
56
+ "INVALID_SCOPE",
57
+ { scope, reason }
58
+ );
59
+ this.name = "InvalidScopeError";
60
+ }
61
+ };
62
+ var MissingUserContextError = class extends RBACError {
63
+ constructor() {
64
+ super(
65
+ "User context is required but not available. Make sure to wrap your app with an auth provider.",
66
+ "MISSING_USER_CONTEXT"
67
+ );
68
+ this.name = "MissingUserContextError";
69
+ }
70
+ };
71
+
72
+ // src/rbac/cache.ts
73
+ var RBACCache = class {
74
+ constructor() {
75
+ this.cache = /* @__PURE__ */ new Map();
76
+ this.sessionCache = /* @__PURE__ */ new Map();
77
+ this.TTL = 120 * 1e3;
78
+ // 120 seconds (short-term) - increased from 60s
79
+ this.SESSION_TTL = 15 * 60 * 1e3;
80
+ // 15 minutes (session-level) - increased from 5min
81
+ this.invalidationCallbacks = /* @__PURE__ */ new Set();
82
+ }
83
+ /**
84
+ * Get a value from the cache
85
+ *
86
+ * Checks both short-term cache and session cache.
87
+ *
88
+ * @param key - Cache key
89
+ * @param useSessionCache - Whether to check session cache (default: true)
90
+ * @returns Cached value or null if not found/expired
91
+ */
92
+ get(key, useSessionCache = true) {
93
+ const now = Date.now();
94
+ const entry = this.cache.get(key);
95
+ if (entry && now <= entry.expires) {
96
+ return entry.data;
97
+ }
98
+ if (entry && now > entry.expires) {
99
+ this.cache.delete(key);
100
+ }
101
+ if (useSessionCache) {
102
+ const sessionEntry = this.sessionCache.get(key);
103
+ if (sessionEntry && now <= sessionEntry.expires) {
104
+ return sessionEntry.data;
105
+ }
106
+ if (sessionEntry && now > sessionEntry.expires) {
107
+ this.sessionCache.delete(key);
108
+ }
109
+ }
110
+ return null;
111
+ }
112
+ /**
113
+ * Set a value in the cache
114
+ *
115
+ * @param key - Cache key
116
+ * @param data - Data to cache
117
+ * @param ttl - Time to live in milliseconds (defaults to 60s)
118
+ * @param useSessionCache - Whether to also store in session cache (default: false for page-level checks)
119
+ */
120
+ set(key, data, ttl = this.TTL, useSessionCache = false) {
121
+ const now = Date.now();
122
+ const expires = ttl <= 0 ? now - 1 : now + ttl;
123
+ this.cache.set(key, {
124
+ data,
125
+ expires
126
+ });
127
+ if (useSessionCache) {
128
+ const sessionExpires = ttl <= 0 ? now - 1 : now + this.SESSION_TTL;
129
+ this.sessionCache.set(key, {
130
+ data,
131
+ expires: sessionExpires
132
+ });
133
+ }
134
+ }
135
+ /**
136
+ * Delete a specific key from the cache
137
+ *
138
+ * @param key - Cache key to delete
139
+ */
140
+ delete(key) {
141
+ this.cache.delete(key);
142
+ this.sessionCache.delete(key);
143
+ }
144
+ /**
145
+ * Invalidate cache entries matching a pattern
146
+ *
147
+ * @param pattern - Pattern to match against cache keys
148
+ */
149
+ invalidate(pattern) {
150
+ const trimmedPattern = pattern?.trim();
151
+ if (!trimmedPattern) {
152
+ return;
153
+ }
154
+ const matcher = this.createMatcher(trimmedPattern);
155
+ const keysToDelete = [];
156
+ for (const key of this.cache.keys()) {
157
+ if (matcher(key)) {
158
+ keysToDelete.push(key);
159
+ }
160
+ }
161
+ for (const key of this.sessionCache.keys()) {
162
+ if (matcher(key) && !keysToDelete.includes(key)) {
163
+ keysToDelete.push(key);
164
+ }
165
+ }
166
+ keysToDelete.forEach((key) => {
167
+ this.cache.delete(key);
168
+ this.sessionCache.delete(key);
169
+ });
170
+ this.invalidationCallbacks.forEach((callback) => callback(trimmedPattern));
171
+ }
172
+ createMatcher(pattern) {
173
+ if (pattern.includes("*")) {
174
+ const escapedSegments = pattern.split("*").map((segment) => segment.replace(/[|\\{}()[\]^$+?.-]/g, "\\$&"));
175
+ const regexPattern = escapedSegments.join(".*");
176
+ const regex = new RegExp(regexPattern);
177
+ return (key) => regex.test(key);
178
+ }
179
+ return (key) => key.includes(pattern);
180
+ }
181
+ /**
182
+ * Clear all cache entries
183
+ */
184
+ clear() {
185
+ this.cache.clear();
186
+ this.sessionCache.clear();
187
+ }
188
+ /**
189
+ * Get cache statistics
190
+ */
191
+ getStats() {
192
+ return {
193
+ size: this.cache.size,
194
+ sessionSize: this.sessionCache.size,
195
+ ttl: this.TTL,
196
+ sessionTtl: this.SESSION_TTL,
197
+ keys: Array.from(this.cache.keys())
198
+ };
199
+ }
200
+ /**
201
+ * Add an invalidation callback
202
+ *
203
+ * @param callback - Function to call when cache is invalidated
204
+ */
205
+ onInvalidate(callback) {
206
+ this.invalidationCallbacks.add(callback);
207
+ return () => {
208
+ this.invalidationCallbacks.delete(callback);
209
+ };
210
+ }
211
+ /**
212
+ * Generate cache key for permission check (simplified signature)
213
+ *
214
+ * @param userId - User ID
215
+ * @param permission - Permission string
216
+ * @param organisationId - Organisation ID (optional)
217
+ * @param eventId - Event ID (optional)
218
+ * @param appId - App ID (optional)
219
+ * @param pageId - Page ID (optional)
220
+ * @returns String cache key
221
+ */
222
+ static generateKey(userId, permission, organisationId, eventId, appId, pageId) {
223
+ const parts = [
224
+ "perm",
225
+ userId,
226
+ organisationId || "null",
227
+ eventId || "null",
228
+ appId || "null",
229
+ permission || "null",
230
+ pageId || "null"
231
+ ];
232
+ return parts.join(":");
233
+ }
234
+ /**
235
+ * Generate cache key for permission check (object signature)
236
+ *
237
+ * @param key - Permission cache key object
238
+ * @returns String cache key
239
+ */
240
+ static generatePermissionKey(key) {
241
+ const parts = [
242
+ "perm",
243
+ key.userId,
244
+ key.organisationId || "null",
245
+ key.eventId || "null",
246
+ key.appId || "null",
247
+ key.permission || "null",
248
+ key.pageId || "null"
249
+ ];
250
+ return parts.join(":");
251
+ }
252
+ /**
253
+ * Generate cache key for access level
254
+ *
255
+ * @param userId - User ID
256
+ * @param organisationId - Organisation ID
257
+ * @param eventId - Event ID (optional)
258
+ * @param appId - App ID (optional)
259
+ * @returns String cache key
260
+ */
261
+ static generateAccessLevelKey(userId, organisationId, eventId, appId) {
262
+ const parts = [
263
+ "access",
264
+ userId,
265
+ organisationId,
266
+ eventId || "null",
267
+ appId || "null"
268
+ ];
269
+ return parts.join(":");
270
+ }
271
+ /**
272
+ * Generate cache key for permission map
273
+ *
274
+ * @param userId - User ID
275
+ * @param organisationId - Organisation ID
276
+ * @param eventId - Event ID (optional)
277
+ * @param appId - App ID (optional)
278
+ * @returns String cache key
279
+ */
280
+ static generatePermissionMapKey(userId, organisationId, eventId, appId) {
281
+ const parts = [
282
+ "map",
283
+ userId,
284
+ organisationId,
285
+ eventId || "null",
286
+ appId || "null"
287
+ ];
288
+ return parts.join(":");
289
+ }
290
+ };
291
+ var rbacCache = new RBACCache();
292
+ var CACHE_PATTERNS = {
293
+ USER: (userId) => `:${userId}:`,
294
+ ORGANISATION: (organisationId) => `:${organisationId}:`,
295
+ EVENT: (eventId) => `:${eventId}:`,
296
+ APP: (appId) => `:${appId}`,
297
+ PERMISSION: (userId, organisationId) => `perm:${userId}:${organisationId}:`
298
+ };
299
+
300
+ // src/rbac/cache-invalidation.ts
301
+ var log = createLogger("RBACCache");
302
+ var INVALIDATION_PATTERNS = {
303
+ // User-level invalidation
304
+ USER_ROLES_CHANGED: (userId) => [
305
+ CACHE_PATTERNS.USER(userId),
306
+ `perm:${userId}:*`,
307
+ `access:${userId}:*`,
308
+ `map:${userId}:*`
309
+ ],
310
+ // Organisation-level invalidation
311
+ ORGANISATION_PERMISSIONS_CHANGED: (organisationId) => [
312
+ CACHE_PATTERNS.ORGANISATION(organisationId),
313
+ `perm:*:${organisationId}:*`,
314
+ `access:*:${organisationId}:*`,
315
+ `map:*:${organisationId}:*`
316
+ ],
317
+ // Event-level invalidation
318
+ EVENT_PERMISSIONS_CHANGED: (eventId) => [
319
+ CACHE_PATTERNS.EVENT(eventId),
320
+ `perm:*:*:${eventId}:*`,
321
+ `access:*:*:${eventId}:*`,
322
+ `map:*:*:${eventId}:*`
323
+ ],
324
+ // App-level invalidation
325
+ APP_PERMISSIONS_CHANGED: (appId) => [
326
+ CACHE_PATTERNS.APP(appId),
327
+ `perm:*:*:*:${appId}:*`,
328
+ `access:*:*:*:${appId}`,
329
+ `map:*:*:*:${appId}`
330
+ ],
331
+ // Page-level invalidation
332
+ PAGE_PERMISSIONS_CHANGED: (pageId) => [
333
+ `perm:*:*:*:*:${pageId}`,
334
+ `map:*:*:*:*`
335
+ ]
336
+ };
337
+ var RBACCacheInvalidationManager = class {
338
+ constructor(supabase) {
339
+ this.invalidationCallbacks = /* @__PURE__ */ new Set();
340
+ this.channels = [];
341
+ this.supabase = supabase;
342
+ this.setupRealtimeSubscriptions();
343
+ }
344
+ /**
345
+ * Add a callback for cache invalidation events
346
+ *
347
+ * @param callback - Function to call when cache is invalidated
348
+ * @returns Unsubscribe function
349
+ */
350
+ onInvalidation(callback) {
351
+ this.invalidationCallbacks.add(callback);
352
+ return () => this.invalidationCallbacks.delete(callback);
353
+ }
354
+ /**
355
+ * Invalidate cache for a specific user
356
+ *
357
+ * @param userId - User ID
358
+ * @param reason - Reason for invalidation
359
+ */
360
+ invalidateUser(userId, reason) {
361
+ const patterns = INVALIDATION_PATTERNS.USER_ROLES_CHANGED(userId);
362
+ this.invalidatePatterns(patterns, reason);
363
+ }
364
+ /**
365
+ * Invalidate cache for a specific organisation
366
+ *
367
+ * @param organisationId - Organisation ID
368
+ * @param reason - Reason for invalidation
369
+ */
370
+ invalidateOrganisation(organisationId, reason) {
371
+ const patterns = INVALIDATION_PATTERNS.ORGANISATION_PERMISSIONS_CHANGED(organisationId);
372
+ this.invalidatePatterns(patterns, reason);
373
+ }
374
+ /**
375
+ * Invalidate cache for a specific event
376
+ *
377
+ * @param eventId - Event ID
378
+ * @param reason - Reason for invalidation
379
+ */
380
+ invalidateEvent(eventId, reason) {
381
+ const patterns = INVALIDATION_PATTERNS.EVENT_PERMISSIONS_CHANGED(eventId);
382
+ this.invalidatePatterns(patterns, reason);
383
+ }
384
+ /**
385
+ * Invalidate cache for a specific app
386
+ *
387
+ * @param appId - App ID
388
+ * @param reason - Reason for invalidation
389
+ */
390
+ invalidateApp(appId, reason) {
391
+ const patterns = INVALIDATION_PATTERNS.APP_PERMISSIONS_CHANGED(appId);
392
+ this.invalidatePatterns(patterns, reason);
393
+ }
394
+ /**
395
+ * Invalidate cache for a specific page
396
+ *
397
+ * @param pageId - Page ID
398
+ * @param reason - Reason for invalidation
399
+ */
400
+ invalidatePage(pageId, reason) {
401
+ const patterns = INVALIDATION_PATTERNS.PAGE_PERMISSIONS_CHANGED(pageId);
402
+ this.invalidatePatterns(patterns, reason);
403
+ }
404
+ /**
405
+ * Invalidate cache patterns and notify callbacks
406
+ *
407
+ * @param patterns - Array of cache patterns to invalidate
408
+ * @param reason - Reason for invalidation
409
+ */
410
+ invalidatePatterns(patterns, reason) {
411
+ log.debug(`Invalidating patterns: ${patterns.join(", ")} (${reason})`);
412
+ patterns.forEach((pattern) => {
413
+ rbacCache.invalidate(pattern);
414
+ });
415
+ this.invalidationCallbacks.forEach((callback) => {
416
+ patterns.forEach((pattern) => callback(pattern));
417
+ });
418
+ emitAuditEvent({
419
+ type: "permission_check",
420
+ userId: "system",
421
+ organisationId: "00000000-0000-0000-0000-000000000000",
422
+ permission: "cache:invalidate",
423
+ decision: true,
424
+ source: "api",
425
+ duration_ms: 0,
426
+ metadata: {
427
+ reason,
428
+ patterns,
429
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
430
+ cache_invalidation: true
431
+ }
432
+ }).catch((error) => {
433
+ log.warn("Failed to log cache invalidation audit event:", error);
434
+ });
435
+ }
436
+ /**
437
+ * Cleanup subscriptions only (not all callbacks)
438
+ * Used internally to cleanup before setting up new subscriptions
439
+ */
440
+ cleanupSubscriptions() {
441
+ this.channels.forEach((channel) => {
442
+ try {
443
+ if (channel && typeof channel.unsubscribe === "function") {
444
+ channel.unsubscribe();
445
+ }
446
+ } catch (error) {
447
+ log.warn("Failed to unsubscribe from channel:", error);
448
+ }
449
+ });
450
+ this.channels = [];
451
+ }
452
+ /**
453
+ * Setup realtime subscriptions for automatic cache invalidation
454
+ * Always cleans up existing subscriptions before setting up new ones to prevent duplicates
455
+ */
456
+ setupRealtimeSubscriptions() {
457
+ this.cleanupSubscriptions();
458
+ if (!this.supabase.channel || typeof this.supabase.channel !== "function") {
459
+ log.debug("Realtime not available, skipping subscriptions");
460
+ return;
461
+ }
462
+ const orgRolesChannel = this.supabase.channel("rbac_organisation_roles_changes").on("postgres_changes", {
463
+ event: "*",
464
+ schema: "public",
465
+ table: "rbac_organisation_roles"
466
+ }, (payload) => {
467
+ const payloadData = payload;
468
+ const { organisation_id, user_id } = payloadData.new || payloadData.old || {};
469
+ if (organisation_id) {
470
+ this.invalidateOrganisation(organisation_id, `organisation_role_${payloadData.eventType || "unknown"}`);
471
+ }
472
+ if (user_id) {
473
+ this.invalidateUser(user_id, `organisation_role_${payloadData.eventType || "unknown"}`);
474
+ }
475
+ });
476
+ const orgRolesSubscription = orgRolesChannel.subscribe();
477
+ this.channels.push(orgRolesSubscription);
478
+ const eventAppRolesChannel = this.supabase.channel("rbac_event_app_roles_changes").on("postgres_changes", {
479
+ event: "*",
480
+ schema: "public",
481
+ table: "rbac_event_app_roles"
482
+ }, (payload) => {
483
+ const payloadData = payload;
484
+ const { organisation_id, user_id, event_id, app_id } = payloadData.new || payloadData.old || {};
485
+ if (organisation_id) {
486
+ this.invalidateOrganisation(organisation_id, `event_app_role_${payloadData.eventType || "unknown"}`);
487
+ }
488
+ if (user_id) {
489
+ this.invalidateUser(user_id, `event_app_role_${payloadData.eventType || "unknown"}`);
490
+ }
491
+ if (event_id) {
492
+ this.invalidateEvent(event_id, `event_app_role_${payloadData.eventType || "unknown"}`);
493
+ }
494
+ if (app_id) {
495
+ this.invalidateApp(app_id, `event_app_role_${payloadData.eventType || "unknown"}`);
496
+ }
497
+ });
498
+ const eventAppRolesSubscription = eventAppRolesChannel.subscribe();
499
+ this.channels.push(eventAppRolesSubscription);
500
+ const globalRolesChannel = this.supabase.channel("rbac_global_roles_changes").on("postgres_changes", {
501
+ event: "*",
502
+ schema: "public",
503
+ table: "rbac_global_roles"
504
+ }, (payload) => {
505
+ const payloadData = payload;
506
+ const { user_id } = payloadData.new || payloadData.old || {};
507
+ if (user_id) {
508
+ this.invalidateUser(user_id, `global_role_${payloadData.eventType || "unknown"}`);
509
+ }
510
+ });
511
+ const globalRolesSubscription = globalRolesChannel.subscribe();
512
+ this.channels.push(globalRolesSubscription);
513
+ const pagePermissionsChannel = this.supabase.channel("rbac_page_permissions_changes").on("postgres_changes", {
514
+ event: "*",
515
+ schema: "public",
516
+ table: "rbac_page_permissions"
517
+ }, (payload) => {
518
+ const { organisation_id, app_page_id } = payload.new || payload.old || {};
519
+ if (organisation_id) {
520
+ this.invalidateOrganisation(organisation_id, `page_permission_${payload.eventType}`);
521
+ }
522
+ if (app_page_id) {
523
+ this.invalidatePage(app_page_id, `page_permission_${payload.eventType}`);
524
+ }
525
+ });
526
+ const pagePermissionsSubscription = pagePermissionsChannel.subscribe();
527
+ this.channels.push(pagePermissionsSubscription);
528
+ }
529
+ /**
530
+ * Cleanup all realtime subscriptions
531
+ * Call this when the manager is no longer needed to prevent memory leaks
532
+ */
533
+ cleanup() {
534
+ this.channels.forEach((channel) => {
535
+ try {
536
+ if (channel && typeof channel.unsubscribe === "function") {
537
+ channel.unsubscribe();
538
+ }
539
+ } catch (error) {
540
+ log.warn("Failed to unsubscribe from channel:", error);
541
+ }
542
+ });
543
+ this.channels = [];
544
+ this.invalidationCallbacks.clear();
545
+ }
546
+ /**
547
+ * Manually trigger cache invalidation for all users in an organisation
548
+ *
549
+ * @param organisationId - Organisation ID
550
+ * @param reason - Reason for invalidation
551
+ */
552
+ async invalidateAllUsersInOrganisation(organisationId, reason) {
553
+ const { data: users } = await this.supabase.from("rbac_organisation_roles").select("user_id").eq("organisation_id", organisationId).eq("is_active", true);
554
+ if (users) {
555
+ users.forEach(({ user_id }) => {
556
+ this.invalidateUser(user_id, reason);
557
+ });
558
+ }
559
+ }
560
+ /**
561
+ * Clear all cache entries
562
+ */
563
+ clearAllCache() {
564
+ log.debug("Clearing all cache entries");
565
+ rbacCache.clear();
566
+ }
567
+ };
568
+ var globalCacheInvalidationManager = null;
569
+ function initializeCacheInvalidation(supabase) {
570
+ if (globalCacheInvalidationManager) {
571
+ globalCacheInvalidationManager.cleanup();
572
+ }
573
+ globalCacheInvalidationManager = new RBACCacheInvalidationManager(supabase);
574
+ return globalCacheInvalidationManager;
575
+ }
576
+
577
+ // src/rbac/errors.ts
578
+ var RATE_LIMIT_STATUS_CODES = /* @__PURE__ */ new Set([429]);
579
+ var AUTH_STATUS_CODES = /* @__PURE__ */ new Set([401]);
580
+ var AUTHZ_STATUS_CODES = /* @__PURE__ */ new Set([403]);
581
+ function normalize(value) {
582
+ if (!value) {
583
+ return "";
584
+ }
585
+ if (typeof value === "string") {
586
+ return value.toLowerCase();
587
+ }
588
+ if (value instanceof Error && typeof value.message === "string") {
589
+ return value.message.toLowerCase();
590
+ }
591
+ return String(value).toLowerCase();
592
+ }
593
+ function categorizeByErrorClass(error) {
594
+ if (error instanceof PermissionDeniedError) {
595
+ return "authorization_error" /* AUTHORIZATION */;
596
+ }
597
+ if (error instanceof OrganisationContextRequiredError || error instanceof InvalidScopeError) {
598
+ return "validation_error" /* VALIDATION */;
599
+ }
600
+ if (error instanceof MissingUserContextError) {
601
+ return "authentication_error" /* AUTHENTICATION */;
602
+ }
603
+ return null;
604
+ }
605
+ function categorizeByRBACErrorCode(error) {
606
+ if (!(error instanceof RBACError)) {
607
+ return null;
608
+ }
609
+ switch (error.code) {
610
+ case "PERMISSION_DENIED":
611
+ return "authorization_error" /* AUTHORIZATION */;
612
+ case "ORGANISATION_CONTEXT_REQUIRED":
613
+ case "INVALID_SCOPE":
614
+ return "validation_error" /* VALIDATION */;
615
+ case "MISSING_USER_CONTEXT":
616
+ return "authentication_error" /* AUTHENTICATION */;
617
+ default:
618
+ return null;
619
+ }
620
+ }
621
+ function categorizeByHttpStatus(error) {
622
+ if (!error || typeof error !== "object") {
623
+ return null;
624
+ }
625
+ const status = error.status;
626
+ if (typeof status !== "number") {
627
+ return null;
628
+ }
629
+ if (RATE_LIMIT_STATUS_CODES.has(status)) {
630
+ return "rate_limit_error" /* RATE_LIMIT */;
631
+ }
632
+ if (AUTH_STATUS_CODES.has(status)) {
633
+ return "authentication_error" /* AUTHENTICATION */;
634
+ }
635
+ if (AUTHZ_STATUS_CODES.has(status)) {
636
+ return "authorization_error" /* AUTHORIZATION */;
637
+ }
638
+ if (status >= 500) {
639
+ return "database_error" /* DATABASE */;
640
+ }
641
+ return null;
642
+ }
643
+ function categorizeByCodeString(error) {
644
+ if (!error || typeof error !== "object") {
645
+ return null;
646
+ }
647
+ const codeValue = normalize(error.code);
648
+ if (!codeValue) {
649
+ return null;
650
+ }
651
+ if (codeValue.includes("network")) {
652
+ return "network_error" /* NETWORK */;
653
+ }
654
+ if (codeValue.includes("postgres") || codeValue.includes("database") || codeValue.includes("db")) {
655
+ return "database_error" /* DATABASE */;
656
+ }
657
+ if (codeValue.includes("rate")) {
658
+ return "rate_limit_error" /* RATE_LIMIT */;
659
+ }
660
+ if (codeValue.includes("auth")) {
661
+ return "authentication_error" /* AUTHENTICATION */;
662
+ }
663
+ if (codeValue.includes("permission")) {
664
+ return "authorization_error" /* AUTHORIZATION */;
665
+ }
666
+ if (codeValue.includes("scope") || codeValue.includes("invalid")) {
667
+ return "validation_error" /* VALIDATION */;
668
+ }
669
+ return null;
670
+ }
671
+ function categorizeByMessage(error) {
672
+ const message = normalize(error);
673
+ if (message.includes("timeout") || message.includes("network") || message.includes("fetch")) {
674
+ return "network_error" /* NETWORK */;
675
+ }
676
+ if (message.includes("postgres") || message.includes("database") || message.includes("connection")) {
677
+ return "database_error" /* DATABASE */;
678
+ }
679
+ if (message.includes("rate limit") || message.includes("too many requests")) {
680
+ return "rate_limit_error" /* RATE_LIMIT */;
681
+ }
682
+ if (message.includes("permission") || message.includes("forbidden")) {
683
+ return "authorization_error" /* AUTHORIZATION */;
684
+ }
685
+ if (message.includes("auth") || message.includes("token") || message.includes("session")) {
686
+ return "authentication_error" /* AUTHENTICATION */;
687
+ }
688
+ if (message.includes("invalid") || message.includes("scope") || message.includes("validation")) {
689
+ return "validation_error" /* VALIDATION */;
690
+ }
691
+ return null;
692
+ }
693
+ function categorizeError(error) {
694
+ const byClass = categorizeByErrorClass(error);
695
+ if (byClass !== null) return byClass;
696
+ const byCode = categorizeByRBACErrorCode(error);
697
+ if (byCode !== null) return byCode;
698
+ const byStatus = categorizeByHttpStatus(error);
699
+ if (byStatus !== null) return byStatus;
700
+ const byCodeString = categorizeByCodeString(error);
701
+ if (byCodeString !== null) return byCodeString;
702
+ const byMessage = categorizeByMessage(error);
703
+ if (byMessage !== null) return byMessage;
704
+ return "unknown_error" /* UNKNOWN */;
705
+ }
706
+ function mapErrorCategoryToSecurityEventType(category) {
707
+ switch (category) {
708
+ case "authorization_error" /* AUTHORIZATION */:
709
+ return "permission_denied";
710
+ case "network_error" /* NETWORK */:
711
+ return "network_error";
712
+ case "database_error" /* DATABASE */:
713
+ return "database_error";
714
+ case "validation_error" /* VALIDATION */:
715
+ return "validation_error";
716
+ case "rate_limit_error" /* RATE_LIMIT */:
717
+ return "rate_limit_error";
718
+ case "authentication_error" /* AUTHENTICATION */:
719
+ return "authentication_error";
720
+ case "unknown_error" /* UNKNOWN */:
721
+ default:
722
+ return "unknown_error";
723
+ }
724
+ }
725
+
726
+ // src/rbac/security.ts
727
+ var log2 = createLogger("RBACSecurity");
728
+ var RBACSecurityValidator = class {
729
+ /**
730
+ * Validate permission string format
731
+ * @param permission - Permission string to validate
732
+ * @returns True if valid, false otherwise
733
+ */
734
+ static validatePermission(permission) {
735
+ if (typeof permission !== "string" || permission.length === 0) {
736
+ return false;
737
+ }
738
+ const permissionRegex = /^(read|create|update|delete):[a-z0-9._-]+$/;
739
+ return permissionRegex.test(permission);
740
+ }
741
+ /**
742
+ * Validate UUID format
743
+ * @param uuid - UUID string to validate
744
+ * @returns True if valid, false otherwise
745
+ */
746
+ static validateUUID(uuid) {
747
+ if (typeof uuid !== "string" || uuid.length === 0) {
748
+ return false;
749
+ }
750
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
751
+ return uuidRegex.test(uuid);
752
+ }
753
+ /**
754
+ * Validate scope object
755
+ * @param scope - Scope object to validate
756
+ * @returns True if valid, false otherwise
757
+ */
758
+ static validateScope(scope) {
759
+ if (!scope || typeof scope !== "object") {
760
+ return false;
761
+ }
762
+ if (scope.organisationId !== void 0) {
763
+ if (typeof scope.organisationId === "string" && scope.organisationId.trim() === "") {
764
+ return false;
765
+ }
766
+ if (scope.organisationId && !this.validateUUID(scope.organisationId)) {
767
+ return false;
768
+ }
769
+ }
770
+ if (scope.eventId && typeof scope.eventId !== "string") {
771
+ return false;
772
+ }
773
+ if (scope.appId && !this.validateUUID(scope.appId)) {
774
+ return false;
775
+ }
776
+ return !!(scope.organisationId || scope.eventId || scope.appId);
777
+ }
778
+ /**
779
+ * Sanitize input string to prevent injection attacks
780
+ * @param input - Input string to sanitize
781
+ * @returns Sanitized string
782
+ */
783
+ static sanitizeInput(input) {
784
+ if (typeof input !== "string") {
785
+ return "";
786
+ }
787
+ return input.replace(/<[^>]*>/g, "").replace(/[<>\"'&]/g, "").replace(/[;()]/g, "").replace(/javascript:/gi, "").replace(/data:/gi, "").trim();
788
+ }
789
+ /**
790
+ * Validate user ID format
791
+ * @param userId - User ID to validate
792
+ * @returns True if valid, false otherwise
793
+ */
794
+ static validateUserId(userId) {
795
+ return this.validateUUID(userId);
796
+ }
797
+ /**
798
+ * Check if permission is a wildcard permission
799
+ * @param permission - Permission string to check
800
+ * @returns True if wildcard, false otherwise
801
+ */
802
+ static isWildcardPermission(permission) {
803
+ return permission.includes("*") || permission.endsWith(":*");
804
+ }
805
+ /**
806
+ * Validate permission hierarchy
807
+ * @param permission - Permission to validate
808
+ * @param requiredOperation - Required operation
809
+ * @returns True if permission matches or is higher in hierarchy
810
+ */
811
+ static validatePermissionHierarchy(permission, requiredOperation) {
812
+ if (!this.validatePermission(permission)) {
813
+ return false;
814
+ }
815
+ const [operation] = permission.split(":");
816
+ const hierarchy = ["read", "create", "update", "delete"];
817
+ const permissionLevel = hierarchy.indexOf(operation);
818
+ const requiredLevel = hierarchy.indexOf(requiredOperation);
819
+ if (permissionLevel === -1 || requiredLevel === -1) {
820
+ return false;
821
+ }
822
+ return permissionLevel >= requiredLevel;
823
+ }
824
+ /**
825
+ * Rate limiting check (placeholder for future implementation)
826
+ * @param userId - User ID
827
+ * @param operation - Operation being performed
828
+ * @returns True if within rate limit, false otherwise
829
+ */
830
+ static async checkRateLimit(_userId, _operation) {
831
+ return true;
832
+ }
833
+ // Only warn once per 5 seconds per user
834
+ static logSecurityEvent(event) {
835
+ const securityEvent = {
836
+ ...event,
837
+ timestamp: event.timestamp || /* @__PURE__ */ new Date(),
838
+ severity: this.getEventSeverity(event.type)
839
+ };
840
+ if (event.type === "rate_limit_exceeded") {
841
+ const now = Date.now();
842
+ const userWarning = this.rateLimitWarningCount.get(event.userId);
843
+ if (userWarning) {
844
+ const timeSinceLastWarning = now - userWarning.lastWarning;
845
+ if (timeSinceLastWarning < this.RATE_LIMIT_WARNING_THROTTLE_MS) {
846
+ userWarning.count++;
847
+ this.rateLimitWarningCount.set(event.userId, userWarning);
848
+ return;
849
+ } else {
850
+ log2.warn("Security event (throttled):", {
851
+ ...securityEvent,
852
+ details: {
853
+ ...securityEvent.details,
854
+ suppressedWarnings: userWarning.count,
855
+ message: `Rate limit exceeded (${userWarning.count + 1} times in last ${Math.round(timeSinceLastWarning / 1e3)}s)`
856
+ }
857
+ });
858
+ this.rateLimitWarningCount.set(event.userId, { count: 0, lastWarning: now });
859
+ return;
860
+ }
861
+ } else {
862
+ this.rateLimitWarningCount.set(event.userId, { count: 0, lastWarning: now });
863
+ log2.warn("Security event:", securityEvent);
864
+ return;
865
+ }
866
+ }
867
+ log2.warn("Security event:", securityEvent);
868
+ }
869
+ /**
870
+ * Get severity level for security event
871
+ * @param eventType - Type of security event
872
+ * @returns Severity level
873
+ */
874
+ static getEventSeverity(eventType) {
875
+ switch (eventType) {
876
+ case "permission_denied":
877
+ return "low";
878
+ case "invalid_input":
879
+ case "rate_limit_exceeded":
880
+ case "rate_limit_error":
881
+ case "network_error":
882
+ return "medium";
883
+ case "validation_error":
884
+ return "high";
885
+ case "authentication_error":
886
+ case "database_error":
887
+ return "critical";
888
+ case "suspicious_activity":
889
+ case "unknown_error":
890
+ return "high";
891
+ default:
892
+ return "low";
893
+ }
894
+ }
895
+ };
896
+ /**
897
+ * Log security event for monitoring
898
+ * @param event - Security event details
899
+ */
900
+ RBACSecurityValidator.rateLimitWarningCount = /* @__PURE__ */ new Map();
901
+ RBACSecurityValidator.RATE_LIMIT_WARNING_THROTTLE_MS = 5e3;
902
+ var DEFAULT_SECURITY_CONFIG = {
903
+ enableInputValidation: true,
904
+ enableRateLimiting: true,
905
+ enableAuditLogging: true,
906
+ maxPermissionChecksPerMinute: 1e3,
907
+ // Increased from 100 to 1000 for normal app usage
908
+ suspiciousActivityThreshold: 10
909
+ };
910
+ var RBACSecurityMiddleware = class {
911
+ constructor(config = DEFAULT_SECURITY_CONFIG) {
912
+ /**
913
+ * In-memory rate limiting cache (sliding window)
914
+ * Note: For production, this should use Redis or Supabase Edge Functions
915
+ */
916
+ this.rateLimitCache = /* @__PURE__ */ new Map();
917
+ this.config = config;
918
+ this._startCleanupInterval();
919
+ }
920
+ /**
921
+ * Start periodic cleanup of expired entries
922
+ */
923
+ _startCleanupInterval() {
924
+ setInterval(() => {
925
+ this.clearExpiredEntries();
926
+ }, 5 * 60 * 1e3);
927
+ }
928
+ /**
929
+ * Validate input before processing
930
+ * @param input - Input to validate
931
+ * @param context - Security context
932
+ * @returns Validation result
933
+ */
934
+ async validateInput(input, context) {
935
+ const errors = [];
936
+ if (!RBACSecurityValidator.validateUserId(context.userId)) {
937
+ errors.push("Invalid user ID format");
938
+ }
939
+ const permission = typeof input.permission === "string" ? input.permission : "";
940
+ const isPagePermission = permission.includes(":page.") || !!input.pageId;
941
+ const requiresOrgId = !isPagePermission;
942
+ if (requiresOrgId) {
943
+ if (!context.organisationId) {
944
+ errors.push("Organisation ID is required for resource-level permissions");
945
+ } else if (!RBACSecurityValidator.validateUUID(context.organisationId)) {
946
+ errors.push("Invalid organisation ID format");
947
+ }
948
+ } else {
949
+ if (context.organisationId && !RBACSecurityValidator.validateUUID(context.organisationId)) {
950
+ errors.push("Invalid organisation ID format");
951
+ }
952
+ }
953
+ if (permission && !RBACSecurityValidator.validatePermission(permission)) {
954
+ errors.push("Invalid permission format");
955
+ }
956
+ if (input.scope && !RBACSecurityValidator.validateScope(input.scope)) {
957
+ errors.push("Invalid scope format");
958
+ }
959
+ if (this.config.enableInputValidation) {
960
+ if (context.ipAddress && typeof context.ipAddress !== "string") {
961
+ errors.push("Invalid IP address format");
962
+ }
963
+ if (context.userAgent && typeof context.userAgent !== "string") {
964
+ errors.push("Invalid user agent format");
965
+ }
966
+ }
967
+ if (errors.length > 0) {
968
+ RBACSecurityValidator.logSecurityEvent({
969
+ type: "invalid_input",
970
+ userId: context.userId,
971
+ details: { errors, input: this.sanitizeInput(JSON.stringify(input)) }
972
+ });
973
+ }
974
+ return {
975
+ isValid: errors.length === 0,
976
+ errors
977
+ };
978
+ }
979
+ /**
980
+ * Check rate limiting
981
+ * @param context - Security context
982
+ * @returns Rate limit check result
983
+ */
984
+ async checkRateLimit(context) {
985
+ if (!this.config.enableRateLimiting) {
986
+ return { isAllowed: true, remaining: this.config.maxPermissionChecksPerMinute };
987
+ }
988
+ const isAllowed = await this._checkRateLimitInternal(context.userId);
989
+ const remaining = isAllowed ? this.config.maxPermissionChecksPerMinute - this._getRequestCount(context.userId) : 0;
990
+ return {
991
+ isAllowed,
992
+ remaining: Math.max(0, remaining)
993
+ };
994
+ }
995
+ async _checkRateLimitInternal(userId) {
996
+ const now = Date.now();
997
+ const windowMs = 60 * 1e3;
998
+ const entries = this.rateLimitCache.get(userId) || [];
999
+ const validEntries = entries.filter((entry) => now - entry.timestamp < windowMs);
1000
+ const requestCount = validEntries.length;
1001
+ const isAllowed = requestCount < this.config.maxPermissionChecksPerMinute;
1002
+ if (isAllowed) {
1003
+ validEntries.push({ timestamp: now });
1004
+ }
1005
+ this.rateLimitCache.set(userId, validEntries);
1006
+ return isAllowed;
1007
+ }
1008
+ _getRequestCount(userId) {
1009
+ const now = Date.now();
1010
+ const windowMs = 60 * 1e3;
1011
+ const entries = this.rateLimitCache.get(userId) || [];
1012
+ const validEntries = entries.filter((entry) => now - entry.timestamp < windowMs);
1013
+ return validEntries.length;
1014
+ }
1015
+ /**
1016
+ * Clear old rate limit entries to prevent memory leaks
1017
+ * Should be called periodically (e.g., every 5 minutes)
1018
+ */
1019
+ clearExpiredEntries() {
1020
+ const now = Date.now();
1021
+ const windowMs = 60 * 1e3;
1022
+ for (const [userId, entries] of this.rateLimitCache.entries()) {
1023
+ const validEntries = entries.filter((entry) => now - entry.timestamp < windowMs);
1024
+ if (validEntries.length === 0) {
1025
+ this.rateLimitCache.delete(userId);
1026
+ } else {
1027
+ this.rateLimitCache.set(userId, validEntries);
1028
+ }
1029
+ }
1030
+ }
1031
+ /**
1032
+ * Sanitize input data
1033
+ * @param input - Input to sanitize
1034
+ * @returns Sanitized input
1035
+ */
1036
+ sanitizeInput(input) {
1037
+ return RBACSecurityValidator.sanitizeInput(input);
1038
+ }
1039
+ };
1040
+
1041
+ // src/rbac/config.ts
1042
+ var logger = createLogger("RBAC");
1043
+ var RBACConfigManager = class {
1044
+ constructor() {
1045
+ this.config = null;
1046
+ this.logger = null;
1047
+ }
1048
+ setConfig(config) {
1049
+ this.config = config;
1050
+ this.setupLogger();
1051
+ }
1052
+ getConfig() {
1053
+ return this.config;
1054
+ }
1055
+ getLogger() {
1056
+ if (!this.logger) {
1057
+ this.logger = this.createDefaultLogger();
1058
+ }
1059
+ return this.logger;
1060
+ }
1061
+ setupLogger() {
1062
+ if (!this.config) return;
1063
+ const { debug = false, logLevel = "warn" } = this.config;
1064
+ this.logger = {
1065
+ error: (message, ...args) => {
1066
+ logger.error(message, ...args);
1067
+ },
1068
+ warn: (message, ...args) => {
1069
+ if (logLevel === "warn" || logLevel === "info" || logLevel === "debug") {
1070
+ logger.warn(message, ...args);
1071
+ }
1072
+ },
1073
+ info: (message, ...args) => {
1074
+ if (logLevel === "info" || logLevel === "debug") {
1075
+ logger.info(message, ...args);
1076
+ }
1077
+ },
1078
+ debug: (message, ...args) => {
1079
+ if (debug && logLevel === "debug") {
1080
+ logger.debug(message, ...args);
1081
+ }
1082
+ }
1083
+ };
1084
+ }
1085
+ createDefaultLogger() {
1086
+ return {
1087
+ error: (message, ...args) => logger.error(message, ...args),
1088
+ warn: (message, ...args) => logger.warn(message, ...args),
1089
+ info: (message, ...args) => logger.info(message, ...args),
1090
+ debug: (message, ...args) => logger.debug(message, ...args)
1091
+ };
1092
+ }
1093
+ isDebugMode() {
1094
+ return this.config?.debug ?? false;
1095
+ }
1096
+ isDevelopmentMode() {
1097
+ return this.config?.developmentMode ?? false;
1098
+ }
1099
+ getMockPermissions() {
1100
+ return this.config?.mockPermissions ?? null;
1101
+ }
1102
+ };
1103
+ var configManager = new RBACConfigManager();
1104
+ function createRBACConfig(config) {
1105
+ configManager.setConfig(config);
1106
+ return config;
1107
+ }
1108
+ function getRBACConfig() {
1109
+ return configManager.getConfig();
1110
+ }
1111
+ function getRBACLogger() {
1112
+ return configManager.getLogger();
1113
+ }
1114
+ function isDebugMode() {
1115
+ return configManager.isDebugMode();
1116
+ }
1117
+ function isDevelopmentMode() {
1118
+ return configManager.isDevelopmentMode();
1119
+ }
1120
+
1121
+ // src/rbac/engine.ts
1122
+ var RBACEngine = class {
1123
+ constructor(supabase, securityConfig) {
1124
+ this.supabase = supabase;
1125
+ const mergedSecurityConfig = {
1126
+ ...DEFAULT_SECURITY_CONFIG,
1127
+ ...securityConfig
1128
+ };
1129
+ this.securityMiddleware = new RBACSecurityMiddleware(mergedSecurityConfig);
1130
+ initializeCacheInvalidation(supabase);
1131
+ }
1132
+ /**
1133
+ * Check if a user has a specific permission
1134
+ *
1135
+ * This method now delegates to the database RPC function for all the heavy lifting.
1136
+ *
1137
+ * @param input - Permission check input
1138
+ * @param securityContext - Security context for validation (required)
1139
+ * @returns Promise resolving to permission result
1140
+ */
1141
+ async isPermitted(input, securityContext) {
1142
+ const startTime = Date.now();
1143
+ const { userId, permission, scope, pageId } = input;
1144
+ let cacheHit = false;
1145
+ let cacheSource = "rpc";
1146
+ try {
1147
+ const validation = await this.securityMiddleware.validateInput(input, securityContext);
1148
+ if (!validation.isValid) {
1149
+ const scopeRejected = validation.errors.includes("Invalid scope format");
1150
+ getRBACLogger().warn("[RBAC] Validation failed \u2014 check that an event is selected if the Menu/units page requires it.", {
1151
+ errors: validation.errors,
1152
+ scope: input.scope,
1153
+ permission: input.permission
1154
+ });
1155
+ RBACSecurityValidator.logSecurityEvent({
1156
+ type: "invalid_input",
1157
+ userId,
1158
+ details: {
1159
+ errors: validation.errors,
1160
+ input: JSON.stringify(input),
1161
+ ...scopeRejected && { scopeRejected: input.scope }
1162
+ }
1163
+ });
1164
+ if (scopeRejected) {
1165
+ getRBACLogger().warn("[RBAC] Invalid scope (from middleware). Scope must have at least one of organisationId, eventId, appId; no empty strings.", {
1166
+ scope: input.scope,
1167
+ permission: input.permission,
1168
+ userId
1169
+ });
1170
+ }
1171
+ return false;
1172
+ }
1173
+ const rateLimit = await this.securityMiddleware.checkRateLimit(securityContext);
1174
+ if (!rateLimit.isAllowed) {
1175
+ RBACSecurityValidator.logSecurityEvent({
1176
+ type: "rate_limit_exceeded",
1177
+ userId,
1178
+ details: { remaining: rateLimit.remaining }
1179
+ });
1180
+ return false;
1181
+ }
1182
+ if (!RBACSecurityValidator.validateUserId(userId)) {
1183
+ RBACSecurityValidator.logSecurityEvent({
1184
+ type: "invalid_input",
1185
+ userId,
1186
+ details: { error: "Invalid user ID format" }
1187
+ });
1188
+ return false;
1189
+ }
1190
+ if (!RBACSecurityValidator.validatePermission(permission)) {
1191
+ RBACSecurityValidator.logSecurityEvent({
1192
+ type: "invalid_input",
1193
+ userId,
1194
+ details: { error: "Invalid permission format", permission }
1195
+ });
1196
+ return false;
1197
+ }
1198
+ if (!RBACSecurityValidator.validateScope(scope)) {
1199
+ RBACSecurityValidator.logSecurityEvent({
1200
+ type: "invalid_input",
1201
+ userId,
1202
+ details: { error: "Invalid scope format", scope }
1203
+ });
1204
+ getRBACLogger().warn("[RBAC] Invalid scope (engine check). Scope must have at least one of organisationId, eventId, appId; no empty strings.", {
1205
+ scope,
1206
+ permission,
1207
+ userId
1208
+ });
1209
+ return false;
1210
+ }
1211
+ const cacheKey = RBACCache.generateKey(
1212
+ userId,
1213
+ permission,
1214
+ scope.organisationId,
1215
+ scope.eventId,
1216
+ scope.appId,
1217
+ pageId
1218
+ );
1219
+ const cached = rbacCache.get(cacheKey);
1220
+ if (cached !== null) {
1221
+ cacheHit = true;
1222
+ cacheSource = "memory";
1223
+ return cached;
1224
+ }
1225
+ const { data, error } = await this.supabase.rpc("rbac_check_permission_simplified", {
1226
+ p_user_id: userId,
1227
+ p_permission: permission,
1228
+ p_organisation_id: scope.organisationId || void 0,
1229
+ p_event_id: scope.eventId || void 0,
1230
+ p_app_id: scope.appId || void 0,
1231
+ p_page_id: pageId || void 0
1232
+ });
1233
+ if (error) {
1234
+ const logger2 = getRBACLogger();
1235
+ logger2.error("RPC error:", error);
1236
+ const category = categorizeError(error);
1237
+ const eventType = mapErrorCategoryToSecurityEventType(category);
1238
+ const errorDetails = error;
1239
+ RBACSecurityValidator.logSecurityEvent({
1240
+ type: eventType,
1241
+ userId,
1242
+ details: {
1243
+ error: errorDetails?.message || "RPC call failed",
1244
+ code: errorDetails?.code,
1245
+ hint: errorDetails?.hint,
1246
+ details: errorDetails?.details,
1247
+ permission,
1248
+ scope: JSON.stringify(scope),
1249
+ category
1250
+ }
1251
+ });
1252
+ return false;
1253
+ }
1254
+ const hasPermission = data === true;
1255
+ rbacCache.set(cacheKey, hasPermission, 6e4);
1256
+ const duration = Date.now() - startTime;
1257
+ if (scope.organisationId) {
1258
+ const resolvedPageId = await this.resolvePageId(pageId, scope.appId);
1259
+ await emitAuditEvent({
1260
+ type: hasPermission ? "permission_check" : "permission_denied",
1261
+ userId,
1262
+ organisationId: scope.organisationId,
1263
+ eventId: scope.eventId,
1264
+ appId: scope.appId,
1265
+ pageId: resolvedPageId,
1266
+ permission,
1267
+ decision: hasPermission,
1268
+ source: "api",
1269
+ duration_ms: duration,
1270
+ cache_hit: cacheHit,
1271
+ cache_source: cacheSource
1272
+ });
1273
+ }
1274
+ return hasPermission;
1275
+ } catch (error) {
1276
+ const category = categorizeError(error);
1277
+ const eventType = mapErrorCategoryToSecurityEventType(category);
1278
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
1279
+ RBACSecurityValidator.logSecurityEvent({
1280
+ type: eventType,
1281
+ userId,
1282
+ details: {
1283
+ error: errorMessage,
1284
+ permission,
1285
+ scope: JSON.stringify(scope),
1286
+ category
1287
+ }
1288
+ });
1289
+ const logger2 = getRBACLogger();
1290
+ logger2.error("Permission check failed:", error);
1291
+ return false;
1292
+ }
1293
+ }
1294
+ /**
1295
+ * Get user's access level in a scope
1296
+ *
1297
+ * This is derived from roles, not permissions.
1298
+ *
1299
+ * @param input - Access level input
1300
+ * @returns Promise resolving to access level
1301
+ */
1302
+ async getAccessLevel(input) {
1303
+ const { userId, scope } = input;
1304
+ const cacheKey = RBACCache.generateAccessLevelKey(
1305
+ userId,
1306
+ scope.organisationId || "",
1307
+ scope.eventId,
1308
+ scope.appId
1309
+ );
1310
+ const cached = rbacCache.get(cacheKey);
1311
+ if (cached) {
1312
+ return cached;
1313
+ }
1314
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1315
+ const isSuperAdmin2 = await this.checkSuperAdmin(userId);
1316
+ if (isSuperAdmin2) {
1317
+ rbacCache.set(cacheKey, "super", 6e4);
1318
+ return "super";
1319
+ }
1320
+ if (scope.organisationId) {
1321
+ const { data: orgRoles } = await this.supabase.from("rbac_organisation_roles").select("role").eq("user_id", userId).eq("organisation_id", scope.organisationId).eq("status", "active").is("revoked_at", null).lte("valid_from", now).or(`valid_to.is.null,valid_to.gte.${now}`).limit(1);
1322
+ const orgRole = orgRoles?.[0];
1323
+ if (orgRole?.role === "org_admin") {
1324
+ rbacCache.set(cacheKey, "admin", 6e4);
1325
+ return "admin";
1326
+ }
1327
+ }
1328
+ if (scope.eventId && scope.appId) {
1329
+ const { data: eventRole } = await this.supabase.from("rbac_event_app_roles").select("role").eq("user_id", userId).eq("event_id", scope.eventId).eq("app_id", scope.appId).eq("status", "active").lte("valid_from", now).or(`valid_to.is.null,valid_to.gte.${now}`).single();
1330
+ if (eventRole?.role === "event_admin") {
1331
+ rbacCache.set(cacheKey, "admin", 6e4);
1332
+ return "admin";
1333
+ }
1334
+ if (eventRole?.role === "planner") {
1335
+ rbacCache.set(cacheKey, "planner", 6e4);
1336
+ return "planner";
1337
+ }
1338
+ if (eventRole?.role === "participant") {
1339
+ rbacCache.set(cacheKey, "participant", 6e4);
1340
+ return "participant";
1341
+ }
1342
+ }
1343
+ rbacCache.set(cacheKey, "viewer", 6e4);
1344
+ return "viewer";
1345
+ }
1346
+ /**
1347
+ * Get user's permission map for a scope
1348
+ *
1349
+ * This builds a map of page IDs to allowed operations.
1350
+ * Uses the simplified RPC for each permission check.
1351
+ *
1352
+ * @param input - Permission map input
1353
+ * @returns Promise resolving to permission map
1354
+ */
1355
+ async getPermissionMap(input) {
1356
+ const { userId, scope } = input;
1357
+ const cacheKey = RBACCache.generatePermissionMapKey(
1358
+ userId,
1359
+ scope.organisationId || "",
1360
+ scope.eventId,
1361
+ scope.appId
1362
+ );
1363
+ const isSuperAdmin2 = await this.checkSuperAdmin(userId);
1364
+ if (isSuperAdmin2) {
1365
+ const wildcardMap = { "*": true };
1366
+ rbacCache.set(cacheKey, wildcardMap, 6e4);
1367
+ return wildcardMap;
1368
+ }
1369
+ if (!scope.organisationId) {
1370
+ return {};
1371
+ }
1372
+ const cached = rbacCache.get(cacheKey);
1373
+ if (cached) {
1374
+ return cached;
1375
+ }
1376
+ const permissionMap = {};
1377
+ if (scope.appId) {
1378
+ const { data: pages } = await this.supabase.from("rbac_app_pages").select("id, page_name").eq("app_id", scope.appId);
1379
+ if (pages) {
1380
+ if (!scope.organisationId) {
1381
+ rbacCache.set(cacheKey, permissionMap, 6e4);
1382
+ return permissionMap;
1383
+ }
1384
+ const securityContext = {
1385
+ userId,
1386
+ organisationId: scope.organisationId,
1387
+ // Required
1388
+ timestamp: /* @__PURE__ */ new Date()
1389
+ };
1390
+ for (const page of pages) {
1391
+ for (const operation of ["read", "create", "update", "delete"]) {
1392
+ const permissionString = `${operation}:page.${page.page_name}`;
1393
+ const hasPermission = await this.isPermitted(
1394
+ {
1395
+ userId,
1396
+ scope,
1397
+ permission: permissionString,
1398
+ pageId: page.id
1399
+ },
1400
+ securityContext
1401
+ );
1402
+ const permissionKey = permissionString;
1403
+ permissionMap[permissionKey] = hasPermission;
1404
+ }
1405
+ }
1406
+ }
1407
+ }
1408
+ rbacCache.set(cacheKey, permissionMap, 6e4);
1409
+ return permissionMap;
1410
+ }
1411
+ async resolveAppContext(input) {
1412
+ try {
1413
+ const { userId, appName } = input;
1414
+ const { data, error } = await this.supabase.rpc("data_app_resolve", {
1415
+ p_user_id: userId,
1416
+ p_app_name: appName
1417
+ });
1418
+ if (error) {
1419
+ const logger2 = getRBACLogger();
1420
+ logger2.error("Failed to resolve app context:", error);
1421
+ return null;
1422
+ }
1423
+ if (!data || !Array.isArray(data) || data.length === 0) {
1424
+ return null;
1425
+ }
1426
+ const appData = data[0];
1427
+ if (!appData?.app_id) {
1428
+ return null;
1429
+ }
1430
+ return {
1431
+ appId: appData.app_id,
1432
+ hasAccess: appData.has_access !== false
1433
+ };
1434
+ } catch (error) {
1435
+ const logger2 = getRBACLogger();
1436
+ logger2.error("Unexpected error resolving app context:", error);
1437
+ return null;
1438
+ }
1439
+ }
1440
+ async getRoleContext(input) {
1441
+ const result = {
1442
+ globalRole: null,
1443
+ organisationRole: null,
1444
+ eventAppRole: null
1445
+ };
1446
+ try {
1447
+ const { userId, scope } = input;
1448
+ const { data, error } = await this.supabase.rpc("rbac_permissions_get", {
1449
+ p_user_id: userId,
1450
+ p_organisation_id: scope.organisationId || null,
1451
+ p_event_id: scope.eventId || null,
1452
+ p_app_id: scope.appId || null,
1453
+ p_page_id: null
1454
+ // Optional: can filter to specific page if needed
1455
+ });
1456
+ if (error) {
1457
+ const logger2 = getRBACLogger();
1458
+ logger2.error("Failed to load role context:", error);
1459
+ return result;
1460
+ }
1461
+ if (!Array.isArray(data)) {
1462
+ return result;
1463
+ }
1464
+ const mapToOrganisationRole = (level) => {
1465
+ switch (level) {
1466
+ case "supporter":
1467
+ return "supporter";
1468
+ case "member":
1469
+ return "member";
1470
+ case "leader":
1471
+ return "leader";
1472
+ case "org_admin":
1473
+ case "admin":
1474
+ case "super":
1475
+ return "org_admin";
1476
+ default:
1477
+ return null;
1478
+ }
1479
+ };
1480
+ const mapToEventAppRole = (level) => {
1481
+ switch (level) {
1482
+ case "viewer":
1483
+ return "viewer";
1484
+ case "participant":
1485
+ return "participant";
1486
+ case "planner":
1487
+ return "planner";
1488
+ case "admin":
1489
+ case "super":
1490
+ return "event_admin";
1491
+ default:
1492
+ return null;
1493
+ }
1494
+ };
1495
+ for (const permission of data) {
1496
+ if (permission.permission_type === "all_permissions") {
1497
+ result.globalRole = "super_admin";
1498
+ }
1499
+ if (permission.permission_type === "organisation_access") {
1500
+ result.organisationRole = mapToOrganisationRole(permission.role_name);
1501
+ }
1502
+ if (permission.permission_type === "event_app_access") {
1503
+ result.eventAppRole = mapToEventAppRole(permission.role_name);
1504
+ }
1505
+ }
1506
+ return result;
1507
+ } catch (error) {
1508
+ const logger2 = getRBACLogger();
1509
+ logger2.error("Unexpected error loading role context:", error);
1510
+ return result;
1511
+ }
1512
+ }
1513
+ /**
1514
+ * Check if user is super admin
1515
+ *
1516
+ * @param userId - User ID
1517
+ * @returns Promise resolving to super admin status
1518
+ */
1519
+ async checkSuperAdmin(userId) {
1520
+ const cacheKey = `super_admin:${userId}`;
1521
+ const cached = rbacCache.get(cacheKey);
1522
+ if (cached !== null) {
1523
+ return cached;
1524
+ }
1525
+ const startTime = Date.now();
1526
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1527
+ try {
1528
+ const { data, error } = await this.supabase.from("rbac_global_roles").select("role").eq("user_id", userId).eq("role", "super_admin").lte("valid_from", now).or(`valid_to.is.null,valid_to.gte.${now}`).limit(1);
1529
+ const elapsed = Date.now() - startTime;
1530
+ if (elapsed > 2e3) {
1531
+ const logger2 = getRBACLogger();
1532
+ const errorMessage = error && typeof error === "object" && "message" in error ? String(error.message) : void 0;
1533
+ logger2.warn("[RBACEngine] Super admin check took longer than expected", {
1534
+ userId,
1535
+ elapsedMs: elapsed,
1536
+ error: errorMessage
1537
+ });
1538
+ }
1539
+ const isSuperAdmin2 = !error && data && data.length > 0;
1540
+ rbacCache.set(cacheKey, isSuperAdmin2, 6e4);
1541
+ return Boolean(isSuperAdmin2);
1542
+ } catch (err2) {
1543
+ const elapsed = Date.now() - startTime;
1544
+ const logger2 = getRBACLogger();
1545
+ logger2.error("[RBACEngine] Error checking super admin", {
1546
+ userId,
1547
+ error: err2,
1548
+ elapsedMs: elapsed
1549
+ });
1550
+ return false;
1551
+ }
1552
+ }
1553
+ /**
1554
+ * Resolve a page ID to UUID if it's a page name
1555
+ *
1556
+ * @param pageId - Page ID (UUID) or page name (string)
1557
+ * @param appId - App ID to look up the page
1558
+ * @returns Resolved page ID (UUID) or original pageId
1559
+ */
1560
+ async resolvePageId(pageId, appId) {
1561
+ if (!pageId) {
1562
+ return void 0;
1563
+ }
1564
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1565
+ if (uuidRegex.test(pageId)) {
1566
+ return pageId;
1567
+ }
1568
+ if (!appId) {
1569
+ return pageId;
1570
+ }
1571
+ try {
1572
+ const { data: page, error: pageError } = await this.supabase.from("rbac_app_pages").select("id").eq("app_id", appId).eq("page_name", pageId).maybeSingle();
1573
+ if (pageError) {
1574
+ const logger2 = getRBACLogger();
1575
+ if (pageError.code !== "PGRST116") {
1576
+ logger2.warn("Failed to resolve page name to UUID:", { pageId, appId, error: pageError });
1577
+ }
1578
+ return pageId;
1579
+ }
1580
+ return page?.id || pageId;
1581
+ } catch (error) {
1582
+ const logger2 = getRBACLogger();
1583
+ logger2.warn("Failed to resolve page name to UUID:", { pageId, appId, error });
1584
+ return pageId;
1585
+ }
1586
+ }
1587
+ };
1588
+ function createRBACEngine(supabase, securityConfig) {
1589
+ return new RBACEngine(supabase, securityConfig);
1590
+ }
1591
+
1592
+ // src/rbac/performance.ts
1593
+ var RBACPerformanceMonitor = class {
1594
+ constructor() {
1595
+ this.metrics = {
1596
+ totalChecks: 0,
1597
+ cacheHits: 0,
1598
+ cacheMisses: 0,
1599
+ cacheHitRate: 0,
1600
+ deduplicatedRequests: 0,
1601
+ networkRequests: 0,
1602
+ averageResponseTime: 0,
1603
+ totalResponseTime: 0,
1604
+ batchedAuditEvents: 0,
1605
+ individualAuditEvents: 0
1606
+ };
1607
+ this.enabled = false;
1608
+ }
1609
+ /**
1610
+ * Enable or disable performance monitoring
1611
+ */
1612
+ setEnabled(enabled) {
1613
+ this.enabled = enabled;
1614
+ }
1615
+ /**
1616
+ * Check if performance monitoring is enabled
1617
+ */
1618
+ isEnabled() {
1619
+ return this.enabled;
1620
+ }
1621
+ /**
1622
+ * Record a permission check
1623
+ */
1624
+ recordCheck(cacheHit, responseTime, wasDeduplicated = false) {
1625
+ if (!this.enabled) {
1626
+ return;
1627
+ }
1628
+ this.metrics.totalChecks++;
1629
+ if (cacheHit) {
1630
+ this.metrics.cacheHits++;
1631
+ } else {
1632
+ this.metrics.cacheMisses++;
1633
+ this.metrics.networkRequests++;
1634
+ }
1635
+ if (wasDeduplicated) {
1636
+ this.metrics.deduplicatedRequests++;
1637
+ }
1638
+ this.metrics.totalResponseTime += responseTime;
1639
+ this.metrics.averageResponseTime = this.metrics.totalResponseTime / this.metrics.totalChecks;
1640
+ this.metrics.cacheHitRate = this.metrics.cacheHits / this.metrics.totalChecks;
1641
+ }
1642
+ /**
1643
+ * Record an audit event
1644
+ */
1645
+ recordAuditEvent(batched) {
1646
+ if (!this.enabled) {
1647
+ return;
1648
+ }
1649
+ if (batched) {
1650
+ this.metrics.batchedAuditEvents++;
1651
+ } else {
1652
+ this.metrics.individualAuditEvents++;
1653
+ }
1654
+ }
1655
+ /**
1656
+ * Get current metrics
1657
+ */
1658
+ getMetrics() {
1659
+ return { ...this.metrics };
1660
+ }
1661
+ /**
1662
+ * Reset all metrics
1663
+ */
1664
+ reset() {
1665
+ this.metrics = {
1666
+ totalChecks: 0,
1667
+ cacheHits: 0,
1668
+ cacheMisses: 0,
1669
+ cacheHitRate: 0,
1670
+ deduplicatedRequests: 0,
1671
+ networkRequests: 0,
1672
+ averageResponseTime: 0,
1673
+ totalResponseTime: 0,
1674
+ batchedAuditEvents: 0,
1675
+ individualAuditEvents: 0
1676
+ };
1677
+ }
1678
+ /**
1679
+ * Get metrics summary as a formatted string
1680
+ */
1681
+ getSummary() {
1682
+ const m = this.metrics;
1683
+ return `
1684
+ RBAC Performance Metrics:
1685
+ Total Checks: ${m.totalChecks}
1686
+ Cache Hits: ${m.cacheHits} (${(m.cacheHitRate * 100).toFixed(1)}%)
1687
+ Cache Misses: ${m.cacheMisses}
1688
+ Deduplicated Requests: ${m.deduplicatedRequests}
1689
+ Network Requests: ${m.networkRequests}
1690
+ Average Response Time: ${m.averageResponseTime.toFixed(2)}ms
1691
+ Batched Audit Events: ${m.batchedAuditEvents}
1692
+ Individual Audit Events: ${m.individualAuditEvents}
1693
+ `;
1694
+ }
1695
+ };
1696
+ var performanceMonitor = new RBACPerformanceMonitor();
1697
+ function enablePerformanceMonitoring() {
1698
+ performanceMonitor.setEnabled(true);
1699
+ }
1700
+ function disablePerformanceMonitoring() {
1701
+ performanceMonitor.setEnabled(false);
1702
+ }
1703
+ function isPerformanceMonitoringEnabled() {
1704
+ return performanceMonitor.isEnabled();
1705
+ }
1706
+ function recordPermissionCheck(cacheHit, responseTime, wasDeduplicated = false) {
1707
+ performanceMonitor.recordCheck(cacheHit, responseTime, wasDeduplicated);
1708
+ }
1709
+ function recordAuditEvent(batched) {
1710
+ performanceMonitor.recordAuditEvent(batched);
1711
+ }
1712
+ function getPerformanceMetrics() {
1713
+ return performanceMonitor.getMetrics();
1714
+ }
1715
+ function resetPerformanceMetrics() {
1716
+ performanceMonitor.reset();
1717
+ }
1718
+ function getPerformanceSummary() {
1719
+ return performanceMonitor.getSummary();
1720
+ }
1721
+
1722
+ // src/rbac/request-deduplication.ts
1723
+ var inFlightRequests = /* @__PURE__ */ new Map();
1724
+ function generateDeduplicationKey(input) {
1725
+ return RBACCache.generatePermissionKey({
1726
+ userId: input.userId,
1727
+ organisationId: input.scope.organisationId,
1728
+ // Can be undefined for page-level permissions
1729
+ eventId: input.scope.eventId,
1730
+ appId: input.scope.appId,
1731
+ permission: input.permission,
1732
+ pageId: input.pageId
1733
+ });
1734
+ }
1735
+ async function getOrCreateRequest(input, checkFn) {
1736
+ const key = generateDeduplicationKey(input);
1737
+ const existingRequest = inFlightRequests.get(key);
1738
+ if (existingRequest) {
1739
+ return existingRequest;
1740
+ }
1741
+ const requestPromise = checkFn(input).finally(() => {
1742
+ inFlightRequests.delete(key);
1743
+ });
1744
+ inFlightRequests.set(key, requestPromise);
1745
+ return requestPromise;
1746
+ }
1747
+ function clearInFlightRequests() {
1748
+ inFlightRequests.clear();
1749
+ }
1750
+ function getInFlightRequestCount() {
1751
+ return inFlightRequests.size;
1752
+ }
1753
+
1754
+ // src/rbac/utils/eventContext.ts
1755
+ var orgDerivationCache = /* @__PURE__ */ new Map();
1756
+ var MAX_CACHE_SIZE = 100;
1757
+ async function getOrganisationFromEvent(supabase, eventId) {
1758
+ if (orgDerivationCache.has(eventId)) {
1759
+ return ok(orgDerivationCache.get(eventId) ?? null);
1760
+ }
1761
+ try {
1762
+ const { data, error } = await supabase.from("core_events").select("organisation_id").eq("event_id", eventId).single();
1763
+ let organisationId = null;
1764
+ if (error) {
1765
+ return err({ code: "ORG_FROM_EVENT_FAILED", message: error.message ?? "Failed to get organisation from event" });
1766
+ }
1767
+ if (data?.organisation_id) {
1768
+ organisationId = data.organisation_id;
1769
+ }
1770
+ if (orgDerivationCache.size >= MAX_CACHE_SIZE) {
1771
+ const firstKey = orgDerivationCache.keys().next().value;
1772
+ if (firstKey) {
1773
+ orgDerivationCache.delete(firstKey);
1774
+ }
1775
+ }
1776
+ orgDerivationCache.set(eventId, organisationId);
1777
+ return ok(organisationId);
1778
+ } catch (e) {
1779
+ return err({ code: "ORG_FROM_EVENT_FAILED", message: e instanceof Error ? e.message : String(e) });
1780
+ }
1781
+ }
1782
+
1783
+ // src/rbac/utils/contextValidator.ts
1784
+ var log3 = createLogger("ContextValidator");
1785
+ function allowsOptionalContexts(appName) {
1786
+ return appName === "PORTAL" || appName === "ADMIN";
1787
+ }
1788
+ var ContextValidator = class {
1789
+ /**
1790
+ * Derive organisation ID from event ID
1791
+ *
1792
+ * @param supabase - Supabase client
1793
+ * @param eventId - Event ID
1794
+ * @returns Organisation ID or null
1795
+ */
1796
+ static async deriveOrgFromEvent(supabase, eventId) {
1797
+ const result = await getOrganisationFromEvent(supabase, eventId);
1798
+ if (!result.ok) {
1799
+ return null;
1800
+ }
1801
+ return result.data;
1802
+ }
1803
+ /**
1804
+ * Resolve scope based on page-level scope_type
1805
+ *
1806
+ * This method handles page-level scoping. All pages have explicit scope_type set.
1807
+ * Used for hybrid apps that have both event and organisation pages.
1808
+ *
1809
+ * @param scope - Current scope
1810
+ * @param pageScopeType - Page scope type ('event', 'organisation', or 'both')
1811
+ * @param appName - App name (for PORTAL/ADMIN special case)
1812
+ * @param supabase - Supabase client (for deriving org from event, only if not already provided)
1813
+ * @param immediateOrganisationId - Optional immediate organisation ID (from selectedEvent.organisation_id) - avoids querying
1814
+ * @returns Resolved scope with all required context
1815
+ */
1816
+ static async resolveScopeForPage(scope, pageScopeType, appName, supabase, immediateOrganisationId) {
1817
+ const effectiveScopeType = pageScopeType;
1818
+ if (effectiveScopeType === "both") {
1819
+ if (!scope.organisationId && !scope.eventId) {
1820
+ if (allowsOptionalContexts(appName)) {
1821
+ return {
1822
+ isValid: true,
1823
+ resolvedScope: {
1824
+ organisationId: void 0,
1825
+ eventId: void 0,
1826
+ appId: scope.appId
1827
+ },
1828
+ error: null
1829
+ };
1830
+ }
1831
+ return {
1832
+ isValid: false,
1833
+ resolvedScope: null,
1834
+ error: new Error("Page requires either organisation or event context")
1835
+ };
1836
+ }
1837
+ let organisationId = scope.organisationId || immediateOrganisationId || void 0;
1838
+ if (!organisationId && scope.eventId && supabase) {
1839
+ try {
1840
+ const derivedOrgId = await this.deriveOrgFromEvent(supabase, scope.eventId);
1841
+ organisationId = derivedOrgId || void 0;
1842
+ } catch (error) {
1843
+ log3.warn("Failed to derive org from event for both-scope page:", error);
1844
+ }
1845
+ }
1846
+ return {
1847
+ isValid: true,
1848
+ resolvedScope: {
1849
+ organisationId,
1850
+ eventId: scope.eventId,
1851
+ appId: scope.appId
1852
+ },
1853
+ error: null
1854
+ };
1855
+ }
1856
+ if (effectiveScopeType === "event") {
1857
+ if (!scope.eventId) {
1858
+ if (allowsOptionalContexts(appName)) {
1859
+ return {
1860
+ isValid: true,
1861
+ resolvedScope: {
1862
+ organisationId: scope.organisationId,
1863
+ eventId: void 0,
1864
+ appId: scope.appId
1865
+ },
1866
+ error: null
1867
+ };
1868
+ }
1869
+ return {
1870
+ isValid: false,
1871
+ resolvedScope: null,
1872
+ error: new EventContextRequiredError()
1873
+ };
1874
+ }
1875
+ let organisationId = scope.organisationId || immediateOrganisationId || void 0;
1876
+ if (!organisationId && supabase && scope.eventId) {
1877
+ try {
1878
+ const derivedOrgId = await this.deriveOrgFromEvent(supabase, scope.eventId);
1879
+ organisationId = derivedOrgId || void 0;
1880
+ if (!organisationId) {
1881
+ return {
1882
+ isValid: false,
1883
+ resolvedScope: null,
1884
+ error: new Error("Could not resolve organisation from event context")
1885
+ };
1886
+ }
1887
+ } catch (error) {
1888
+ log3.error("Failed to derive org from event:", error);
1889
+ return {
1890
+ isValid: false,
1891
+ resolvedScope: null,
1892
+ error: error instanceof Error ? error : new Error("Failed to derive organisation from event")
1893
+ };
1894
+ }
1895
+ }
1896
+ return {
1897
+ isValid: true,
1898
+ resolvedScope: {
1899
+ organisationId,
1900
+ eventId: scope.eventId,
1901
+ appId: scope.appId
1902
+ },
1903
+ error: null
1904
+ };
1905
+ }
1906
+ if (effectiveScopeType === "organisation") {
1907
+ if (!scope.organisationId) {
1908
+ if (allowsOptionalContexts(appName)) {
1909
+ return {
1910
+ isValid: true,
1911
+ resolvedScope: {
1912
+ organisationId: void 0,
1913
+ eventId: scope.eventId,
1914
+ appId: scope.appId
1915
+ },
1916
+ error: null
1917
+ };
1918
+ }
1919
+ return {
1920
+ isValid: false,
1921
+ resolvedScope: null,
1922
+ error: new OrganisationContextRequiredError()
1923
+ };
1924
+ }
1925
+ return {
1926
+ isValid: true,
1927
+ resolvedScope: {
1928
+ organisationId: scope.organisationId,
1929
+ eventId: scope.eventId,
1930
+ // Event is optional for org-scoped pages
1931
+ appId: scope.appId
1932
+ },
1933
+ error: null
1934
+ };
1935
+ }
1936
+ return {
1937
+ isValid: false,
1938
+ resolvedScope: null,
1939
+ error: new Error("Invalid scope type")
1940
+ };
1941
+ }
1942
+ };
1943
+
1944
+ // src/rbac/api.ts
1945
+ var log4 = createLogger("RBACAPI");
1946
+ var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1947
+ function normalizeScope(scope) {
1948
+ const org = scope.organisationId;
1949
+ const ev = scope.eventId;
1950
+ const app = scope.appId;
1951
+ const hasOrg = typeof org === "string" && org.trim() !== "";
1952
+ const hasEv = typeof ev === "string" && ev.trim() !== "";
1953
+ const hasApp = typeof app === "string" && app.trim() !== "";
1954
+ return {
1955
+ ...hasOrg ? { organisationId: org } : {},
1956
+ ...hasEv ? { eventId: ev } : {},
1957
+ ...hasApp ? { appId: app } : {}
1958
+ };
1959
+ }
1960
+ function toApiError(error) {
1961
+ if (error instanceof RBACNotInitializedError) {
1962
+ return { code: "RBAC_NOT_INITIALIZED", message: error.message };
1963
+ }
1964
+ if (error instanceof OrganisationContextRequiredError) {
1965
+ return { code: "ORGANISATION_CONTEXT_REQUIRED", message: error.message };
1966
+ }
1967
+ const message = error instanceof Error ? error.message : String(error);
1968
+ return { code: "RBAC_ERROR", message };
1969
+ }
1970
+ var globalEngine = null;
1971
+ function setupRBAC(supabase, config) {
1972
+ const isDevelopment = import.meta.env.MODE === "development";
1973
+ const fullConfig = {
1974
+ supabase,
1975
+ debug: isDevelopment,
1976
+ logLevel: "warn",
1977
+ developmentMode: isDevelopment,
1978
+ ...config
1979
+ };
1980
+ createRBACConfig(fullConfig);
1981
+ const securityConfig = config === void 0 && !isDevelopment ? void 0 : {
1982
+ // Default: disable rate limiting in development
1983
+ ...isDevelopment && config?.security?.enableRateLimiting === void 0 ? { enableRateLimiting: false } : {},
1984
+ // Explicit config overrides defaults
1985
+ ...config?.security
1986
+ };
1987
+ globalEngine = createRBACEngine(supabase, securityConfig);
1988
+ const useBatchedAudit = config?.audit?.batched !== false && config?.performance?.enableBatchedAuditLogging !== false;
1989
+ const batchConfig = useBatchedAudit ? {
1990
+ batchWindow: config?.audit?.batchWindow,
1991
+ batchSize: config?.audit?.batchSize
1992
+ } : void 0;
1993
+ const auditManager = createAuditManager(supabase, useBatchedAudit, batchConfig);
1994
+ setGlobalAuditManager(auditManager);
1995
+ if (config?.performance?.enablePerformanceTracking) {
1996
+ enablePerformanceMonitoring();
1997
+ }
1998
+ }
1999
+ function isRBACInitialized() {
2000
+ return globalEngine !== null;
2001
+ }
2002
+ function getEngine() {
2003
+ if (!globalEngine) {
2004
+ throw new RBACNotInitializedError();
2005
+ }
2006
+ return globalEngine;
2007
+ }
2008
+ async function getAccessLevel(input, appName) {
2009
+ try {
2010
+ const engine = getEngine();
2011
+ const isSuperAdminUser = await engine["checkSuperAdmin"](input.userId);
2012
+ if (isSuperAdminUser) {
2013
+ return ok("super");
2014
+ }
2015
+ const validation = await ContextValidator.resolveScopeForPage(
2016
+ input.scope,
2017
+ "organisation",
2018
+ // Default to organisation scope when no page context
2019
+ appName,
2020
+ engine["supabase"]
2021
+ );
2022
+ if (!validation.isValid || !validation.resolvedScope) {
2023
+ throw validation.error || new OrganisationContextRequiredError();
2024
+ }
2025
+ const accessLevel = await engine.getAccessLevel({
2026
+ ...input,
2027
+ scope: validation.resolvedScope
2028
+ });
2029
+ return ok(accessLevel);
2030
+ } catch (error) {
2031
+ return err(toApiError(error));
2032
+ }
2033
+ }
2034
+ async function getPermissionMap(input, appName) {
2035
+ try {
2036
+ const engine = getEngine();
2037
+ const validation = await ContextValidator.resolveScopeForPage(
2038
+ input.scope,
2039
+ "organisation",
2040
+ // Default to organisation scope when no page context
2041
+ appName,
2042
+ engine["supabase"]
2043
+ );
2044
+ if (!validation.isValid || !validation.resolvedScope) {
2045
+ throw validation.error || new OrganisationContextRequiredError();
2046
+ }
2047
+ const permissionMap = await engine.getPermissionMap({
2048
+ ...input,
2049
+ scope: validation.resolvedScope
2050
+ });
2051
+ return ok(permissionMap);
2052
+ } catch (error) {
2053
+ return err(toApiError(error));
2054
+ }
2055
+ }
2056
+ async function resolveAppContext(input) {
2057
+ try {
2058
+ const engine = getEngine();
2059
+ const context = await engine.resolveAppContext(input);
2060
+ return ok(context);
2061
+ } catch (error) {
2062
+ return err(toApiError(error));
2063
+ }
2064
+ }
2065
+ async function getRoleContext(input, appName) {
2066
+ try {
2067
+ const engine = getEngine();
2068
+ const validation = await ContextValidator.resolveScopeForPage(
2069
+ input.scope,
2070
+ "organisation",
2071
+ // Default to organisation scope when no page context
2072
+ appName,
2073
+ engine["supabase"]
2074
+ );
2075
+ if (!validation.isValid || !validation.resolvedScope) {
2076
+ throw validation.error || new OrganisationContextRequiredError();
2077
+ }
2078
+ const roleContext = await engine.getRoleContext({
2079
+ ...input,
2080
+ scope: validation.resolvedScope
2081
+ });
2082
+ return ok(roleContext);
2083
+ } catch (error) {
2084
+ return err(toApiError(error));
2085
+ }
2086
+ }
2087
+ async function isPermitted(input, appName, precomputedSuperAdmin = null) {
2088
+ try {
2089
+ const engine = getEngine();
2090
+ if (!input.scope || typeof input.scope !== "object") {
2091
+ return ok(false);
2092
+ }
2093
+ const normalizedInputScope = normalizeScope(input.scope);
2094
+ if (!RBACSecurityValidator.validateScope(normalizedInputScope)) {
2095
+ return ok(false);
2096
+ }
2097
+ let inputWithNormalizedScope = { ...input, scope: normalizedInputScope };
2098
+ if (precomputedSuperAdmin === true) {
2099
+ return ok(true);
2100
+ }
2101
+ if (precomputedSuperAdmin === null) {
2102
+ const isSuperAdminUser = await engine["checkSuperAdmin"](input.userId);
2103
+ if (isSuperAdminUser) {
2104
+ return ok(true);
2105
+ }
2106
+ }
2107
+ let scopeForCheck = inputWithNormalizedScope.scope;
2108
+ const isPageName = input.pageId && typeof input.pageId === "string" && !UUID_REGEX.test(input.pageId);
2109
+ const hasEventId = typeof scopeForCheck.eventId === "string" && scopeForCheck.eventId.trim() !== "";
2110
+ const noAppId = !scopeForCheck.appId || typeof scopeForCheck.appId === "string" && scopeForCheck.appId.trim() === "";
2111
+ if (isPageName && hasEventId && noAppId) {
2112
+ const currentAppName = getCurrentAppName();
2113
+ if (currentAppName) {
2114
+ try {
2115
+ const { data: app } = await engine["supabase"].from("rbac_apps").select("id").eq("name", currentAppName).eq("is_active", true).maybeSingle();
2116
+ if (app) {
2117
+ scopeForCheck = { ...scopeForCheck, appId: app.id };
2118
+ inputWithNormalizedScope = { ...inputWithNormalizedScope, scope: scopeForCheck };
2119
+ }
2120
+ } catch (_err) {
2121
+ }
2122
+ }
2123
+ }
2124
+ let resolvedAppName = appName;
2125
+ if (!resolvedAppName && inputWithNormalizedScope.scope.appId) {
2126
+ try {
2127
+ const { data } = await engine["supabase"].from("rbac_apps").select("name").eq("id", inputWithNormalizedScope.scope.appId).eq("is_active", true).single();
2128
+ if (data) {
2129
+ resolvedAppName = data.name;
2130
+ }
2131
+ } catch (_err) {
2132
+ }
2133
+ }
2134
+ let pageScopeType;
2135
+ if (input.pageId) {
2136
+ const scopeResult = await getPageScopeType(
2137
+ input.pageId,
2138
+ inputWithNormalizedScope.scope.appId,
2139
+ resolvedAppName
2140
+ );
2141
+ if (!scopeResult.ok) {
2142
+ log4.error("Failed to get page scope type:", scopeResult.error);
2143
+ return err(scopeResult.error);
2144
+ }
2145
+ if (!scopeResult.data) {
2146
+ return err({ code: "PAGE_SCOPE_TYPE_MISSING", message: `Page ${input.pageId} does not have scope_type set` });
2147
+ }
2148
+ pageScopeType = scopeResult.data;
2149
+ } else {
2150
+ pageScopeType = "organisation";
2151
+ }
2152
+ const validation = await ContextValidator.resolveScopeForPage(
2153
+ inputWithNormalizedScope.scope,
2154
+ pageScopeType,
2155
+ resolvedAppName,
2156
+ engine["supabase"]
2157
+ );
2158
+ if (!validation.isValid || !validation.resolvedScope) {
2159
+ throw validation.error || new OrganisationContextRequiredError();
2160
+ }
2161
+ const validatedScope = normalizeScope(validation.resolvedScope);
2162
+ if (!RBACSecurityValidator.validateScope(validatedScope)) {
2163
+ log4.warn("Scope has no valid identifier after normalisation \u2014 skipping engine call", {
2164
+ permission: input.permission,
2165
+ pageId: input.pageId
2166
+ });
2167
+ return ok(false);
2168
+ }
2169
+ if (pageScopeType === "both" && input.pageId) {
2170
+ const eventScope = {
2171
+ organisationId: validatedScope.organisationId,
2172
+ // Org derived from event
2173
+ eventId: validatedScope.eventId,
2174
+ appId: validatedScope.appId
2175
+ };
2176
+ const eventSecurityContext = {
2177
+ userId: input.userId,
2178
+ organisationId: eventScope.organisationId || null,
2179
+ timestamp: /* @__PURE__ */ new Date()
2180
+ };
2181
+ const eventInput = {
2182
+ ...input,
2183
+ scope: eventScope
2184
+ };
2185
+ const hasEventPermission = await engine.isPermitted(eventInput, eventSecurityContext);
2186
+ if (validatedScope.organisationId && validatedScope.eventId) {
2187
+ const orgScope = {
2188
+ organisationId: validatedScope.organisationId,
2189
+ eventId: void 0,
2190
+ // Clear event for org-only check
2191
+ appId: validatedScope.appId
2192
+ };
2193
+ const orgSecurityContext = {
2194
+ userId: input.userId,
2195
+ organisationId: orgScope.organisationId || null,
2196
+ timestamp: /* @__PURE__ */ new Date()
2197
+ };
2198
+ const orgInput = {
2199
+ ...input,
2200
+ scope: orgScope
2201
+ };
2202
+ const hasOrgPermission = await engine.isPermitted(orgInput, orgSecurityContext);
2203
+ return ok(hasEventPermission || hasOrgPermission);
2204
+ }
2205
+ return ok(hasEventPermission);
2206
+ }
2207
+ const securityContext = {
2208
+ userId: input.userId,
2209
+ organisationId: validatedScope.organisationId || null,
2210
+ timestamp: /* @__PURE__ */ new Date()
2211
+ };
2212
+ const validatedInput = {
2213
+ ...input,
2214
+ scope: validatedScope
2215
+ };
2216
+ const permitted = await engine.isPermitted(validatedInput, securityContext);
2217
+ return ok(permitted);
2218
+ } catch (error) {
2219
+ return err(toApiError(error));
2220
+ }
2221
+ }
2222
+ async function isPermittedCached(input, appName) {
2223
+ const { userId, scope, permission, pageId } = input;
2224
+ const cacheKey = RBACCache.generatePermissionKey({
2225
+ userId,
2226
+ organisationId: scope.organisationId,
2227
+ eventId: scope.eventId,
2228
+ appId: scope.appId,
2229
+ permission,
2230
+ pageId
2231
+ });
2232
+ const cached = rbacCache.get(cacheKey, true);
2233
+ if (cached !== null) {
2234
+ return ok(cached);
2235
+ }
2236
+ return getOrCreateRequest(input, async (checkInput) => {
2237
+ const result = await isPermitted(checkInput, appName, null);
2238
+ if (!result.ok) {
2239
+ return result;
2240
+ }
2241
+ const isPageLevelCheck = !!pageId || permission.includes("page.");
2242
+ rbacCache.set(cacheKey, result.data, void 0, isPageLevelCheck);
2243
+ return ok(result.data);
2244
+ });
2245
+ }
2246
+ async function hasAnyPermission(input) {
2247
+ const { permissions, ...baseInput } = input;
2248
+ for (const permission of permissions) {
2249
+ const result = await isPermitted({
2250
+ ...baseInput,
2251
+ permission
2252
+ });
2253
+ if (!result.ok) {
2254
+ return result;
2255
+ }
2256
+ if (result.data) {
2257
+ return ok(true);
2258
+ }
2259
+ }
2260
+ return ok(false);
2261
+ }
2262
+ async function hasAllPermissions(input) {
2263
+ const { permissions, ...baseInput } = input;
2264
+ for (const permission of permissions) {
2265
+ const result = await isPermitted({
2266
+ ...baseInput,
2267
+ permission
2268
+ });
2269
+ if (!result.ok) {
2270
+ return result;
2271
+ }
2272
+ if (!result.data) {
2273
+ return ok(false);
2274
+ }
2275
+ }
2276
+ return ok(true);
2277
+ }
2278
+ async function isSuperAdmin(userId) {
2279
+ try {
2280
+ const engine = getEngine();
2281
+ const value = await engine["checkSuperAdmin"](userId);
2282
+ return ok(value);
2283
+ } catch (error) {
2284
+ return err(toApiError(error));
2285
+ }
2286
+ }
2287
+ async function getPageScopeType(pageId, appId, appName) {
2288
+ try {
2289
+ const engine = getEngine();
2290
+ let resolvedAppId = appId;
2291
+ if (!resolvedAppId && appName) {
2292
+ const { data: app, error: appError } = await engine["supabase"].from("rbac_apps").select("id, name, is_active").eq("name", appName).eq("is_active", true).maybeSingle();
2293
+ if (appError) {
2294
+ log4.error("Error resolving appId from appName", {
2295
+ appName,
2296
+ pageId,
2297
+ error: appError,
2298
+ errorMessage: appError instanceof Error ? appError.message : String(appError)
2299
+ });
2300
+ return err({ code: "APP_RESOLVE_FAILED", message: `Failed to resolve appId from appName "${appName}": ${appError instanceof Error ? appError.message : String(appError)}` });
2301
+ }
2302
+ if (!app) {
2303
+ log4.error("App not found or inactive", { appName, pageId });
2304
+ return err({ code: "APP_NOT_FOUND", message: `Could not resolve appId for appName "${appName}" - app not found or not active` });
2305
+ }
2306
+ resolvedAppId = app.id;
2307
+ }
2308
+ if (!resolvedAppId) {
2309
+ log4.error("No appId resolved", { pageId, appId, appName });
2310
+ return err({ code: "APP_ID_REQUIRED", message: `Could not resolve appId for page ${pageId} - appId and appName both missing or invalid` });
2311
+ }
2312
+ let resolvedPageId = pageId;
2313
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2314
+ if (!uuidRegex.test(pageId)) {
2315
+ const { data: page, error: pageError } = await engine["supabase"].from("rbac_app_pages").select("id, page_name, app_id").eq("app_id", resolvedAppId).eq("page_name", pageId).maybeSingle();
2316
+ if (pageError) {
2317
+ log4.error("Error resolving pageId from page_name", { pageId, appId: resolvedAppId, appName, error: pageError });
2318
+ return err({ code: "PAGE_RESOLVE_FAILED", message: `Failed to resolve pageId "${pageId}" for appId ${resolvedAppId}: ${pageError instanceof Error ? pageError.message : String(pageError)}` });
2319
+ }
2320
+ if (!page) {
2321
+ log4.error("Page not found in database", { pageId, appId: resolvedAppId, appName });
2322
+ return err({ code: "PAGE_NOT_FOUND", message: `Could not resolve pageId "${pageId}" to a valid UUID - page not found for appId ${resolvedAppId}` });
2323
+ }
2324
+ resolvedPageId = page.id;
2325
+ }
2326
+ if (!uuidRegex.test(resolvedPageId)) {
2327
+ log4.error("PageId resolution failed - not a valid UUID", { originalPageId: pageId, resolvedPageId, appId: resolvedAppId, appName });
2328
+ return err({ code: "PAGE_ID_INVALID", message: `Could not resolve pageId ${pageId} to a valid UUID` });
2329
+ }
2330
+ const { data: pageData, error } = await engine["supabase"].from("rbac_app_pages").select("scope_type, page_name, app_id").eq("id", resolvedPageId).single();
2331
+ if (error) {
2332
+ log4.error("Error fetching page scope type from database", { pageId: resolvedPageId, originalPageId: pageId, appId: resolvedAppId, appName, error });
2333
+ return err({ code: "PAGE_SCOPE_FETCH_FAILED", message: `Failed to get page scope type: ${error instanceof Error ? error.message : String(error)}` });
2334
+ }
2335
+ if (!pageData || !pageData.scope_type) {
2336
+ log4.error("Page found but scope_type is missing", { pageId: resolvedPageId, originalPageId: pageId, appId: resolvedAppId, appName, pageData });
2337
+ return err({ code: "PAGE_SCOPE_TYPE_MISSING", message: `Page ${resolvedPageId} does not have scope_type set` });
2338
+ }
2339
+ return ok(pageData.scope_type);
2340
+ } catch (error) {
2341
+ log4.error("Error fetching page scope type (catch block)", { pageId, appId, appName, error });
2342
+ return err(toApiError(error));
2343
+ }
2344
+ }
2345
+ async function isOrganisationAdmin(userId, organisationId) {
2346
+ const result = await getAccessLevel({
2347
+ userId,
2348
+ scope: { organisationId }
2349
+ });
2350
+ if (!result.ok) {
2351
+ return result;
2352
+ }
2353
+ return ok(result.data === "admin" || result.data === "super");
2354
+ }
2355
+ async function isEventAdmin(userId, scope) {
2356
+ if (!scope.eventId || !scope.appId) {
2357
+ return ok(false);
2358
+ }
2359
+ const result = await getAccessLevel({ userId, scope });
2360
+ if (!result.ok) {
2361
+ return result;
2362
+ }
2363
+ return ok(result.data === "admin" || result.data === "super");
2364
+ }
2365
+ function invalidateUserCache(userId, organisationId) {
2366
+ const patterns = organisationId ? [
2367
+ CACHE_PATTERNS.PERMISSION(userId, organisationId),
2368
+ `access:${userId}:${organisationId}:`,
2369
+ `map:${userId}:${organisationId}:`
2370
+ ] : [
2371
+ `perm:${userId}:`,
2372
+ `access:${userId}:`,
2373
+ `map:${userId}:`
2374
+ ];
2375
+ patterns.forEach((pattern) => rbacCache.invalidate(pattern));
2376
+ }
2377
+ function invalidateOrganisationCache(organisationId) {
2378
+ rbacCache.invalidate(CACHE_PATTERNS.ORGANISATION(organisationId));
2379
+ }
2380
+ function invalidateEventCache(eventId) {
2381
+ rbacCache.invalidate(CACHE_PATTERNS.EVENT(eventId));
2382
+ }
2383
+ function invalidateAppCache(appId) {
2384
+ rbacCache.invalidate(CACHE_PATTERNS.APP(appId));
2385
+ }
2386
+ function clearCache() {
2387
+ rbacCache.clear();
2388
+ }
2389
+
2390
+ export { CACHE_PATTERNS, ContextValidator, EventContextRequiredError, OrganisationContextRequiredError, RBACCache, RBACEngine, clearCache, clearInFlightRequests, createRBACConfig, createRBACEngine, disablePerformanceMonitoring, enablePerformanceMonitoring, getAccessLevel, getInFlightRequestCount, getPageScopeType, getPerformanceMetrics, getPerformanceSummary, getPermissionMap, getRBACConfig, getRBACLogger, getRoleContext, hasAllPermissions, hasAnyPermission, invalidateAppCache, invalidateEventCache, invalidateOrganisationCache, invalidateUserCache, isDebugMode, isDevelopmentMode, isEventAdmin, isOrganisationAdmin, isPerformanceMonitoringEnabled, isPermitted, isPermittedCached, isRBACInitialized, isSuperAdmin, rbacCache, recordAuditEvent, recordPermissionCheck, resetPerformanceMetrics, resolveAppContext, setupRBAC };