@jmruthers/pace-core 0.5.185 → 0.5.187

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 (300) hide show
  1. package/dist/{DataTable-Z9NLVJh0.d.ts → DataTable-IVYljGJ6.d.ts} +1 -1
  2. package/dist/{DataTable-IX2NBUTP.js → DataTable-K3RJRSOX.js} +7 -7
  3. package/dist/{PublicPageProvider-BABf6JCh.d.ts → PublicPageProvider-DrLDztHt.d.ts} +214 -107
  4. package/dist/{UnifiedAuthProvider-A4BCQRJY.js → UnifiedAuthProvider-B76OWOAT.js} +2 -2
  5. package/dist/{api-BMFCXVQX.js → api-YP7XD5L6.js} +3 -3
  6. package/dist/{audit-WRS3KJKI.js → audit-B5P6FFIR.js} +2 -2
  7. package/dist/{chunk-445GEP27.js → chunk-3IC5WCMO.js} +33 -8
  8. package/dist/chunk-3IC5WCMO.js.map +1 -0
  9. package/dist/{chunk-OKI34GZD.js → chunk-3NFNJOO7.js} +8 -8
  10. package/dist/chunk-3NFNJOO7.js.map +1 -0
  11. package/dist/{chunk-FSFQFJCU.js → chunk-63FOKYGO.js} +174 -6
  12. package/dist/chunk-63FOKYGO.js.map +1 -0
  13. package/dist/{chunk-MX3EIJGQ.js → chunk-C4OYJOV4.js} +631 -97
  14. package/dist/chunk-C4OYJOV4.js.map +1 -0
  15. package/dist/{chunk-HGPQUCBC.js → chunk-FMTK4XNN.js} +3 -3
  16. package/dist/{chunk-U6WNSFX5.js → chunk-HEHYGYOX.js} +279 -44
  17. package/dist/chunk-HEHYGYOX.js.map +1 -0
  18. package/dist/{chunk-XAUHJD3L.js → chunk-K2JGDXGU.js} +2 -2
  19. package/dist/{chunk-HC67NW5K.js → chunk-LBBUPSSC.js} +863 -552
  20. package/dist/chunk-LBBUPSSC.js.map +1 -0
  21. package/dist/{chunk-IXSNYUCT.js → chunk-SAUPYVLF.js} +1 -1
  22. package/dist/chunk-SAUPYVLF.js.map +1 -0
  23. package/dist/{chunk-AISXLWGZ.js → chunk-T6ZJVI3A.js} +27 -23
  24. package/dist/chunk-T6ZJVI3A.js.map +1 -0
  25. package/dist/{chunk-STTZQK2I.js → chunk-ULX5FYEM.js} +9 -7
  26. package/dist/chunk-ULX5FYEM.js.map +1 -0
  27. package/dist/{chunk-FXFJRTKI.js → chunk-WK2Y6TGA.js} +3 -3
  28. package/dist/chunk-WK2Y6TGA.js.map +1 -0
  29. package/dist/chunk-YHCN776L.js +447 -0
  30. package/dist/chunk-YHCN776L.js.map +1 -0
  31. package/dist/components.d.ts +4 -4
  32. package/dist/components.js +12 -10
  33. package/dist/components.js.map +1 -1
  34. package/dist/{database.generated-CBmg2950.d.ts → database.generated-DI89OQeI.d.ts} +63 -9
  35. package/dist/{file-reference-BjR39ktt.d.ts → file-reference-D037xOFK.d.ts} +3 -1
  36. package/dist/hooks.d.ts +265 -6
  37. package/dist/hooks.js +148 -49
  38. package/dist/hooks.js.map +1 -1
  39. package/dist/index.d.ts +25 -10
  40. package/dist/index.js +65 -30
  41. package/dist/index.js.map +1 -1
  42. package/dist/providers.js +1 -1
  43. package/dist/rbac/index.d.ts +125 -8
  44. package/dist/rbac/index.js +27 -7
  45. package/dist/{types-DUyCRSTj.d.ts → types-Bwgl--Xo.d.ts} +162 -1
  46. package/dist/types.d.ts +2 -2
  47. package/dist/types.js +1 -1
  48. package/dist/{usePublicRouteParams-CvnC3d-e.d.ts → usePublicRouteParams-CTDELQ7H.d.ts} +3 -3
  49. package/dist/utils.d.ts +214 -4
  50. package/dist/utils.js +22 -2
  51. package/dist/utils.js.map +1 -1
  52. package/docs/api/classes/ColumnFactory.md +1 -1
  53. package/docs/api/classes/ErrorBoundary.md +1 -1
  54. package/docs/api/classes/InvalidScopeError.md +1 -1
  55. package/docs/api/classes/Logger.md +1 -1
  56. package/docs/api/classes/MissingUserContextError.md +1 -1
  57. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  58. package/docs/api/classes/PermissionDeniedError.md +1 -1
  59. package/docs/api/classes/RBACAuditManager.md +21 -17
  60. package/docs/api/classes/RBACCache.md +31 -23
  61. package/docs/api/classes/RBACEngine.md +6 -6
  62. package/docs/api/classes/RBACError.md +1 -1
  63. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  64. package/docs/api/classes/SecureSupabaseClient.md +5 -5
  65. package/docs/api/classes/StorageUtils.md +1 -1
  66. package/docs/api/enums/FileCategory.md +1 -1
  67. package/docs/api/enums/LogLevel.md +1 -1
  68. package/docs/api/enums/RBACErrorCode.md +1 -1
  69. package/docs/api/enums/RPCFunction.md +1 -1
  70. package/docs/api/interfaces/AddressFieldProps.md +241 -0
  71. package/docs/api/interfaces/AddressFieldRef.md +94 -0
  72. package/docs/api/interfaces/AggregateConfig.md +1 -1
  73. package/docs/api/interfaces/AutocompleteOptions.md +75 -0
  74. package/docs/api/interfaces/BadgeProps.md +1 -1
  75. package/docs/api/interfaces/ButtonProps.md +1 -1
  76. package/docs/api/interfaces/CalendarProps.md +1 -1
  77. package/docs/api/interfaces/CardProps.md +1 -1
  78. package/docs/api/interfaces/ColorPalette.md +1 -1
  79. package/docs/api/interfaces/ColorShade.md +1 -1
  80. package/docs/api/interfaces/ComplianceResult.md +1 -1
  81. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  82. package/docs/api/interfaces/DataRecord.md +1 -1
  83. package/docs/api/interfaces/DataTableAction.md +1 -1
  84. package/docs/api/interfaces/DataTableColumn.md +1 -1
  85. package/docs/api/interfaces/DataTableProps.md +1 -1
  86. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  87. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  88. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  89. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  90. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  91. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  92. package/docs/api/interfaces/ExportColumn.md +1 -1
  93. package/docs/api/interfaces/ExportOptions.md +1 -1
  94. package/docs/api/interfaces/FileDisplayProps.md +15 -15
  95. package/docs/api/interfaces/FileMetadata.md +1 -1
  96. package/docs/api/interfaces/FileReference.md +1 -1
  97. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  98. package/docs/api/interfaces/FileUploadOptions.md +33 -9
  99. package/docs/api/interfaces/FileUploadProps.md +36 -14
  100. package/docs/api/interfaces/FooterProps.md +1 -1
  101. package/docs/api/interfaces/FormFieldProps.md +1 -1
  102. package/docs/api/interfaces/FormProps.md +1 -1
  103. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  104. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  105. package/docs/api/interfaces/InputProps.md +1 -1
  106. package/docs/api/interfaces/LabelProps.md +1 -1
  107. package/docs/api/interfaces/LoggerConfig.md +1 -1
  108. package/docs/api/interfaces/LoginFormProps.md +1 -1
  109. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  110. package/docs/api/interfaces/NavigationContextType.md +1 -1
  111. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  112. package/docs/api/interfaces/NavigationItem.md +1 -1
  113. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  114. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  115. package/docs/api/interfaces/Organisation.md +1 -1
  116. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  117. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  118. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  119. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  120. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  121. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  122. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  123. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  124. package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
  125. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  126. package/docs/api/interfaces/PaletteData.md +1 -1
  127. package/docs/api/interfaces/ParsedAddress.md +120 -0
  128. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  129. package/docs/api/interfaces/ProgressProps.md +1 -1
  130. package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
  131. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  132. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  133. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  134. package/docs/api/interfaces/QuickFix.md +1 -1
  135. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  136. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  137. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  138. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  139. package/docs/api/interfaces/RBACConfig.md +27 -4
  140. package/docs/api/interfaces/RBACContext.md +1 -1
  141. package/docs/api/interfaces/RBACLogger.md +5 -5
  142. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  143. package/docs/api/interfaces/RBACPerformanceMetrics.md +138 -0
  144. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  145. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  146. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  147. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  148. package/docs/api/interfaces/RBACResult.md +1 -1
  149. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  150. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  151. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  152. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  153. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  154. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  155. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  156. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  157. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  158. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  159. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  160. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  161. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  162. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  163. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  164. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  165. package/docs/api/interfaces/RouteConfig.md +1 -1
  166. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  167. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  168. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  169. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  170. package/docs/api/interfaces/SetupIssue.md +1 -1
  171. package/docs/api/interfaces/StorageConfig.md +1 -1
  172. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  173. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  174. package/docs/api/interfaces/StorageListOptions.md +1 -1
  175. package/docs/api/interfaces/StorageListResult.md +1 -1
  176. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  177. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  178. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  179. package/docs/api/interfaces/StyleImport.md +1 -1
  180. package/docs/api/interfaces/SwitchProps.md +1 -1
  181. package/docs/api/interfaces/TabsContentProps.md +1 -1
  182. package/docs/api/interfaces/TabsListProps.md +1 -1
  183. package/docs/api/interfaces/TabsProps.md +1 -1
  184. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  185. package/docs/api/interfaces/TextareaProps.md +1 -1
  186. package/docs/api/interfaces/ToastActionElement.md +1 -1
  187. package/docs/api/interfaces/ToastProps.md +1 -1
  188. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  189. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  190. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  191. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  192. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  193. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  194. package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
  195. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  196. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  197. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  198. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  199. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  200. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  201. package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
  202. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  203. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  204. package/docs/api/interfaces/UserEventAccess.md +1 -1
  205. package/docs/api/interfaces/UserMenuProps.md +1 -1
  206. package/docs/api/interfaces/UserProfile.md +1 -1
  207. package/docs/api/modules.md +328 -69
  208. package/docs/api-reference/components.md +26 -12
  209. package/docs/best-practices/performance.md +11 -0
  210. package/docs/implementation-guides/file-reference-system.md +24 -2
  211. package/docs/implementation-guides/file-upload-storage.md +38 -1
  212. package/docs/rbac/README.md +2 -1
  213. package/docs/rbac/api-reference.md +11 -0
  214. package/docs/rbac/performance.md +320 -0
  215. package/docs/standards/01-architecture-standard.md +5 -0
  216. package/docs/standards/05-security-standard.md +12 -0
  217. package/package.json +1 -1
  218. package/scripts/check-pace-core-compliance.js +512 -0
  219. package/src/components/AddressField/AddressField.test.tsx +411 -0
  220. package/src/components/AddressField/AddressField.tsx +323 -0
  221. package/src/components/AddressField/README.md +336 -0
  222. package/src/components/AddressField/index.ts +10 -0
  223. package/src/components/AddressField/types.ts +65 -0
  224. package/src/components/FileDisplay/FileDisplay.test.tsx +454 -0
  225. package/src/components/FileDisplay/FileDisplay.tsx +28 -1
  226. package/src/components/FileUpload/FileUpload.test.tsx +2 -0
  227. package/src/components/FileUpload/FileUpload.tsx +7 -1
  228. package/src/components/Header/Header.tsx +2 -5
  229. package/src/components/ProtectedRoute/ProtectedRoute.tsx +134 -1
  230. package/src/components/index.ts +2 -0
  231. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +30 -5
  232. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +11 -10
  233. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +31 -6
  234. package/src/hooks/index.ts +9 -0
  235. package/src/hooks/public/usePublicFileDisplay.ts +8 -10
  236. package/src/hooks/useAddressAutocomplete.test.ts +318 -0
  237. package/src/hooks/useAddressAutocomplete.ts +268 -0
  238. package/src/hooks/useFileDisplay.ts +3 -15
  239. package/src/hooks/useFileReference.test.ts +21 -3
  240. package/src/hooks/useFileReference.ts +3 -24
  241. package/src/hooks/useFileUrlCache.ts +246 -0
  242. package/src/hooks/useInactivityTracker.ts +31 -20
  243. package/src/hooks/useOrganisationSecurity.test.ts +10 -7
  244. package/src/hooks/useOrganisationSecurity.ts +3 -3
  245. package/src/hooks/usePreventTabReload.ts +106 -0
  246. package/src/hooks/useQueryCache.ts +315 -0
  247. package/src/hooks/useSecureDataAccess.ts +2 -2
  248. package/src/index.ts +2 -0
  249. package/src/providers/services/EventServiceProvider.tsx +4 -1
  250. package/src/rbac/__tests__/rbac-role-isolation.test.ts +456 -0
  251. package/src/rbac/api.test.ts +21 -6
  252. package/src/rbac/api.ts +32 -11
  253. package/src/rbac/audit-batched.ts +223 -0
  254. package/src/rbac/audit-enhanced.ts +2 -2
  255. package/src/rbac/audit.test.ts +6 -5
  256. package/src/rbac/audit.ts +34 -6
  257. package/src/rbac/cache-invalidation.ts +63 -12
  258. package/src/rbac/cache.test.ts +2 -2
  259. package/src/rbac/cache.ts +61 -14
  260. package/src/rbac/components/PagePermissionGuard.tsx +19 -10
  261. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +248 -0
  262. package/src/rbac/config.ts +9 -0
  263. package/src/rbac/engine.ts +2 -21
  264. package/src/rbac/hooks/usePermissions.ts +21 -5
  265. package/src/rbac/index.ts +19 -0
  266. package/src/rbac/performance.ts +210 -0
  267. package/src/rbac/request-deduplication.ts +87 -0
  268. package/src/rbac/utils/deep-equal.ts +93 -0
  269. package/src/styles/core.css +5 -5
  270. package/src/types/database.generated.ts +63 -9
  271. package/src/types/file-reference.ts +3 -1
  272. package/src/utils/file-reference/__tests__/file-reference.test.ts +89 -8
  273. package/src/utils/file-reference/index.ts +56 -17
  274. package/src/utils/google-places/googlePlacesUtils.test.ts +403 -0
  275. package/src/utils/google-places/googlePlacesUtils.ts +475 -0
  276. package/src/utils/google-places/index.ts +26 -0
  277. package/src/utils/google-places/loadGoogleMapsScript.ts +207 -0
  278. package/src/utils/google-places/types.ts +94 -0
  279. package/src/utils/index.ts +23 -0
  280. package/src/utils/request-deduplication.ts +165 -0
  281. package/src/utils/security/secureDataAccess.ts +1 -1
  282. package/src/utils/storage/helpers.ts +211 -4
  283. package/dist/chunk-445GEP27.js.map +0 -1
  284. package/dist/chunk-AISXLWGZ.js.map +0 -1
  285. package/dist/chunk-FMUCXFII.js +0 -76
  286. package/dist/chunk-FMUCXFII.js.map +0 -1
  287. package/dist/chunk-FSFQFJCU.js.map +0 -1
  288. package/dist/chunk-FXFJRTKI.js.map +0 -1
  289. package/dist/chunk-HC67NW5K.js.map +0 -1
  290. package/dist/chunk-IXSNYUCT.js.map +0 -1
  291. package/dist/chunk-MX3EIJGQ.js.map +0 -1
  292. package/dist/chunk-OKI34GZD.js.map +0 -1
  293. package/dist/chunk-STTZQK2I.js.map +0 -1
  294. package/dist/chunk-U6WNSFX5.js.map +0 -1
  295. /package/dist/{DataTable-IX2NBUTP.js.map → DataTable-K3RJRSOX.js.map} +0 -0
  296. /package/dist/{UnifiedAuthProvider-A4BCQRJY.js.map → UnifiedAuthProvider-B76OWOAT.js.map} +0 -0
  297. /package/dist/{api-BMFCXVQX.js.map → api-YP7XD5L6.js.map} +0 -0
  298. /package/dist/{audit-WRS3KJKI.js.map → audit-B5P6FFIR.js.map} +0 -0
  299. /package/dist/{chunk-HGPQUCBC.js.map → chunk-FMTK4XNN.js.map} +0 -0
  300. /package/dist/{chunk-XAUHJD3L.js.map → chunk-K2JGDXGU.js.map} +0 -0
