@jmruthers/pace-core 0.6.4 → 0.6.6

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 (387) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +5 -403
  3. package/core-usage-manifest.json +93 -0
  4. package/cursor-rules/00-pace-core-compliance.mdc +128 -26
  5. package/cursor-rules/01-standards-compliance.mdc +49 -8
  6. package/cursor-rules/02-project-structure.mdc +6 -0
  7. package/cursor-rules/03-solid-principles.mdc +2 -0
  8. package/cursor-rules/04-testing-standards.mdc +2 -0
  9. package/cursor-rules/05-bug-reports-and-features.mdc +2 -0
  10. package/cursor-rules/06-code-quality.mdc +2 -0
  11. package/cursor-rules/07-tech-stack-compliance.mdc +2 -0
  12. package/cursor-rules/08-markup-quality.mdc +52 -27
  13. package/cursor-rules/09-rbac-compliance.mdc +462 -0
  14. package/cursor-rules/10-error-handling-patterns.mdc +179 -0
  15. package/cursor-rules/11-performance-optimization.mdc +169 -0
  16. package/cursor-rules/12-ci-cd-integration.mdc +150 -0
  17. package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
  18. package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-2N_tqbfq.d.ts} +1 -1
  19. package/dist/DataTable-LRJL4IRV.js +15 -0
  20. package/dist/{PublicPageProvider-DEMpysFR.d.ts → PublicPageProvider-BBH6Vqg7.d.ts} +72 -139
  21. package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
  22. package/dist/api-Y4MQWOFW.js +4 -0
  23. package/dist/audit-MYQXYZFU.js +3 -0
  24. package/dist/{chunk-J36DSWQK.js → chunk-2HGJFNAH.js} +8 -28
  25. package/dist/{chunk-OEWDTMG7.js → chunk-3O3WHILE.js} +38 -121
  26. package/dist/{chunk-M43Y4SSO.js → chunk-3QC3KRHK.js} +1 -14
  27. package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
  28. package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
  29. package/dist/chunk-4T7OBVTU.js +62 -0
  30. package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
  31. package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
  32. package/dist/{chunk-NN6WWZ5U.js → chunk-7TYHROIV.js} +579 -563
  33. package/dist/{chunk-M7MPQISP.js → chunk-A55DK444.js} +9 -16
  34. package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
  35. package/dist/{chunk-L4OXEN46.js → chunk-BVP2BCJF.js} +2 -16
  36. package/dist/chunk-C7NSAPTL.js +1 -0
  37. package/dist/{chunk-YKRAFF5K.js → chunk-FENMYN2U.js} +73 -149
  38. package/dist/{chunk-AVMLPIM7.js → chunk-FTCRZOG2.js} +284 -432
  39. package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
  40. package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
  41. package/dist/{chunk-I6DAQMWX.js → chunk-LAZMKTTF.js} +930 -891
  42. package/dist/{chunk-5EC5MEWX.js → chunk-MAGBIDNS.js} +77 -222
  43. package/dist/chunk-MBADTM7L.js +64 -0
  44. package/dist/chunk-OHIK3MIO.js +994 -0
  45. package/dist/{chunk-6SOIHG6Z.js → chunk-S7DKJPLT.js} +115 -44
  46. package/dist/{chunk-FMUCXFII.js → chunk-SD6WQY43.js} +1 -5
  47. package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
  48. package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
  49. package/dist/{chunk-FFQEQTNW.js → chunk-UIYSCEV7.js} +134 -45
  50. package/dist/{chunk-3LPHPB62.js → chunk-ZFYPMX46.js} +271 -87
  51. package/dist/{chunk-7JPAB3T5.js → chunk-ZS5VO5JB.js} +1989 -1283
  52. package/dist/components.d.ts +6 -6
  53. package/dist/components.js +57 -267
  54. package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
  55. package/dist/eslint-rules/index.cjs +22 -0
  56. package/dist/eslint-rules/rules/compliance.cjs +348 -0
  57. package/dist/eslint-rules/rules/components.cjs +113 -0
  58. package/dist/eslint-rules/rules/imports.cjs +102 -0
  59. package/dist/eslint-rules/rules/rbac.cjs +790 -0
  60. package/dist/eslint-rules/utils/helpers.cjs +42 -0
  61. package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
  62. package/dist/hooks.d.ts +5 -5
  63. package/dist/hooks.js +62 -270
  64. package/dist/icons/index.d.ts +1 -0
  65. package/dist/icons/index.js +1 -0
  66. package/dist/index.d.ts +36 -26
  67. package/dist/index.js +87 -690
  68. package/dist/providers.d.ts +2 -2
  69. package/dist/providers.js +8 -35
  70. package/dist/rbac/eslint-rules.d.ts +46 -44
  71. package/dist/rbac/eslint-rules.js +7 -4
  72. package/dist/rbac/index.d.ts +124 -594
  73. package/dist/rbac/index.js +14 -207
  74. package/dist/styles/index.js +2 -12
  75. package/dist/theming/runtime.js +3 -19
  76. package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
  77. package/dist/{types-CkbwOr4Y.d.ts → types-B-K_5VnO.d.ts} +4 -0
  78. package/dist/types-t9H8qKRw.d.ts +55 -0
  79. package/dist/types.d.ts +1 -1
  80. package/dist/types.js +7 -94
  81. package/dist/{usePublicRouteParams-i3qtoBgg.d.ts → usePublicRouteParams-COZ28Mvq.d.ts} +9 -9
  82. package/dist/utils.d.ts +24 -117
  83. package/dist/utils.js +54 -392
  84. package/docs/README.md +16 -6
  85. package/docs/api/README.md +4 -402
  86. package/docs/api/modules.md +454 -930
  87. package/docs/api-reference/components.md +3 -1
  88. package/docs/api-reference/deprecated.md +31 -6
  89. package/docs/api-reference/rpc-functions.md +78 -3
  90. package/docs/best-practices/accessibility.md +6 -3
  91. package/docs/getting-started/cursor-rules.md +3 -23
  92. package/docs/getting-started/dependencies.md +650 -0
  93. package/docs/getting-started/installation-guide.md +20 -7
  94. package/docs/getting-started/quick-start.md +23 -12
  95. package/docs/implementation-guides/permission-enforcement.md +4 -0
  96. package/docs/rbac/MIGRATION_GUIDE.md +819 -0
  97. package/docs/rbac/RBAC_CONTRACT.md +724 -0
  98. package/docs/rbac/README.md +12 -3
  99. package/docs/rbac/edge-functions-guide.md +376 -0
  100. package/docs/rbac/secure-client-protection.md +0 -34
  101. package/docs/standards/00-pace-core-compliance.md +967 -0
  102. package/docs/standards/01-standards-compliance.md +188 -0
  103. package/docs/standards/02-project-structure.md +985 -0
  104. package/docs/standards/03-solid-principles.md +39 -0
  105. package/docs/standards/04-testing-standards.md +36 -0
  106. package/docs/standards/05-bug-reports-and-features.md +27 -0
  107. package/docs/standards/{04-code-style-standard.md → 06-code-quality.md} +2 -0
  108. package/docs/standards/07-tech-stack-compliance.md +30 -0
  109. package/docs/standards/08-markup-quality.md +345 -0
  110. package/docs/standards/{07-rbac-and-rls-standard.md → 09-rbac-compliance.md} +149 -54
  111. package/docs/standards/10-error-handling-patterns.md +401 -0
  112. package/docs/standards/11-performance-optimization.md +348 -0
  113. package/docs/standards/12-ci-cd-integration.md +370 -0
  114. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +192 -0
  115. package/docs/standards/README.md +62 -33
  116. package/docs/troubleshooting/organisation-context-setup.md +42 -19
  117. package/eslint-config-pace-core.cjs +20 -4
  118. package/package.json +31 -21
  119. package/scripts/audit/audit-compliance.cjs +1295 -0
  120. package/scripts/audit/audit-components.cjs +260 -0
  121. package/scripts/audit/audit-dependencies.cjs +395 -0
  122. package/scripts/audit/audit-rbac.cjs +954 -0
  123. package/scripts/audit/audit-standards.cjs +1268 -0
  124. package/scripts/audit/index.cjs +1898 -194
  125. package/scripts/install-cursor-rules.cjs +259 -8
  126. package/scripts/validate-master.js +1 -1
  127. package/src/__tests__/fixtures/supabase.ts +1 -1
  128. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +1 -1
  129. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
  130. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
  131. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +3 -3
  132. package/src/__tests__/helpers/component-test-utils.tsx +1 -1
  133. package/src/__tests__/helpers/supabaseMock.ts +2 -2
  134. package/src/__tests__/public-recipe-view.test.ts +38 -9
  135. package/src/components/Button/Button.tsx +5 -1
  136. package/src/components/ContextSelector/ContextSelector.tsx +42 -39
  137. package/src/components/DataTable/__tests__/keyboard.test.tsx +15 -2
  138. package/src/components/DataTable/components/DataTableBody.tsx +55 -31
  139. package/src/components/DataTable/components/DataTableCore.tsx +186 -13
  140. package/src/components/DataTable/components/DataTableLayout.tsx +30 -5
  141. package/src/components/DataTable/components/EditFields.tsx +23 -3
  142. package/src/components/DataTable/components/EditableRow.tsx +7 -2
  143. package/src/components/DataTable/components/ImportModal.tsx +4 -6
  144. package/src/components/DataTable/components/RowComponent.tsx +12 -0
  145. package/src/components/DataTable/components/ViewRowModal.tsx +4 -4
  146. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +455 -96
  147. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +122 -58
  148. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
  149. package/src/components/DataTable/core/DataTableContext.tsx +1 -1
  150. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
  151. package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
  152. package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
  153. package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
  154. package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
  155. package/src/components/DataTable/types.ts +5 -0
  156. package/src/components/DateTimeField/DateTimeField.tsx +20 -20
  157. package/src/components/DateTimeField/README.md +5 -2
  158. package/src/components/Dialog/Dialog.test.tsx +361 -318
  159. package/src/components/Dialog/Dialog.tsx +1154 -323
  160. package/src/components/Dialog/index.ts +3 -3
  161. package/src/components/FileDisplay/FileDisplay.test.tsx +45 -2
  162. package/src/components/FileDisplay/FileDisplay.tsx +28 -22
  163. package/src/components/Form/Form.test.tsx +9 -10
  164. package/src/components/Form/Form.tsx +369 -9
  165. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +28 -28
  166. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +40 -54
  167. package/src/components/LoginForm/LoginForm.tsx +2 -2
  168. package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
  169. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
  170. package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
  171. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
  172. package/src/components/PaceAppLayout/PaceAppLayout.tsx +30 -41
  173. package/src/components/PaceAppLayout/README.md +10 -9
  174. package/src/components/PaceAppLayout/test-setup.tsx +40 -31
  175. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
  176. package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
  177. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +61 -0
  178. package/src/components/PasswordChange/PasswordChangeForm.tsx +20 -13
  179. package/src/components/PublicLayout/PublicLayout.test.tsx +7 -3
  180. package/src/components/PublicLayout/PublicPageLayout.tsx +5 -8
  181. package/src/components/Select/Select.tsx +23 -21
  182. package/src/components/Select/types.ts +1 -1
  183. package/src/components/UserMenu/UserMenu.test.tsx +38 -6
  184. package/src/components/UserMenu/UserMenu.tsx +39 -34
  185. package/src/components/index.ts +3 -4
  186. package/src/eslint-rules/index.cjs +22 -0
  187. package/src/eslint-rules/rules/compliance.cjs +348 -0
  188. package/src/eslint-rules/rules/components.cjs +113 -0
  189. package/src/eslint-rules/rules/imports.cjs +102 -0
  190. package/src/eslint-rules/rules/rbac.cjs +790 -0
  191. package/src/eslint-rules/utils/helpers.cjs +42 -0
  192. package/src/eslint-rules/utils/manifest-loader.cjs +75 -0
  193. package/src/hooks/__tests__/hooks.integration.test.tsx +6 -8
  194. package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
  195. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
  196. package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
  197. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
  198. package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
  199. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
  200. package/src/hooks/public/usePublicEvent.ts +62 -190
  201. package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
  202. package/src/hooks/public/usePublicEventLogo.ts +19 -9
  203. package/src/hooks/useAppConfig.ts +26 -24
  204. package/src/hooks/useEventTheme.test.ts +211 -233
  205. package/src/hooks/useEventTheme.ts +19 -28
  206. package/src/hooks/useEvents.ts +11 -7
  207. package/src/hooks/useKeyboardShortcuts.ts +1 -1
  208. package/src/hooks/useOrganisationPermissions.ts +9 -11
  209. package/src/hooks/useOrganisations.ts +13 -7
  210. package/src/hooks/useQueryCache.ts +0 -1
  211. package/src/hooks/useSessionDraft.ts +380 -0
  212. package/src/hooks/useSessionRestoration.ts +3 -1
  213. package/src/icons/index.ts +27 -0
  214. package/src/index.ts +16 -1
  215. package/src/providers/OrganisationProvider.tsx +23 -14
  216. package/src/providers/services/EventServiceProvider.tsx +1 -24
  217. package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
  218. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -0
  219. package/src/rbac/README.md +20 -20
  220. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
  221. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
  222. package/src/rbac/adapters.tsx +7 -295
  223. package/src/rbac/api.test.ts +44 -56
  224. package/src/rbac/api.ts +10 -17
  225. package/src/rbac/cache-invalidation.ts +0 -1
  226. package/src/rbac/compliance/index.ts +10 -0
  227. package/src/rbac/compliance/pattern-detector.ts +553 -0
  228. package/src/rbac/compliance/runtime-compliance.ts +22 -0
  229. package/src/rbac/components/AccessDenied.tsx +150 -0
  230. package/src/rbac/components/NavigationGuard.tsx +12 -20
  231. package/src/rbac/components/PagePermissionGuard.tsx +4 -24
  232. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
  233. package/src/rbac/components/index.ts +3 -41
  234. package/src/rbac/eslint-rules.js +1 -1
  235. package/src/rbac/hooks/index.ts +0 -3
  236. package/src/rbac/hooks/permissions/index.ts +0 -3
  237. package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
  238. package/src/rbac/hooks/usePermissions.ts +0 -3
  239. package/src/rbac/hooks/useRBAC.test.ts +21 -3
  240. package/src/rbac/hooks/useRBAC.ts +4 -3
  241. package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
  242. package/src/rbac/hooks/useResolvedScope.ts +58 -140
  243. package/src/rbac/hooks/useResourcePermissions.test.ts +241 -60
  244. package/src/rbac/hooks/useResourcePermissions.ts +182 -63
  245. package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
  246. package/src/rbac/hooks/useRoleManagement.ts +147 -19
  247. package/src/rbac/hooks/useSecureSupabase.ts +4 -8
  248. package/src/rbac/index.ts +7 -9
  249. package/src/rbac/permissions.ts +17 -17
  250. package/src/rbac/utils/contextValidator.ts +45 -7
  251. package/src/services/AuthService.ts +132 -23
  252. package/src/services/EventService.ts +4 -97
  253. package/src/services/InactivityService.ts +155 -58
  254. package/src/services/OrganisationService.ts +7 -44
  255. package/src/services/__tests__/OrganisationService.test.ts +26 -8
  256. package/src/services/base/BaseService.ts +0 -3
  257. package/src/styles/core.css +4 -0
  258. package/src/types/database.generated.ts +4733 -3809
  259. package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
  260. package/src/utils/context/organisationContext.test.ts +13 -28
  261. package/src/utils/context/organisationContext.ts +21 -52
  262. package/src/utils/dynamic/dynamicUtils.ts +1 -1
  263. package/src/utils/file-reference/index.ts +39 -15
  264. package/src/utils/formatting/formatDateTime.test.ts +3 -2
  265. package/src/utils/formatting/formatTime.test.ts +3 -2
  266. package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
  267. package/src/utils/index.ts +4 -1
  268. package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
  269. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
  270. package/src/utils/persistence/keyDerivation.ts +304 -0
  271. package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
  272. package/src/utils/security/secureStorage.ts +5 -5
  273. package/src/utils/storage/helpers.ts +3 -3
  274. package/src/utils/supabase/createBaseClient.ts +147 -0
  275. package/src/utils/timezone/timezone.test.ts +1 -2
  276. package/src/utils/timezone/timezone.ts +1 -1
  277. package/src/utils/validation/csrf.ts +4 -4
  278. package/cursor-rules/CHANGELOG.md +0 -119
  279. package/cursor-rules/README.md +0 -192
  280. package/dist/DataTable-E7YQZD7D.js +0 -175
  281. package/dist/DataTable-E7YQZD7D.js.map +0 -1
  282. package/dist/UnifiedAuthProvider-QPXO24B4.js +0 -18
  283. package/dist/UnifiedAuthProvider-QPXO24B4.js.map +0 -1
  284. package/dist/api-6LVZTHDS.js +0 -52
  285. package/dist/api-6LVZTHDS.js.map +0 -1
  286. package/dist/audit-V53FV5AG.js +0 -17
  287. package/dist/audit-V53FV5AG.js.map +0 -1
  288. package/dist/chunk-36LVWXB2.js +0 -227
  289. package/dist/chunk-36LVWXB2.js.map +0 -1
  290. package/dist/chunk-3LPHPB62.js.map +0 -1
  291. package/dist/chunk-5DRSZLL2.js.map +0 -1
  292. package/dist/chunk-5EC5MEWX.js.map +0 -1
  293. package/dist/chunk-63FOKYGO.js.map +0 -1
  294. package/dist/chunk-6SOIHG6Z.js.map +0 -1
  295. package/dist/chunk-7JPAB3T5.js.map +0 -1
  296. package/dist/chunk-ATKZM7RX.js +0 -2053
  297. package/dist/chunk-ATKZM7RX.js.map +0 -1
  298. package/dist/chunk-AVMLPIM7.js.map +0 -1
  299. package/dist/chunk-DGUM43GV.js.map +0 -1
  300. package/dist/chunk-E66EQZE6.js.map +0 -1
  301. package/dist/chunk-FFQEQTNW.js.map +0 -1
  302. package/dist/chunk-FMUCXFII.js.map +0 -1
  303. package/dist/chunk-G37KK66H.js.map +0 -1
  304. package/dist/chunk-I6DAQMWX.js.map +0 -1
  305. package/dist/chunk-J36DSWQK.js.map +0 -1
  306. package/dist/chunk-KQCRWDSA.js +0 -1
  307. package/dist/chunk-KQCRWDSA.js.map +0 -1
  308. package/dist/chunk-L4OXEN46.js.map +0 -1
  309. package/dist/chunk-LMC26NLJ.js +0 -84
  310. package/dist/chunk-LMC26NLJ.js.map +0 -1
  311. package/dist/chunk-M43Y4SSO.js.map +0 -1
  312. package/dist/chunk-M7MPQISP.js.map +0 -1
  313. package/dist/chunk-NN6WWZ5U.js.map +0 -1
  314. package/dist/chunk-OEWDTMG7.js.map +0 -1
  315. package/dist/chunk-PWLANIRT.js.map +0 -1
  316. package/dist/chunk-QXHPKYJV.js.map +0 -1
  317. package/dist/chunk-VBXEHIUJ.js.map +0 -1
  318. package/dist/chunk-YKRAFF5K.js.map +0 -1
  319. package/dist/chunk-ZSAAAMVR.js.map +0 -1
  320. package/dist/components.js.map +0 -1
  321. package/dist/contextValidator-OOPCLPZW.js +0 -9
  322. package/dist/contextValidator-OOPCLPZW.js.map +0 -1
  323. package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
  324. package/dist/hooks.js.map +0 -1
  325. package/dist/index.js.map +0 -1
  326. package/dist/providers.js.map +0 -1
  327. package/dist/rbac/eslint-rules.js.map +0 -1
  328. package/dist/rbac/index.js.map +0 -1
  329. package/dist/styles/index.js.map +0 -1
  330. package/dist/theming/runtime.js.map +0 -1
  331. package/dist/types.js.map +0 -1
  332. package/dist/utils.js.map +0 -1
  333. package/docs/standards/01-architecture-standard.md +0 -44
  334. package/docs/standards/02-api-and-rpc-standard.md +0 -39
  335. package/docs/standards/03-component-standard.md +0 -32
  336. package/docs/standards/05-security-standard.md +0 -44
  337. package/docs/standards/06-testing-and-docs-standard.md +0 -29
  338. package/docs/standards/pace-core-compliance.md +0 -432
  339. package/scripts/audit/core/checks/accessibility.cjs +0 -197
  340. package/scripts/audit/core/checks/api-usage.cjs +0 -191
  341. package/scripts/audit/core/checks/bundle.cjs +0 -142
  342. package/scripts/audit/core/checks/compliance.cjs +0 -2706
  343. package/scripts/audit/core/checks/config.cjs +0 -54
  344. package/scripts/audit/core/checks/coverage.cjs +0 -84
  345. package/scripts/audit/core/checks/dependencies.cjs +0 -994
  346. package/scripts/audit/core/checks/documentation.cjs +0 -268
  347. package/scripts/audit/core/checks/environment.cjs +0 -116
  348. package/scripts/audit/core/checks/error-handling.cjs +0 -340
  349. package/scripts/audit/core/checks/forms.cjs +0 -172
  350. package/scripts/audit/core/checks/heuristics.cjs +0 -68
  351. package/scripts/audit/core/checks/hooks.cjs +0 -334
  352. package/scripts/audit/core/checks/imports.cjs +0 -244
  353. package/scripts/audit/core/checks/performance.cjs +0 -325
  354. package/scripts/audit/core/checks/routes.cjs +0 -117
  355. package/scripts/audit/core/checks/state.cjs +0 -130
  356. package/scripts/audit/core/checks/structure.cjs +0 -65
  357. package/scripts/audit/core/checks/style.cjs +0 -584
  358. package/scripts/audit/core/checks/testing.cjs +0 -122
  359. package/scripts/audit/core/checks/typescript.cjs +0 -61
  360. package/scripts/audit/core/scanner.cjs +0 -199
  361. package/scripts/audit/core/utils.cjs +0 -137
  362. package/scripts/audit/reporters/console.cjs +0 -151
  363. package/scripts/audit/reporters/json.cjs +0 -54
  364. package/scripts/audit/reporters/markdown.cjs +0 -124
  365. package/scripts/audit-consuming-app.cjs +0 -86
  366. package/src/eslint-rules/pace-core-compliance.cjs +0 -510
  367. package/src/eslint-rules/pace-core-compliance.js +0 -638
  368. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
  369. package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
  370. package/src/rbac/components/NavigationProvider.test.tsx +0 -481
  371. package/src/rbac/components/NavigationProvider.tsx +0 -345
  372. package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
  373. package/src/rbac/components/PagePermissionProvider.tsx +0 -279
  374. package/src/rbac/components/PermissionEnforcer.tsx +0 -312
  375. package/src/rbac/components/RoleBasedRouter.tsx +0 -440
  376. package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
  377. package/src/rbac/components/SecureDataProvider.tsx +0 -339
  378. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
  379. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
  380. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
  381. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
  382. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
  383. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
  384. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
  385. package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
  386. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
  387. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