@@ -2,7 +2,7 @@ import {
2
2
  createAuditManager,
3
3
  emitAuditEvent,
4
4
  setGlobalAuditManager
5
- } from "./chunk-FSFQFJCU.js";
5
+ } from "./chunk-63FOKYGO.js";
6
6
  import {
7
7
  createLogger
8
8
  } from "./chunk-PWLANIRT.js";
@@ -68,26 +68,41 @@ var MissingUserContextError = class extends RBACError {
68
68
  var RBACCache = class {
69
69
  constructor() {
70
70
  this.cache = /* @__PURE__ */ new Map();
71
- this.TTL = 60 * 1e3;
72
- // 60 seconds
71
+ this.sessionCache = /* @__PURE__ */ new Map();
72
+ this.TTL = 120 * 1e3;
73
+ // 120 seconds (short-term) - increased from 60s
74
+ this.SESSION_TTL = 15 * 60 * 1e3;
75
+ // 15 minutes (session-level) - increased from 5min
73
76
  this.invalidationCallbacks = /* @__PURE__ */ new Set();
74
77
  }
75
78
  /**
76
79
  * Get a value from the cache
77
80
  *
81
+ * Checks both short-term cache and session cache.
82
+ *
78
83
  * @param key - Cache key
84
+ * @param useSessionCache - Whether to check session cache (default: true)
79
85
  * @returns Cached value or null if not found/expired
80
86
  */
81
- get(key) {
87
+ get(key, useSessionCache = true) {
88
+ const now = Date.now();
82
89
  const entry = this.cache.get(key);
83
- if (!entry) {
84
- return null;
90
+ if (entry && now <= entry.expires) {
91
+ return entry.data;
85
92
  }
86
- if (Date.now() > entry.expires) {
93
+ if (entry && now > entry.expires) {
87
94
  this.cache.delete(key);
88
- return null;
89
95
  }
90
- return entry.data;
96
+ if (useSessionCache) {
97
+ const sessionEntry = this.sessionCache.get(key);
98
+ if (sessionEntry && now <= sessionEntry.expires) {
99
+ return sessionEntry.data;
100
+ }
101
+ if (sessionEntry && now > sessionEntry.expires) {
102
+ this.sessionCache.delete(key);
103
+ }
104
+ }
105
+ return null;
91
106
  }
92
107
  /**
93
108
  * Set a value in the cache
@@ -95,13 +110,22 @@ var RBACCache = class {
95
110
  * @param key - Cache key
96
111
  * @param data - Data to cache
97
112
  * @param ttl - Time to live in milliseconds (defaults to 60s)
113
+ * @param useSessionCache - Whether to also store in session cache (default: false for page-level checks)
98
114
  */
99
- set(key, data, ttl = this.TTL) {
100
- const expires = ttl <= 0 ? Date.now() - 1 : Date.now() + ttl;
115
+ set(key, data, ttl = this.TTL, useSessionCache = false) {
116
+ const now = Date.now();
117
+ const expires = ttl <= 0 ? now - 1 : now + ttl;
101
118
  this.cache.set(key, {
102
119
  data,
103
120
  expires
104
121
  });
122
+ if (useSessionCache) {
123
+ const sessionExpires = ttl <= 0 ? now - 1 : now + this.SESSION_TTL;
124
+ this.sessionCache.set(key, {
125
+ data,
126
+ expires: sessionExpires
127
+ });
128
+ }
105
129
  }
106
130
  /**
107
131
  * Delete a specific key from the cache
@@ -110,6 +134,7 @@ var RBACCache = class {
110
134
  */
111
135
  delete(key) {
112
136
  this.cache.delete(key);
137
+ this.sessionCache.delete(key);
113
138
  }
114
139
  /**
115
140
  * Invalidate cache entries matching a pattern
@@ -128,7 +153,15 @@ var RBACCache = class {
128
153
  keysToDelete.push(key);
129
154
  }
130
155
  }
131
- keysToDelete.forEach((key) => this.cache.delete(key));
156
+ for (const key of this.sessionCache.keys()) {
157
+ if (matcher(key) && !keysToDelete.includes(key)) {
158
+ keysToDelete.push(key);
159
+ }
160
+ }
161
+ keysToDelete.forEach((key) => {
162
+ this.cache.delete(key);
163
+ this.sessionCache.delete(key);
164
+ });
132
165
  this.invalidationCallbacks.forEach((callback) => callback(trimmedPattern));
133
166
  }
134
167
  createMatcher(pattern) {
@@ -145,6 +178,7 @@ var RBACCache = class {
145
178
  */
146
179
  clear() {
147
180
  this.cache.clear();
181
+ this.sessionCache.clear();
148
182
  }
149
183
  /**
150
184
  * Get cache statistics
@@ -152,7 +186,9 @@ var RBACCache = class {
152
186
  getStats() {
153
187
  return {
154
188
  size: this.cache.size,
189
+ sessionSize: this.sessionCache.size,
155
190
  ttl: this.TTL,
191
+ sessionTtl: this.SESSION_TTL,
156
192
  keys: Array.from(this.cache.keys())
157
193
  };
158
194
  }
@@ -296,6 +332,7 @@ var INVALIDATION_PATTERNS = {
296
332
  var RBACCacheInvalidationManager = class {
297
333
  constructor(supabase) {
298
334
  this.invalidationCallbacks = /* @__PURE__ */ new Set();
335
+ this.channels = [];
299
336
  this.supabase = supabase;
300
337
  this.setupRealtimeSubscriptions();
301
338
  }
@@ -393,13 +430,18 @@ var RBACCacheInvalidationManager = class {
393
430
  }
394
431
  /**
395
432
  * Setup realtime subscriptions for automatic cache invalidation
433
+ * Prevents duplicate subscriptions by checking if already set up
396
434
  */
397
435
  setupRealtimeSubscriptions() {
398
436
  if (!this.supabase.channel || typeof this.supabase.channel !== "function") {
399
437
  log.debug("Realtime not available, skipping subscriptions");
400
438
  return;
401
439
  }
402
- this.supabase.channel("rbac_organisation_roles_changes").on("postgres_changes", {
440
+ if (this.channels.length > 0) {
441
+ log.debug("Realtime subscriptions already set up, skipping duplicate setup");
442
+ return;
443
+ }
444
+ const orgRolesChannel = this.supabase.channel("rbac_organisation_roles_changes").on("postgres_changes", {
403
445
  event: "*",
404
446
  schema: "public",
405
447
  table: "rbac_organisation_roles"
@@ -411,8 +453,10 @@ var RBACCacheInvalidationManager = class {
411
453
  if (user_id) {
412
454
  this.invalidateUser(user_id, `organisation_role_${payload.eventType}`);
413
455
  }
414
- }).subscribe();
415
- this.supabase.channel("rbac_event_app_roles_changes").on("postgres_changes", {
456
+ });
457
+ const orgRolesSubscription = orgRolesChannel.subscribe();
458
+ this.channels.push(orgRolesSubscription);
459
+ const eventAppRolesChannel = this.supabase.channel("rbac_event_app_roles_changes").on("postgres_changes", {
416
460
  event: "*",
417
461
  schema: "public",
418
462
  table: "rbac_event_app_roles"
@@ -430,8 +474,10 @@ var RBACCacheInvalidationManager = class {
430
474
  if (app_id) {
431
475
  this.invalidateApp(app_id, `event_app_role_${payload.eventType}`);
432
476
  }
433
- }).subscribe();
434
- this.supabase.channel("rbac_global_roles_changes").on("postgres_changes", {
477
+ });
478
+ const eventAppRolesSubscription = eventAppRolesChannel.subscribe();
479
+ this.channels.push(eventAppRolesSubscription);
480
+ const globalRolesChannel = this.supabase.channel("rbac_global_roles_changes").on("postgres_changes", {
435
481
  event: "*",
436
482
  schema: "public",
437
483
  table: "rbac_global_roles"
@@ -440,8 +486,10 @@ var RBACCacheInvalidationManager = class {
440
486
  if (user_id) {
441
487
  this.invalidateUser(user_id, `global_role_${payload.eventType}`);
442
488
  }
443
- }).subscribe();
444
- this.supabase.channel("rbac_page_permissions_changes").on("postgres_changes", {
489
+ });
490
+ const globalRolesSubscription = globalRolesChannel.subscribe();
491
+ this.channels.push(globalRolesSubscription);
492
+ const pagePermissionsChannel = this.supabase.channel("rbac_page_permissions_changes").on("postgres_changes", {
445
493
  event: "*",
446
494
  schema: "public",
447
495
  table: "rbac_page_permissions"
@@ -453,7 +501,26 @@ var RBACCacheInvalidationManager = class {
453
501
  if (app_page_id) {
454
502
  this.invalidatePage(app_page_id, `page_permission_${payload.eventType}`);
455
503
  }
456
- }).subscribe();
504
+ });
505
+ const pagePermissionsSubscription = pagePermissionsChannel.subscribe();
506
+ this.channels.push(pagePermissionsSubscription);
507
+ }
508
+ /**
509
+ * Cleanup all realtime subscriptions
510
+ * Call this when the manager is no longer needed to prevent memory leaks
511
+ */
512
+ cleanup() {
513
+ this.channels.forEach((channel) => {
514
+ try {
515
+ if (channel && typeof channel.unsubscribe === "function") {
516
+ channel.unsubscribe();
517
+ }
518
+ } catch (error) {
519
+ log.warn("Failed to unsubscribe from channel:", error);
520
+ }
521
+ });
522
+ this.channels = [];
523
+ this.invalidationCallbacks.clear();
457
524
  }
458
525
  /**
459
526
  * Manually trigger cache invalidation for all users in an organisation
@@ -479,6 +546,10 @@ var RBACCacheInvalidationManager = class {
479
546
  };
480
547
  var globalCacheInvalidationManager = null;
481
548
  function initializeCacheInvalidation(supabase) {
549
+ if (globalCacheInvalidationManager) {
550
+ log.debug("Cleaning up existing cache invalidation manager before creating new one");
551
+ globalCacheInvalidationManager.cleanup();
552
+ }
482
553
  globalCacheInvalidationManager = new RBACCacheInvalidationManager(supabase);
483
554
  return globalCacheInvalidationManager;
484
555
  }
@@ -1083,24 +1154,6 @@ var RBACEngine = class {
1083
1154
  if (cached !== null) {
1084
1155
  cacheHit = true;
1085
1156
  cacheSource = "memory";
1086
- const duration2 = Date.now() - startTime;
1087
- if (scope.organisationId) {
1088
- const resolvedPageId = await this.resolvePageId(pageId, scope.appId);
1089
- await emitAuditEvent({
1090
- type: "permission_check",
1091
- userId,
1092
- organisationId: scope.organisationId,
1093
- eventId: scope.eventId,
1094
- appId: scope.appId,
1095
- pageId: resolvedPageId,
1096
- permission,
1097
- decision: cached,
1098
- source: "api",
1099
- duration_ms: duration2,
1100
- cache_hit: true,
1101
- cache_source: "memory"
1102
- });
1103
- }
1104
1157
  return cached;
1105
1158
  }
1106
1159
  const { data, error } = await this.supabase.rpc("rbac_check_permission_simplified", {
@@ -1409,6 +1462,167 @@ function createRBACEngine(supabase, securityConfig) {
1409
1462
  return new RBACEngine(supabase, securityConfig);
1410
1463
  }
1411
1464
 
1465
+ // src/rbac/performance.ts
1466
+ var RBACPerformanceMonitor = class {
1467
+ constructor() {
1468
+ this.metrics = {
1469
+ totalChecks: 0,
1470
+ cacheHits: 0,
1471
+ cacheMisses: 0,
1472
+ cacheHitRate: 0,
1473
+ deduplicatedRequests: 0,
1474
+ networkRequests: 0,
1475
+ averageResponseTime: 0,
1476
+ totalResponseTime: 0,
1477
+ batchedAuditEvents: 0,
1478
+ individualAuditEvents: 0
1479
+ };
1480
+ this.enabled = false;
1481
+ }
1482
+ /**
1483
+ * Enable or disable performance monitoring
1484
+ */
1485
+ setEnabled(enabled) {
1486
+ this.enabled = enabled;
1487
+ }
1488
+ /**
1489
+ * Check if performance monitoring is enabled
1490
+ */
1491
+ isEnabled() {
1492
+ return this.enabled;
1493
+ }
1494
+ /**
1495
+ * Record a permission check
1496
+ */
1497
+ recordCheck(cacheHit, responseTime, wasDeduplicated = false) {
1498
+ if (!this.enabled) {
1499
+ return;
1500
+ }
1501
+ this.metrics.totalChecks++;
1502
+ if (cacheHit) {
1503
+ this.metrics.cacheHits++;
1504
+ } else {
1505
+ this.metrics.cacheMisses++;
1506
+ this.metrics.networkRequests++;
1507
+ }
1508
+ if (wasDeduplicated) {
1509
+ this.metrics.deduplicatedRequests++;
1510
+ }
1511
+ this.metrics.totalResponseTime += responseTime;
1512
+ this.metrics.averageResponseTime = this.metrics.totalResponseTime / this.metrics.totalChecks;
1513
+ this.metrics.cacheHitRate = this.metrics.cacheHits / this.metrics.totalChecks;
1514
+ }
1515
+ /**
1516
+ * Record an audit event
1517
+ */
1518
+ recordAuditEvent(batched) {
1519
+ if (!this.enabled) {
1520
+ return;
1521
+ }
1522
+ if (batched) {
1523
+ this.metrics.batchedAuditEvents++;
1524
+ } else {
1525
+ this.metrics.individualAuditEvents++;
1526
+ }
1527
+ }
1528
+ /**
1529
+ * Get current metrics
1530
+ */
1531
+ getMetrics() {
1532
+ return { ...this.metrics };
1533
+ }
1534
+ /**
1535
+ * Reset all metrics
1536
+ */
1537
+ reset() {
1538
+ this.metrics = {
1539
+ totalChecks: 0,
1540
+ cacheHits: 0,
1541
+ cacheMisses: 0,
1542
+ cacheHitRate: 0,
1543
+ deduplicatedRequests: 0,
1544
+ networkRequests: 0,
1545
+ averageResponseTime: 0,
1546
+ totalResponseTime: 0,
1547
+ batchedAuditEvents: 0,
1548
+ individualAuditEvents: 0
1549
+ };
1550
+ }
1551
+ /**
1552
+ * Get metrics summary as a formatted string
1553
+ */
1554
+ getSummary() {
1555
+ const m = this.metrics;
1556
+ return `
1557
+ RBAC Performance Metrics:
1558
+ Total Checks: ${m.totalChecks}
1559
+ Cache Hits: ${m.cacheHits} (${(m.cacheHitRate * 100).toFixed(1)}%)
1560
+ Cache Misses: ${m.cacheMisses}
1561
+ Deduplicated Requests: ${m.deduplicatedRequests}
1562
+ Network Requests: ${m.networkRequests}
1563
+ Average Response Time: ${m.averageResponseTime.toFixed(2)}ms
1564
+ Batched Audit Events: ${m.batchedAuditEvents}
1565
+ Individual Audit Events: ${m.individualAuditEvents}
1566
+ `;
1567
+ }
1568
+ };
1569
+ var performanceMonitor = new RBACPerformanceMonitor();
1570
+ function enablePerformanceMonitoring() {
1571
+ performanceMonitor.setEnabled(true);
1572
+ }
1573
+ function disablePerformanceMonitoring() {
1574
+ performanceMonitor.setEnabled(false);
1575
+ }
1576
+ function isPerformanceMonitoringEnabled() {
1577
+ return performanceMonitor.isEnabled();
1578
+ }
1579
+ function recordPermissionCheck(cacheHit, responseTime, wasDeduplicated = false) {
1580
+ performanceMonitor.recordCheck(cacheHit, responseTime, wasDeduplicated);
1581
+ }
1582
+ function recordAuditEvent(batched) {
1583
+ performanceMonitor.recordAuditEvent(batched);
1584
+ }
1585
+ function getPerformanceMetrics() {
1586
+ return performanceMonitor.getMetrics();
1587
+ }
1588
+ function resetPerformanceMetrics() {
1589
+ performanceMonitor.reset();
1590
+ }
1591
+ function getPerformanceSummary() {
1592
+ return performanceMonitor.getSummary();
1593
+ }
1594
+
1595
+ // src/rbac/request-deduplication.ts
1596
+ var inFlightRequests = /* @__PURE__ */ new Map();
1597
+ function generateDeduplicationKey(input) {
1598
+ return RBACCache.generatePermissionKey({
1599
+ userId: input.userId,
1600
+ organisationId: input.scope.organisationId,
1601
+ eventId: input.scope.eventId,
1602
+ appId: input.scope.appId,
1603
+ permission: input.permission,
1604
+ pageId: input.pageId
1605
+ });
1606
+ }
1607
+ async function getOrCreateRequest(input, checkFn) {
1608
+ const key = generateDeduplicationKey(input);
1609
+ const existingRequest = inFlightRequests.get(key);
1610
+ if (existingRequest) {
1611
+ return existingRequest;
1612
+ }
1613
+ const requestPromise = checkFn(input).finally(() => {
1614
+ inFlightRequests.delete(key);
1615
+ });
1616
+ inFlightRequests.set(key, requestPromise);
1617
+ return requestPromise;
1618
+ }
1619
+ function clearInFlightRequests() {
1620
+ inFlightRequests.clear();
1621
+ }
1622
+ function getInFlightRequestCount() {
1623
+ return inFlightRequests.size;
1624
+ }
1625
+
1412
1626
  // src/rbac/api.ts
1413
1627
  var log3 = createLogger("RBACAPI");
1414
1628
  var globalEngine = null;
@@ -1430,8 +1644,16 @@ function setupRBAC(supabase, config) {
1430
1644
  ...config?.security
1431
1645
  };
1432
1646
  globalEngine = createRBACEngine(supabase, securityConfig);
1433
- const auditManager = createAuditManager(supabase);
1647
+ const useBatchedAudit = config?.audit?.batched !== false && config?.performance?.enableBatchedAuditLogging !== false;
1648
+ const batchConfig = useBatchedAudit ? {
1649
+ batchWindow: config?.audit?.batchWindow,
1650
+ batchSize: config?.audit?.batchSize
1651
+ } : void 0;
1652
+ const auditManager = createAuditManager(supabase, useBatchedAudit, batchConfig);
1434
1653
  setGlobalAuditManager(auditManager);
1654
+ if (config?.performance?.enablePerformanceTracking) {
1655
+ enablePerformanceMonitoring();
1656
+ }
1435
1657
  logger.info("RBAC system initialized successfully");
1436
1658
  }
1437
1659
  function getEngine() {
@@ -1480,13 +1702,16 @@ async function isPermittedCached(input) {
1480
1702
  permission,
1481
1703
  pageId
1482
1704
  });
1483
- const cached = rbacCache.get(cacheKey);
1705
+ const cached = rbacCache.get(cacheKey, true);
1484
1706
  if (cached !== null) {
1485
1707
  return cached;
1486
1708
  }
1487
- const result = await isPermitted(input);
1488
- rbacCache.set(cacheKey, result);
1489
- return result;
1709
+ return getOrCreateRequest(input, async (checkInput) => {
1710
+ const result = await isPermitted(checkInput);
1711
+ const isPageLevelCheck = !!pageId || permission.includes("page.");
1712
+ rbacCache.set(cacheKey, result, void 0, isPageLevelCheck);
1713
+ return result;
1714
+ });
1490
1715
  }
1491
1716
  async function hasPermission(input) {
1492
1717
  return isPermitted(input);
@@ -1589,6 +1814,16 @@ export {
1589
1814
  isDevelopmentMode,
1590
1815
  RBACEngine,
1591
1816
  createRBACEngine,
1817
+ enablePerformanceMonitoring,
1818
+ disablePerformanceMonitoring,
1819
+ isPerformanceMonitoringEnabled,
1820
+ recordPermissionCheck,
1821
+ recordAuditEvent,
1822
+ getPerformanceMetrics,
1823
+ resetPerformanceMetrics,
1824
+ getPerformanceSummary,
1825
+ clearInFlightRequests,
1826
+ getInFlightRequestCount,
1592
1827
  setupRBAC,
1593
1828
  getAccessLevel,
1594
1829
  getPermissionMap,
@@ -1610,4 +1845,4 @@ export {
1610
1845
  invalidateAppCache,
1611
1846
  clearCache
1612
1847
  };
1613
- //# sourceMappingURL=chunk-U6WNSFX5.js.map
1848
+ //# sourceMappingURL=chunk-HEHYGYOX.js.map