@@ -37,18 +37,20 @@ export class AuthService extends BaseService implements IAuthService {
37
37
  restorationError: null,
38
38
  };
39
39
  private restorationTimeoutId: ReturnType<typeof setTimeout> | null = null;
40
- private readonly restorationTimeoutMs = 5000;
40
+ // Increased timeout to handle hard refresh scenarios where localStorage access
41
+ // and session restoration may take longer, especially with organisation/event context
42
+ private readonly restorationTimeoutMs = 10000; // 10 seconds (increased from 5)
41
43
  private restorationStartTime: number | null = null;
42
44
  private appName: string | undefined = undefined;
43
45
  private errorHandler: ((event: ErrorEvent) => void) | null = null;
44
46
  private unhandledRejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;
47
+ private wasAuthenticatedRef: boolean = false; // Track previous auth state to detect transitions
45
48
 
46
49
  constructor(supabaseClient: SupabaseClient, appName?: string) {
47
50
  super();
48
51
  this.instanceId = ++AuthService.instanceCount;
49
52
  this.supabaseClient = supabaseClient;
50
53
  this.appName = appName;
51
- logger.debug('AuthService', `Instance created [ID:${this.instanceId}]`, { appName });
52
54
  }
53
55
 
54
56
  getInstanceId(): number {
@@ -57,11 +59,8 @@ export class AuthService extends BaseService implements IAuthService {
57
59
 
58
60
  // Auth state getters
59
61
  getUser(): User | null {
60
- if (this.user) {
61
- logger.debug('AuthService', `getUser() [ID:${this.instanceId}] returning user: ${this.user.id}`);
62
- } else {
63
- logger.debug('AuthService', `getUser() [ID:${this.instanceId}] returning null`);
64
- }
62
+ // Removed debug logging - getUser() is called frequently and state changes
63
+ // are already logged in the auth state change handler
65
64
  return this.user;
66
65
  }
67
66
 
@@ -112,6 +111,15 @@ export class AuthService extends BaseService implements IAuthService {
112
111
  this.authError = null;
113
112
  this.user = data.user;
114
113
  this.session = data.session;
114
+
115
+ // Clear persistence immediately on successful login
116
+ // This prevents dialogs/forms/datatables from auto-opening with stale state
117
+ // We clear here synchronously before components can mount and check persisted state
118
+ // Also clear old unscoped keys to prevent data leakage
119
+ if (!this.wasAuthenticatedRef && data.user) {
120
+ this.clearPersistenceOnLogin(null, true);
121
+ this.wasAuthenticatedRef = true;
122
+ }
115
123
  }
116
124
 
117
125
  this.notify();
@@ -151,6 +159,14 @@ export class AuthService extends BaseService implements IAuthService {
151
159
  this.authError = null;
152
160
  this.user = data.user;
153
161
  this.session = data.session;
162
+
163
+ // Clear persistence immediately on successful signup/login
164
+ // This prevents dialogs/forms/datatables from auto-opening with stale state
165
+ // Also clear old unscoped keys to prevent data leakage
166
+ if (!this.wasAuthenticatedRef && data.user) {
167
+ this.clearPersistenceOnLogin(null, true);
168
+ this.wasAuthenticatedRef = true;
169
+ }
154
170
  }
155
171
 
156
172
  this.notify();
@@ -179,6 +195,14 @@ export class AuthService extends BaseService implements IAuthService {
179
195
  try {
180
196
  const { error } = await this.supabaseClient.auth.signOut();
181
197
 
198
+ // Clear sessionStorage on logout
199
+ try {
200
+ sessionStorage.clear();
201
+ } catch (storageError) {
202
+ // Ignore storage errors (e.g., in private browsing mode)
203
+ logger.warn('AuthService', 'Failed to clear sessionStorage', { error: storageError });
204
+ }
205
+
182
206
  if (error) {
183
207
  this.authError = error;
184
208
  } else {
@@ -190,6 +214,14 @@ export class AuthService extends BaseService implements IAuthService {
190
214
  this.notify();
191
215
  return { user: null, session: null, error };
192
216
  } catch (error) {
217
+ // Clear sessionStorage even on error
218
+ try {
219
+ sessionStorage.clear();
220
+ } catch (storageError) {
221
+ // Ignore storage errors (e.g., in private browsing mode)
222
+ logger.warn('AuthService', 'Failed to clear sessionStorage', { error: storageError });
223
+ }
224
+
193
225
  // Convert regular Error to AuthError if needed
194
226
  const authError = error instanceof AuthError
195
227
  ? error
@@ -400,6 +432,56 @@ export class AuthService extends BaseService implements IAuthService {
400
432
  }
401
433
  }
402
434
 
435
+ /**
436
+ * Clear pace-core persistence entries from sessionStorage
437
+ * This includes dialog, form, and datatable persistence
438
+ *
439
+ * @param userId - Optional user ID to clear only that user's persistence.
440
+ * If not provided, clears all pace-core persistence (for user changes).
441
+ * @param clearUnscoped - If true, also clears old unscoped keys (without :user: prefix)
442
+ */
443
+ private clearPersistenceOnLogin(userId?: string | null, clearUnscoped: boolean = true): void {
444
+ if (typeof window === 'undefined' || !window.sessionStorage) {
445
+ return;
446
+ }
447
+
448
+ try {
449
+ const keysToRemove: string[] = [];
450
+
451
+ // Collect all pace-core persistence keys
452
+ for (let i = 0; i < sessionStorage.length; i++) {
453
+ const key = sessionStorage.key(i);
454
+ if (key && (
455
+ key.startsWith('pace-core:draft:') ||
456
+ key.startsWith('pace-core:dialog:')
457
+ )) {
458
+ // If userId is provided, only clear keys for that user
459
+ // Otherwise, clear all (for user changes or fresh login)
460
+ if (userId && !key.includes(`:user:${userId}`)) {
461
+ // Also clear old unscoped keys (without :user: prefix) if requested
462
+ if (clearUnscoped && !key.includes(':user:')) {
463
+ keysToRemove.push(key);
464
+ }
465
+ continue; // Skip keys that don't match this user
466
+ }
467
+ keysToRemove.push(key);
468
+ }
469
+ }
470
+
471
+ // Remove all collected keys
472
+ keysToRemove.forEach(key => {
473
+ try {
474
+ sessionStorage.removeItem(key);
475
+ } catch (error) {
476
+ logger.warn('AuthService', `Failed to remove persistence key: ${key}`, error);
477
+ }
478
+ });
479
+
480
+ } catch (error) {
481
+ logger.warn('AuthService', `Failed to clear persistence [ID:${this.instanceId}]:`, error);
482
+ }
483
+ }
484
+
403
485
  private async setupAuthStateListener(): Promise<void> {
404
486
  if (!this.supabaseClient) {
405
487
  this.authLoading = false;
@@ -411,16 +493,20 @@ export class AuthService extends BaseService implements IAuthService {
411
493
  const subscription = this.supabaseClient.auth.onAuthStateChange(
412
494
  (event: AuthChangeEvent, session: SupabaseSession | null) => {
413
495
  try {
414
- logger.debug('AuthService', `Auth state change [ID:${this.instanceId}]`, {
415
- event,
416
- hasSession: !!session,
417
- userId: session?.user?.id
418
- });
496
+
497
+ // Track authentication state transition
498
+ const wasAuthenticated = this.wasAuthenticatedRef;
499
+ const isNowAuthenticated = !!session?.user;
500
+ const previousUserId = this.user?.id || null;
501
+ const newUserId = session?.user?.id || null;
502
+ const userChanged = previousUserId !== null && newUserId !== null && previousUserId !== newUserId;
503
+
419
504
  // Handle different auth events
420
505
  if (event === 'SIGNED_OUT') {
421
506
  this.session = null;
422
507
  this.user = null;
423
508
  this.authError = null;
509
+ this.wasAuthenticatedRef = false;
424
510
 
425
511
  // Automatic session tracking (non-blocking)
426
512
  if (session?.user) {
@@ -437,6 +523,19 @@ export class AuthService extends BaseService implements IAuthService {
437
523
  this.authError = null;
438
524
  }
439
525
 
526
+ // Clear persistence when:
527
+ // 1. Transitioning from unauthenticated to authenticated (fresh login) - clear all + old unscoped keys
528
+ // 2. User changes (different user logs in) - clear previous user's persistence + old unscoped keys
529
+ if (!wasAuthenticated && isNowAuthenticated && event === 'SIGNED_IN') {
530
+ // Fresh login - clear all persistence including old unscoped keys
531
+ this.clearPersistenceOnLogin(null, true);
532
+ } else if (userChanged && previousUserId) {
533
+ // User changed - clear previous user's persistence + old unscoped keys
534
+ this.clearPersistenceOnLogin(previousUserId, true);
535
+ }
536
+
537
+ this.wasAuthenticatedRef = isNowAuthenticated;
538
+
440
539
  // Automatic session tracking for login (non-blocking)
441
540
  // Only track on SIGNED_IN, not TOKEN_REFRESHED (to avoid duplicate login records)
442
541
  if (event === 'SIGNED_IN' && session?.user) {
@@ -446,10 +545,30 @@ export class AuthService extends BaseService implements IAuthService {
446
545
  }
447
546
  } else if (event === 'INITIAL_SESSION') {
448
547
  if (session) {
548
+ const previousUserId = this.user?.id || null;
549
+ const newUserId = session.user?.id || null;
550
+ const userChanged = previousUserId !== null && newUserId !== null && previousUserId !== newUserId;
551
+
449
552
  this.session = session;
450
553
  this.user = session.user ?? null;
451
554
  this.authError = null;
452
555
 
556
+ // Clear persistence if user changed (e.g., different user's session restored)
557
+ // This prevents data leakage when a different user's session is restored
558
+ if (userChanged && previousUserId) {
559
+ // Clear previous user's persistence + old unscoped keys
560
+ this.clearPersistenceOnLogin(previousUserId, true);
561
+ } else if (!wasAuthenticated && !!session.user) {
562
+ // Fresh login on INITIAL_SESSION - clear all persistence including old unscoped keys
563
+ this.clearPersistenceOnLogin(null, true);
564
+ }
565
+ // Don't clear persistence on INITIAL_SESSION for same user - this is just session restoration
566
+ // Persistence should only be cleared on actual SIGNED_IN events or user changes
567
+ // INITIAL_SESSION happens on page load/refresh, and we want to preserve
568
+ // dialog/form/datatable state across page refreshes for the same user
569
+
570
+ this.wasAuthenticatedRef = !!session.user;
571
+
453
572
  // Reset restoration state if valid session arrives after earlier failure
454
573
  // This clears stale errors when session eventually succeeds
455
574
  const hasTimeoutError = this.sessionRestorationState.restorationError?.name === 'SessionRestorationTimeoutError';
@@ -460,6 +579,7 @@ export class AuthService extends BaseService implements IAuthService {
460
579
  }
461
580
  } else {
462
581
  // No session in INITIAL_SESSION event - user is not authenticated
582
+ this.wasAuthenticatedRef = false;
463
583
  // Finish restoration to clear loading state
464
584
  if (this.sessionRestorationState.isRestoring) {
465
585
  this.finishSessionRestoration();
@@ -471,11 +591,6 @@ export class AuthService extends BaseService implements IAuthService {
471
591
  // before checking authentication state
472
592
  this.authLoading = false;
473
593
 
474
- // Final check: Ensure state matches what we just logged
475
- logger.debug('AuthService', `State synchronized after INITIAL_SESSION [ID:${this.instanceId}]`, {
476
- hasUser: !!this.user,
477
- userId: this.user?.id
478
- });
479
594
 
480
595
  this.notify();
481
596
  return; // Return early to avoid setting loading to false again below
@@ -484,12 +599,6 @@ export class AuthService extends BaseService implements IAuthService {
484
599
  // For other events (SIGNED_IN, SIGNED_OUT, TOKEN_REFRESHED), set loading to false and notify
485
600
  this.authLoading = false;
486
601
 
487
- // Final check: Ensure state matches what we just logged
488
- logger.debug('AuthService', `State synchronized after event [ID:${this.instanceId}]`, {
489
- event,
490
- hasUser: !!this.user,
491
- userId: this.user?.id
492
- });
493
602
 
494
603
  this.notify();
495
604
  } catch (error) {
@@ -59,11 +59,6 @@ export class EventService extends BaseService implements IEventService {
59
59
  this.appName = appName;
60
60
  this.selectedOrganisation = selectedOrganisation;
61
61
  this.setSelectedEventId = setSelectedEventId;
62
- logger.debug('EventService', `Instance created [ID:${this.instanceId}]`, {
63
- appName,
64
- hasUser: !!user,
65
- userId: user?.id
66
- });
67
62
  }
68
63
 
69
64
  getInstanceId(): number {
@@ -112,11 +107,6 @@ export class EventService extends BaseService implements IEventService {
112
107
  this.userClearedEventRef = false;
113
108
  this.hasAutoSelectedRef = false;
114
109
 
115
- logger.debug('EventService', `User changed [ID:${this.instanceId}]`, {
116
- previousUserId,
117
- newUserId,
118
- willInitialize: newUserId !== null
119
- });
120
110
  }
121
111
 
122
112
  this.supabaseClient = supabaseClient;
@@ -142,10 +132,6 @@ export class EventService extends BaseService implements IEventService {
142
132
 
143
133
  if (isRBACInitialized()) {
144
134
  this.isSuperAdmin = await checkSuperAdmin(user.id as UUID);
145
- logger.debug('EventService', 'Super admin status updated in updateDependencies', {
146
- userId: user.id,
147
- isSuperAdmin: this.isSuperAdmin
148
- });
149
135
  } else {
150
136
  // RBAC not initialized - this should be rare since UnifiedAuthProvider initializes it synchronously
151
137
  // Keep existing value (don't reset to false) to avoid clearing a previously determined super admin status
@@ -260,11 +246,6 @@ export class EventService extends BaseService implements IEventService {
260
246
  });
261
247
  // Reset the user cleared flag when selecting an event
262
248
  this.userClearedEventRef = false;
263
- logger.debug('EventService', 'Event selected', {
264
- eventId: event.event_id,
265
- eventName: event.event_name,
266
- userClearedEventRef: this.userClearedEventRef
267
- });
268
249
  } else {
269
250
  const previousEventId = this.selectedEvent?.event_id;
270
251
  this.selectedEvent = null;
@@ -277,11 +258,6 @@ export class EventService extends BaseService implements IEventService {
277
258
  this.hasAutoSelectedRef = false;
278
259
  // Mark that user explicitly cleared the event to prevent auto-selection
279
260
  this.userClearedEventRef = true;
280
- logger.debug('EventService', 'Event cleared via setSelectedEvent(null)', {
281
- previousEventId,
282
- userClearedEventRef: this.userClearedEventRef,
283
- stackTrace: new Error().stack
284
- });
285
261
  }
286
262
  this.notify();
287
263
  }
@@ -407,13 +383,11 @@ export class EventService extends BaseService implements IEventService {
407
383
  protected async doInitialize(): Promise<void> {
408
384
  // Skip if already initialized
409
385
  if (this.isInitializedRef) {
410
- logger.debug('EventService', 'Skipping initialization - already initialized');
411
386
  return;
412
387
  }
413
388
 
414
389
  // Skip if already fetching
415
390
  if (this.isFetchingRef) {
416
- logger.debug('EventService', 'Skipping initialization - already fetching');
417
391
  return;
418
392
  }
419
393
 
@@ -430,27 +404,14 @@ export class EventService extends BaseService implements IEventService {
430
404
  // For event-required apps, selectedOrganisation may be null (org derived from event)
431
405
  // For org-required apps, selectedOrganisation is required
432
406
  if (!this.user) {
433
- logger.debug('EventService', 'Skipping initialization - no user');
434
407
  return;
435
408
  }
436
409
 
437
- logger.debug('EventService', 'Initializing', {
438
- userId: this.user.id,
439
- appName: this.appName,
440
- hasSelectedOrganisation: !!this.selectedOrganisation,
441
- hasSupabaseClient: !!this.supabaseClient,
442
- hasSession: !!this.session
443
- });
444
-
445
410
  // Initial setup - fetch events on initialization
446
411
  await this.fetchEvents(false);
447
412
 
448
413
  // Mark as initialized after successful fetch
449
414
  this.isInitializedRef = true;
450
- logger.debug('EventService', 'Initialization complete', {
451
- eventsCount: this.events.length,
452
- hasError: !!this.error
453
- });
454
415
  }
455
416
 
456
417
  protected doCleanup(): void {
@@ -505,10 +466,6 @@ export class EventService extends BaseService implements IEventService {
505
466
  userIsSuperAdmin = await checkSuperAdmin(this.user.id as UUID);
506
467
  // Update cached value for future use
507
468
  this.isSuperAdmin = userIsSuperAdmin;
508
- logger.debug('EventService', 'Super admin check completed', {
509
- userId: this.user.id,
510
- isSuperAdmin: userIsSuperAdmin
511
- });
512
469
  } else {
513
470
  // RBAC not initialized - this should be rare since UnifiedAuthProvider initializes it synchronously
514
471
  // Use cached value from updateDependencies as fallback
@@ -544,10 +501,6 @@ export class EventService extends BaseService implements IEventService {
544
501
  } else {
545
502
  // No context available - pass null to get all accessible events via event-app roles
546
503
  // This allows users with event-app roles to see their events even without org context
547
- logger.debug('EventService', 'No organisation context available, fetching all accessible events', {
548
- hasSelectedEvent: !!this.selectedEvent,
549
- hasSelectedOrganisation: !!this.selectedOrganisation
550
- });
551
504
  organisationIdForRpc = null; // Will return events user has access to via event-app roles
552
505
  }
553
506
  }
@@ -580,14 +533,6 @@ export class EventService extends BaseService implements IEventService {
580
533
 
581
534
  // Call the RPC function following the established pattern
582
535
  // For super admins, pass null for p_organisation_id to see all events
583
- logger.debug('EventService', 'Fetching events', {
584
- userId: this.user.id,
585
- organisationIdForRpc,
586
- appName: this.appName,
587
- hasSelectedEvent: !!this.selectedEvent,
588
- hasSelectedOrganisation: !!this.selectedOrganisation,
589
- isSuperAdmin: userIsSuperAdmin
590
- });
591
536
 
592
537
  let { data, error: rpcError } = await this.supabaseClient.rpc('data_user_events_get', {
593
538
  p_user_id: this.user.id,
@@ -595,11 +540,6 @@ export class EventService extends BaseService implements IEventService {
595
540
  p_app_name: this.appName
596
541
  });
597
542
 
598
- logger.debug('EventService', 'RPC response', {
599
- dataLength: data?.length || 0,
600
- hasError: !!rpcError,
601
- error: rpcError
602
- });
603
543
 
604
544
  if (rpcError) {
605
545
  logger.error('EventService', 'RPC error fetching events:', rpcError);
@@ -671,10 +611,7 @@ export class EventService extends BaseService implements IEventService {
671
611
  this.setSelectedEventId?.(null);
672
612
  // Restore the previous userClearedEventRef value - this was an automatic clear, not user-initiated
673
613
  this.userClearedEventRef = previousUserClearedRef;
674
- logger.debug('EventService', 'Cleared selected event - no longer in events list', {
675
- previousEventId: selectedEventId,
676
- eventsCount: transformedEvents.length
677
- });
614
+ // Cleared selected event - no longer in events list
678
615
  }
679
616
  }
680
617
 
@@ -685,62 +622,32 @@ export class EventService extends BaseService implements IEventService {
685
622
  if (!skipLoadPersisted) {
686
623
  const persistedEventLoaded = await this.loadPersistedEvent(transformedEvents);
687
624
 
688
- logger.debug('EventService', 'Event selection check', {
689
- persistedEventLoaded,
690
- userClearedEventRef: this.userClearedEventRef,
691
- eventsCount: transformedEvents.length,
692
- hasSelectedEvent: !!this.selectedEvent
693
- });
694
-
695
625
  // If no persisted event was loaded and user hasn't explicitly cleared an event, auto-select the next event
696
626
  if (!persistedEventLoaded && !this.userClearedEventRef) {
697
627
  const nextEvent = this.getNextEventByDate(transformedEvents);
698
- logger.debug('EventService', 'Auto-selection attempt', {
699
- nextEventFound: !!nextEvent,
700
- nextEventId: nextEvent?.event_id,
701
- nextEventDate: nextEvent?.event_date
702
- });
703
628
  if (nextEvent) {
704
629
  this.hasAutoSelectedRef = true;
705
630
  // Use setSelectedEvent() to ensure consistent behavior
706
631
  // Theme will be applied by useEventTheme() hook
707
632
  this.setSelectedEvent(nextEvent);
708
- logger.debug('EventService', 'Auto-selected next event', {
709
- eventId: nextEvent.event_id,
710
- eventName: nextEvent.event_name,
711
- eventDate: nextEvent.event_date
712
- });
713
- } else {
714
- logger.debug('EventService', 'No next event found for auto-selection', {
715
- eventsCount: transformedEvents.length,
716
- eventsWithDates: transformedEvents.filter(e => e.event_date).length
717
- });
718
633
  }
719
634
  } else if (persistedEventLoaded) {
720
- logger.debug('EventService', 'Skipped auto-selection - persisted event loaded');
635
+ // Skipped auto-selection - persisted event loaded
721
636
  } else if (this.userClearedEventRef) {
722
- logger.debug('EventService', 'Skipped auto-selection - user explicitly cleared event');
637
+ // Skipped auto-selection - user explicitly cleared event
723
638
  }
724
639
  } else {
725
640
  // If skipping persisted event load, still do auto-selection for new users
726
641
  if (!this.userClearedEventRef) {
727
642
  const nextEvent = this.getNextEventByDate(transformedEvents);
728
- logger.debug('EventService', 'Auto-selection attempt (skip persisted)', {
729
- nextEventFound: !!nextEvent,
730
- nextEventId: nextEvent?.event_id
731
- });
732
643
  if (nextEvent) {
733
644
  this.hasAutoSelectedRef = true;
734
645
  // Use setSelectedEvent() to ensure consistent behavior
735
646
  // Theme will be applied by useEventTheme() hook
736
647
  this.setSelectedEvent(nextEvent);
737
- logger.debug('EventService', 'Auto-selected next event (skip persisted)', {
738
- eventId: nextEvent.event_id,
739
- eventName: nextEvent.event_name
740
- });
741
648
  }
742
649
  } else {
743
- logger.debug('EventService', 'Skipped auto-selection (skip persisted) - user explicitly cleared event');
650
+ // Skipped auto-selection (skip persisted) - user explicitly cleared event
744
651
  }
745
652
  }
746
653
  }