@jmruthers/pace-core 0.5.189 → 0.5.190
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.
- package/core-usage-manifest.json +0 -4
- package/dist/{AuthService-B-cd2MA4.d.ts → AuthService-CbP_utw2.d.ts} +7 -3
- package/dist/{DataTable-GUFUNZ3N.js → DataTable-ON3IXISJ.js} +8 -8
- package/dist/{PublicPageProvider-B8HaLe69.d.ts → PublicPageProvider-C4uxosp6.d.ts} +83 -24
- package/dist/{UnifiedAuthProvider-BG0AL5eE.d.ts → UnifiedAuthProvider-BYA9qB-o.d.ts} +4 -3
- package/dist/{UnifiedAuthProvider-643PUAIM.js → UnifiedAuthProvider-X5NXANVI.js} +4 -2
- package/dist/{api-YP7XD5L6.js → api-I6UCQ5S6.js} +4 -2
- package/dist/{chunk-DDM4CCYT.js → chunk-4QYC5L4K.js} +60 -35
- package/dist/chunk-4QYC5L4K.js.map +1 -0
- package/dist/{chunk-IM4QE42D.js → chunk-73HSNNOQ.js} +141 -326
- package/dist/chunk-73HSNNOQ.js.map +1 -0
- package/dist/{chunk-YHCN776L.js → chunk-DZWK57KZ.js} +2 -75
- package/dist/chunk-DZWK57KZ.js.map +1 -0
- package/dist/{chunk-3GOZZZYH.js → chunk-HQVPB5MZ.js} +238 -301
- package/dist/chunk-HQVPB5MZ.js.map +1 -0
- package/dist/{chunk-THRPYOFK.js → chunk-HW3OVDUF.js} +5 -5
- package/dist/chunk-HW3OVDUF.js.map +1 -0
- package/dist/{chunk-F2IMUDXZ.js → chunk-I7PSE6JW.js} +75 -2
- package/dist/chunk-I7PSE6JW.js.map +1 -0
- package/dist/{chunk-VGZZXKBR.js → chunk-J2XXC7R5.js} +280 -52
- package/dist/chunk-J2XXC7R5.js.map +1 -0
- package/dist/{chunk-UCQSRW7Z.js → chunk-NIU6J6OX.js} +425 -378
- package/dist/chunk-NIU6J6OX.js.map +1 -0
- package/dist/{chunk-HESYZWZW.js → chunk-QWWZ5CAQ.js} +2 -2
- package/dist/{chunk-HEHYGYOX.js → chunk-RUYZKXOD.js} +401 -46
- package/dist/chunk-RUYZKXOD.js.map +1 -0
- package/dist/{chunk-2UUZZJFT.js → chunk-SDMHPX3X.js} +176 -160
- package/dist/{chunk-2UUZZJFT.js.map → chunk-SDMHPX3X.js.map} +1 -1
- package/dist/{chunk-MX64ZF6I.js → chunk-STYK4OH2.js} +11 -11
- package/dist/chunk-STYK4OH2.js.map +1 -0
- package/dist/{chunk-YGPFYGA6.js → chunk-VVBAW5A5.js} +822 -498
- package/dist/chunk-VVBAW5A5.js.map +1 -0
- package/dist/chunk-Y4BUBBHD.js +614 -0
- package/dist/chunk-Y4BUBBHD.js.map +1 -0
- package/dist/{chunk-SAUPYVLF.js → chunk-ZSAAAMVR.js} +1 -1
- package/dist/chunk-ZSAAAMVR.js.map +1 -0
- package/dist/components.d.ts +3 -4
- package/dist/components.js +19 -19
- package/dist/components.js.map +1 -1
- package/dist/eslint-rules/pace-core-compliance.cjs +0 -2
- package/dist/{file-reference-D037xOFK.d.ts → file-reference-BavO2eQj.d.ts} +13 -10
- package/dist/hooks.d.ts +10 -5
- package/dist/hooks.js +14 -8
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +13 -11
- package/dist/index.js +79 -69
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +3 -3
- package/dist/providers.js +3 -1
- package/dist/rbac/index.d.ts +76 -12
- package/dist/rbac/index.js +12 -9
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/{usePublicRouteParams-CTDELQ7H.d.ts → usePublicRouteParams-DxIDS4bC.d.ts} +16 -9
- package/dist/utils.js +16 -16
- package/docs/README.md +2 -2
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +2 -2
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +2 -2
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +4 -4
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +2 -2
- package/docs/api/classes/SecureSupabaseClient.md +21 -16
- package/docs/api/classes/StorageUtils.md +7 -4
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +1 -1
- package/docs/api/interfaces/AddressFieldRef.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CalendarProps.md +20 -6
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +62 -16
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +2 -2
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +26 -12
- package/docs/api/interfaces/FileUploadProps.md +30 -19
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +1 -1
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
- package/docs/api/interfaces/NavigationContextType.md +9 -9
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +7 -7
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +8 -8
- package/docs/api/interfaces/PagePermissionContextType.md +8 -8
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +3 -11
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/QuickFix.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
- package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +10 -10
- package/docs/api/interfaces/RouteConfig.md +10 -10
- package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- package/docs/api/interfaces/SetupIssue.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +4 -4
- package/docs/api/interfaces/StorageFileInfo.md +7 -7
- package/docs/api/interfaces/StorageFileMetadata.md +25 -14
- package/docs/api/interfaces/StorageListOptions.md +22 -9
- package/docs/api/interfaces/StorageListResult.md +4 -4
- package/docs/api/interfaces/StorageUploadOptions.md +21 -8
- package/docs/api/interfaces/StorageUploadResult.md +6 -6
- package/docs/api/interfaces/StorageUrlOptions.md +19 -6
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +1 -1
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
- package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +11 -11
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +151 -92
- package/docs/api-reference/components.md +15 -7
- package/docs/api-reference/providers.md +2 -2
- package/docs/api-reference/rpc-functions.md +1 -0
- package/docs/best-practices/README.md +1 -1
- package/docs/best-practices/deployment.md +8 -8
- package/docs/getting-started/examples/README.md +2 -2
- package/docs/getting-started/installation-guide.md +4 -4
- package/docs/getting-started/quick-start.md +3 -3
- package/docs/migration/MIGRATION_GUIDE.md +3 -3
- package/docs/rbac/compliance/compliance-guide.md +2 -2
- package/docs/rbac/event-based-apps.md +2 -2
- package/docs/rbac/getting-started.md +2 -2
- package/docs/rbac/quick-start.md +2 -2
- package/docs/security/README.md +4 -4
- package/docs/standards/07-rbac-and-rls-standard.md +430 -7
- package/docs/troubleshooting/README.md +2 -2
- package/docs/troubleshooting/migration.md +3 -3
- package/package.json +1 -3
- package/scripts/check-pace-core-compliance.cjs +1 -1
- package/scripts/check-pace-core-compliance.js +1 -1
- package/src/__tests__/fixtures/supabase.ts +301 -0
- package/src/__tests__/public-recipe-view.test.ts +9 -9
- package/src/__tests__/rls-policies.test.ts +197 -61
- package/src/components/AddressField/AddressField.test.tsx +42 -0
- package/src/components/AddressField/AddressField.tsx +71 -60
- package/src/components/AddressField/README.md +1 -0
- package/src/components/Alert/Alert.test.tsx +50 -10
- package/src/components/Alert/Alert.tsx +5 -3
- package/src/components/Avatar/Avatar.test.tsx +95 -43
- package/src/components/Avatar/Avatar.tsx +16 -16
- package/src/components/Button/Button.test.tsx +2 -1
- package/src/components/Button/Button.tsx +3 -3
- package/src/components/Calendar/Calendar.test.tsx +53 -37
- package/src/components/Calendar/Calendar.tsx +409 -82
- package/src/components/Card/Card.test.tsx +7 -4
- package/src/components/Card/Card.tsx +3 -6
- package/src/components/Checkbox/Checkbox.tsx +2 -2
- package/src/components/DataTable/components/ActionButtons.tsx +5 -5
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
- package/src/components/DataTable/components/ColumnFilter.tsx +1 -1
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +3 -3
- package/src/components/DataTable/components/DataTableBody.tsx +12 -12
- package/src/components/DataTable/components/DataTableCore.tsx +3 -3
- package/src/components/DataTable/components/DataTableToolbar.tsx +5 -5
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -3
- package/src/components/DataTable/components/EditableRow.tsx +2 -2
- package/src/components/DataTable/components/EmptyState.tsx +3 -3
- package/src/components/DataTable/components/GroupHeader.tsx +2 -2
- package/src/components/DataTable/components/GroupingDropdown.tsx +1 -1
- package/src/components/DataTable/components/ImportModal.tsx +4 -4
- package/src/components/DataTable/components/LoadingState.tsx +1 -1
- package/src/components/DataTable/components/PaginationControls.tsx +11 -11
- package/src/components/DataTable/components/UnifiedTableBody.tsx +9 -9
- package/src/components/DataTable/components/ViewRowModal.tsx +2 -2
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +11 -37
- package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +157 -0
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +2 -1
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +128 -0
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +19 -0
- package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +51 -0
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +84 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +14 -0
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +136 -0
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +16 -0
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +18 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +28 -7
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +30 -1
- package/src/components/DataTable/utils/hierarchicalUtils.ts +38 -10
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -3
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +4 -4
- package/src/components/Dialog/Dialog.tsx +2 -2
- package/src/components/EventSelector/EventSelector.tsx +7 -7
- package/src/components/FileDisplay/FileDisplay.tsx +291 -179
- package/src/components/FileUpload/FileUpload.tsx +7 -4
- package/src/components/Header/Header.test.tsx +28 -0
- package/src/components/Header/Header.tsx +22 -9
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -2
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +19 -14
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +5 -5
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +127 -1
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +8 -8
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +4 -0
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +16 -6
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +37 -3
- package/src/components/PaceAppLayout/test-setup.tsx +1 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +66 -45
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +6 -4
- package/src/components/Progress/Progress.test.tsx +18 -19
- package/src/components/Progress/Progress.tsx +31 -32
- package/src/components/PublicLayout/PublicLayout.test.tsx +6 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +5 -3
- package/src/components/Select/Select.tsx +5 -5
- package/src/components/Switch/Switch.test.tsx +2 -1
- package/src/components/Switch/Switch.tsx +1 -1
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.test.tsx +8 -2
- package/src/components/UserMenu/UserMenu.tsx +3 -3
- package/src/eslint-rules/pace-core-compliance.cjs +0 -2
- package/src/eslint-rules/pace-core-compliance.js +0 -2
- package/src/hooks/__tests__/hooks.integration.test.tsx +4 -1
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +76 -5
- package/src/hooks/__tests__/useDataTableState.test.ts +76 -0
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +25 -69
- package/src/hooks/__tests__/useFileUrlCache.test.ts +129 -0
- package/src/hooks/__tests__/usePreventTabReload.test.ts +88 -0
- package/src/hooks/__tests__/{usePublicEvent.unit.test.ts → usePublicEvent.test.ts} +28 -1
- package/src/hooks/__tests__/useQueryCache.test.ts +144 -0
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +58 -16
- package/src/hooks/index.ts +1 -1
- package/src/hooks/public/usePublicEvent.ts +2 -2
- package/src/hooks/public/usePublicFileDisplay.ts +173 -87
- package/src/hooks/useAppConfig.ts +24 -5
- package/src/hooks/useFileDisplay.ts +297 -34
- package/src/hooks/useFileReference.ts +56 -11
- package/src/hooks/useFileUrl.ts +1 -1
- package/src/hooks/useInactivityTracker.ts +16 -7
- package/src/hooks/usePermissionCache.test.ts +85 -8
- package/src/hooks/useQueryCache.ts +21 -0
- package/src/hooks/useSecureDataAccess.test.ts +80 -35
- package/src/hooks/useSecureDataAccess.ts +80 -37
- package/src/providers/services/EventServiceProvider.tsx +37 -17
- package/src/providers/services/InactivityServiceProvider.tsx +4 -4
- package/src/providers/services/OrganisationServiceProvider.tsx +8 -1
- package/src/providers/services/UnifiedAuthProvider.tsx +115 -29
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +451 -0
- package/src/rbac/__tests__/engine.comprehensive.test.ts +12 -0
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +8 -0
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +4 -0
- package/src/rbac/api.ts +240 -36
- package/src/rbac/cache-invalidation.ts +21 -7
- package/src/rbac/compliance/quick-fix-suggestions.ts +1 -1
- package/src/rbac/components/NavigationGuard.tsx +23 -63
- package/src/rbac/components/NavigationProvider.test.tsx +52 -23
- package/src/rbac/components/NavigationProvider.tsx +13 -11
- package/src/rbac/components/PagePermissionGuard.tsx +77 -203
- package/src/rbac/components/PagePermissionProvider.tsx +13 -11
- package/src/rbac/components/PermissionEnforcer.tsx +24 -62
- package/src/rbac/components/RoleBasedRouter.tsx +14 -12
- package/src/rbac/components/SecureDataProvider.tsx +13 -11
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +104 -41
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +49 -12
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +22 -1
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +161 -82
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +22 -1
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +77 -30
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +39 -5
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +47 -4
- package/src/rbac/engine.ts +4 -2
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +144 -52
- package/src/rbac/hooks/index.ts +3 -0
- package/src/rbac/hooks/useCan.test.ts +101 -53
- package/src/rbac/hooks/usePermissions.ts +108 -41
- package/src/rbac/hooks/useRBAC.test.ts +11 -3
- package/src/rbac/hooks/useRBAC.ts +83 -40
- package/src/rbac/hooks/useResolvedScope.test.ts +189 -63
- package/src/rbac/hooks/useResolvedScope.ts +128 -70
- package/src/rbac/hooks/useSecureSupabase.ts +36 -19
- package/src/rbac/hooks/useSuperAdminBypass.ts +126 -0
- package/src/rbac/request-deduplication.ts +1 -1
- package/src/rbac/secureClient.ts +72 -12
- package/src/rbac/security.ts +29 -23
- package/src/rbac/types.ts +10 -0
- package/src/rbac/utils/__tests__/contextValidator.test.ts +150 -0
- package/src/rbac/utils/__tests__/deep-equal.test.ts +53 -0
- package/src/rbac/utils/__tests__/eventContext.test.ts +6 -1
- package/src/rbac/utils/contextValidator.ts +288 -0
- package/src/rbac/utils/eventContext.ts +48 -2
- package/src/services/EventService.ts +165 -21
- package/src/services/OrganisationService.ts +37 -2
- package/src/services/__tests__/EventService.test.ts +26 -21
- package/src/types/file-reference.ts +13 -10
- package/src/utils/app/appNameResolver.test.ts +346 -73
- package/src/utils/context/superAdminOverride.ts +58 -0
- package/src/utils/file-reference/index.ts +61 -33
- package/src/utils/google-places/googlePlacesUtils.test.ts +98 -0
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +83 -0
- package/src/utils/storage/helpers.test.ts +1 -1
- package/src/utils/storage/helpers.ts +38 -19
- package/src/utils/storage/types.ts +15 -8
- package/src/utils/validation/__tests__/csrf.test.ts +105 -0
- package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +92 -0
- package/src/vite-env.d.ts +2 -2
- package/dist/chunk-3GOZZZYH.js.map +0 -1
- package/dist/chunk-DDM4CCYT.js.map +0 -1
- package/dist/chunk-E7UAOUMY.js +0 -75
- package/dist/chunk-E7UAOUMY.js.map +0 -1
- package/dist/chunk-F2IMUDXZ.js.map +0 -1
- package/dist/chunk-HEHYGYOX.js.map +0 -1
- package/dist/chunk-IM4QE42D.js.map +0 -1
- package/dist/chunk-MX64ZF6I.js.map +0 -1
- package/dist/chunk-SAUPYVLF.js.map +0 -1
- package/dist/chunk-THRPYOFK.js.map +0 -1
- package/dist/chunk-UCQSRW7Z.js.map +0 -1
- package/dist/chunk-VGZZXKBR.js.map +0 -1
- package/dist/chunk-YGPFYGA6.js.map +0 -1
- package/dist/chunk-YHCN776L.js.map +0 -1
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -703
- package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
- package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -428
- /package/dist/{DataTable-GUFUNZ3N.js.map → DataTable-ON3IXISJ.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-643PUAIM.js.map → UnifiedAuthProvider-X5NXANVI.js.map} +0 -0
- /package/dist/{api-YP7XD5L6.js.map → api-I6UCQ5S6.js.map} +0 -0
- /package/dist/{chunk-HESYZWZW.js.map → chunk-QWWZ5CAQ.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
lastUpdated: 2025-01-
|
|
3
|
-
version: 0.5.
|
|
4
|
-
reviewedBy:
|
|
2
|
+
lastUpdated: 2025-01-02T00:00:00+11:00
|
|
3
|
+
version: 0.5.182
|
|
4
|
+
reviewedBy: rls-audit-and-fixes
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# RBAC and RLS Standard
|
|
@@ -138,6 +138,24 @@ These functions are available for use in RLS policies:
|
|
|
138
138
|
- **Purpose**: Returns the current organisation context from the session
|
|
139
139
|
- **Usage**: `get_organisation_context()`
|
|
140
140
|
|
|
141
|
+
#### `is_authenticated_user()`
|
|
142
|
+
- **Returns**: `boolean`
|
|
143
|
+
- **Purpose**: Checks if the current user is authenticated (not anonymous)
|
|
144
|
+
- **Usage**: `is_authenticated_user()`
|
|
145
|
+
- **Note**: Use this instead of `(SELECT auth.role()) = 'authenticated'` in policies
|
|
146
|
+
|
|
147
|
+
#### `is_service_role()`
|
|
148
|
+
- **Returns**: `boolean`
|
|
149
|
+
- **Purpose**: Checks if the current user has service_role
|
|
150
|
+
- **Usage**: `is_service_role()`
|
|
151
|
+
- **Note**: Use this instead of `(SELECT auth.role()) = 'service_role'` in policies
|
|
152
|
+
|
|
153
|
+
#### `get_effective_user_id()`
|
|
154
|
+
- **Returns**: `UUID`
|
|
155
|
+
- **Purpose**: Returns the current user ID (auth.uid()) in a STABLE function
|
|
156
|
+
- **Usage**: `get_effective_user_id()`
|
|
157
|
+
- **Note**: Use this instead of `(SELECT auth.uid())` or inline `auth.uid()` in policies
|
|
158
|
+
|
|
141
159
|
### Event Helper Functions
|
|
142
160
|
|
|
143
161
|
#### `get_unit_event_id(p_unit_id TEXT)`
|
|
@@ -170,8 +188,24 @@ These functions are available for use in RLS policies:
|
|
|
170
188
|
|
|
171
189
|
## RLS Policy Patterns
|
|
172
190
|
|
|
191
|
+
This section documents the standard RLS policy patterns used throughout the codebase. All patterns follow the principles of using helper functions, enforcing security by default, and maintaining consistent structure.
|
|
192
|
+
|
|
193
|
+
### Policy Naming Convention
|
|
194
|
+
|
|
195
|
+
Policies follow this naming pattern:
|
|
196
|
+
- `rbac_{operation}_{table_name}_{scope}` for authenticated policies
|
|
197
|
+
- `{operation}_{table_name}_{scope}` for public/anonymous policies
|
|
198
|
+
|
|
199
|
+
Examples:
|
|
200
|
+
- `rbac_select_cake_dish_authenticated` - Authenticated SELECT policy
|
|
201
|
+
- `event_public_select` - Public SELECT policy for events
|
|
202
|
+
- `rbac_insert_file_references` - INSERT policy (no scope suffix if only one)
|
|
203
|
+
|
|
173
204
|
### Standard Organisation-Scoped Policy
|
|
174
205
|
|
|
206
|
+
**Use Case:** Tables where rows belong to an organisation and access is controlled by organisation membership.
|
|
207
|
+
|
|
208
|
+
**Pattern:**
|
|
175
209
|
```sql
|
|
176
210
|
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
177
211
|
FOR SELECT TO authenticated
|
|
@@ -184,8 +218,18 @@ USING (
|
|
|
184
218
|
);
|
|
185
219
|
```
|
|
186
220
|
|
|
187
|
-
|
|
221
|
+
**Example:** `organisations`, `organisation_app_access`
|
|
222
|
+
|
|
223
|
+
**Notes:**
|
|
224
|
+
- Always check `organisation_id IS NOT NULL` first
|
|
225
|
+
- Super admin check comes before organisation access check
|
|
226
|
+
- Use `check_user_organisation_access()` for basic membership checks
|
|
188
227
|
|
|
228
|
+
### RBAC Permission-Based Policy
|
|
229
|
+
|
|
230
|
+
**Use Case:** Tables that require specific page-level permissions (most common pattern for app tables).
|
|
231
|
+
|
|
232
|
+
**Pattern:**
|
|
189
233
|
```sql
|
|
190
234
|
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
191
235
|
FOR SELECT TO authenticated
|
|
@@ -193,14 +237,22 @@ USING (
|
|
|
193
237
|
organisation_id IS NOT NULL
|
|
194
238
|
AND (
|
|
195
239
|
is_super_admin()
|
|
196
|
-
OR
|
|
240
|
+
OR check_rbac_permission_with_context(
|
|
241
|
+
'read:page.table_name',
|
|
242
|
+
'table_name',
|
|
243
|
+
organisation_id,
|
|
244
|
+
event_id, -- NULL if not event-scoped
|
|
245
|
+
get_app_id('APP_NAME')
|
|
246
|
+
)
|
|
197
247
|
)
|
|
198
248
|
);
|
|
199
249
|
```
|
|
200
250
|
|
|
201
|
-
|
|
251
|
+
**Example:** `cake_dish`, `cake_item`, `base_application`
|
|
202
252
|
|
|
253
|
+
**Full CRUD Example:**
|
|
203
254
|
```sql
|
|
255
|
+
-- SELECT
|
|
204
256
|
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
205
257
|
FOR SELECT TO authenticated
|
|
206
258
|
USING (
|
|
@@ -216,12 +268,171 @@ USING (
|
|
|
216
268
|
)
|
|
217
269
|
)
|
|
218
270
|
);
|
|
271
|
+
|
|
272
|
+
-- INSERT
|
|
273
|
+
CREATE POLICY "rbac_insert_table_name" ON table_name
|
|
274
|
+
FOR INSERT TO authenticated
|
|
275
|
+
WITH CHECK (
|
|
276
|
+
organisation_id IS NOT NULL
|
|
277
|
+
AND (
|
|
278
|
+
is_super_admin()
|
|
279
|
+
OR check_rbac_permission_with_context(
|
|
280
|
+
'create:page.table_name',
|
|
281
|
+
'table_name',
|
|
282
|
+
organisation_id,
|
|
283
|
+
event_id,
|
|
284
|
+
get_app_id('APP_NAME')
|
|
285
|
+
)
|
|
286
|
+
)
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
-- UPDATE
|
|
290
|
+
CREATE POLICY "rbac_update_table_name" ON table_name
|
|
291
|
+
FOR UPDATE TO authenticated
|
|
292
|
+
USING (
|
|
293
|
+
organisation_id IS NOT NULL
|
|
294
|
+
AND (
|
|
295
|
+
is_super_admin()
|
|
296
|
+
OR check_rbac_permission_with_context(
|
|
297
|
+
'update:page.table_name',
|
|
298
|
+
'table_name',
|
|
299
|
+
organisation_id,
|
|
300
|
+
event_id,
|
|
301
|
+
get_app_id('APP_NAME')
|
|
302
|
+
)
|
|
303
|
+
)
|
|
304
|
+
)
|
|
305
|
+
WITH CHECK (
|
|
306
|
+
organisation_id IS NOT NULL
|
|
307
|
+
AND (
|
|
308
|
+
is_super_admin()
|
|
309
|
+
OR check_rbac_permission_with_context(
|
|
310
|
+
'update:page.table_name',
|
|
311
|
+
'table_name',
|
|
312
|
+
organisation_id,
|
|
313
|
+
event_id,
|
|
314
|
+
get_app_id('APP_NAME')
|
|
315
|
+
)
|
|
316
|
+
)
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
-- DELETE
|
|
320
|
+
CREATE POLICY "rbac_delete_table_name" ON table_name
|
|
321
|
+
FOR DELETE TO authenticated
|
|
322
|
+
USING (
|
|
323
|
+
organisation_id IS NOT NULL
|
|
324
|
+
AND (
|
|
325
|
+
is_super_admin()
|
|
326
|
+
OR check_rbac_permission_with_context(
|
|
327
|
+
'delete:page.table_name',
|
|
328
|
+
'table_name',
|
|
329
|
+
organisation_id,
|
|
330
|
+
event_id,
|
|
331
|
+
get_app_id('APP_NAME')
|
|
332
|
+
)
|
|
333
|
+
)
|
|
334
|
+
);
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Notes:**
|
|
338
|
+
- Always use `check_rbac_permission_with_context()` instead of calling `rbac_check_permission_simplified()` with `auth.uid()` directly
|
|
339
|
+
- The wrapper function is STABLE SECURITY DEFINER and ensures optimal performance
|
|
340
|
+
- Permission format: `{operation}:page.{page_name}` (e.g., `'read:page.dishes'`, `'create:page.items'`)
|
|
341
|
+
- Use `get_app_id('APP_NAME')` to get the app UUID (never hardcode)
|
|
342
|
+
|
|
343
|
+
### Standard Event-Scoped Policy
|
|
344
|
+
|
|
345
|
+
**Use Case:** Tables where rows belong to an event and access is controlled by event membership.
|
|
346
|
+
|
|
347
|
+
**Pattern:**
|
|
348
|
+
```sql
|
|
349
|
+
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
350
|
+
FOR SELECT TO authenticated
|
|
351
|
+
USING (
|
|
352
|
+
organisation_id IS NOT NULL
|
|
353
|
+
AND (
|
|
354
|
+
is_super_admin()
|
|
355
|
+
OR check_user_event_access(event_id)
|
|
356
|
+
)
|
|
357
|
+
);
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**Example:** Event-specific data that doesn't require page-level permissions
|
|
361
|
+
|
|
362
|
+
**Note:** For event-scoped data that also requires page permissions, combine with RBAC permission pattern.
|
|
363
|
+
|
|
364
|
+
### User-Scoped Data Policy
|
|
365
|
+
|
|
366
|
+
**Use Case:** Tables where rows belong to individual users (organisation_id IS NULL) and users can only access their own data.
|
|
367
|
+
|
|
368
|
+
**Pattern:**
|
|
369
|
+
```sql
|
|
370
|
+
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
371
|
+
FOR SELECT TO authenticated
|
|
372
|
+
USING (
|
|
373
|
+
organisation_id IS NULL
|
|
374
|
+
AND get_effective_user_id() = user_id
|
|
375
|
+
);
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**Example:** User profile data, user-scoped file references
|
|
379
|
+
|
|
380
|
+
**Multi-Condition Pattern (Organisation OR User-Scoped):**
|
|
381
|
+
```sql
|
|
382
|
+
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
383
|
+
FOR SELECT
|
|
384
|
+
USING (
|
|
385
|
+
-- Organisation-scoped access
|
|
386
|
+
(
|
|
387
|
+
organisation_id IS NOT NULL
|
|
388
|
+
AND is_authenticated_user()
|
|
389
|
+
AND (
|
|
390
|
+
is_super_admin()
|
|
391
|
+
OR check_user_organisation_access(organisation_id)
|
|
392
|
+
)
|
|
393
|
+
)
|
|
394
|
+
OR
|
|
395
|
+
-- User-scoped access
|
|
396
|
+
(
|
|
397
|
+
organisation_id IS NULL
|
|
398
|
+
AND is_authenticated_user()
|
|
399
|
+
AND get_effective_user_id() = user_id
|
|
400
|
+
)
|
|
401
|
+
);
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
**Example:** `file_references`, `pace_address` (can be either organisation or user-scoped)
|
|
405
|
+
|
|
406
|
+
### Service Role Policy
|
|
407
|
+
|
|
408
|
+
**Use Case:** Allow service_role to bypass RLS for system operations.
|
|
409
|
+
|
|
410
|
+
**Pattern:**
|
|
411
|
+
```sql
|
|
412
|
+
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
413
|
+
FOR SELECT
|
|
414
|
+
USING (
|
|
415
|
+
is_service_role()
|
|
416
|
+
OR (
|
|
417
|
+
-- Other conditions for authenticated users
|
|
418
|
+
is_authenticated_user()
|
|
419
|
+
AND ...
|
|
420
|
+
)
|
|
421
|
+
);
|
|
219
422
|
```
|
|
220
423
|
|
|
221
|
-
**
|
|
424
|
+
**Example:** `file_references` (service_role can access all files for system operations)
|
|
425
|
+
|
|
426
|
+
**Notes:**
|
|
427
|
+
- Service role check should be first in OR conditions
|
|
428
|
+
- Service role bypasses all other security checks
|
|
429
|
+
- Use sparingly - only for tables that need system-level access
|
|
222
430
|
|
|
223
431
|
### Public Access Policy
|
|
224
432
|
|
|
433
|
+
**Use Case:** Tables where some data should be publicly accessible (anonymous users).
|
|
434
|
+
|
|
435
|
+
**Pattern:**
|
|
225
436
|
```sql
|
|
226
437
|
CREATE POLICY "public_select_table_name" ON table_name
|
|
227
438
|
FOR SELECT TO anon
|
|
@@ -230,6 +441,195 @@ USING (
|
|
|
230
441
|
);
|
|
231
442
|
```
|
|
232
443
|
|
|
444
|
+
**Alternative Pattern (Simple Public Flag):**
|
|
445
|
+
```sql
|
|
446
|
+
CREATE POLICY "public_select_table_name" ON table_name
|
|
447
|
+
FOR SELECT TO anon
|
|
448
|
+
USING (
|
|
449
|
+
is_public = true
|
|
450
|
+
AND organisation_id IS NOT NULL
|
|
451
|
+
);
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
**Example:** `event` (public events), `forms` (published forms)
|
|
455
|
+
|
|
456
|
+
**Combined Public + Authenticated Pattern:**
|
|
457
|
+
```sql
|
|
458
|
+
-- Public access
|
|
459
|
+
CREATE POLICY "public_select_table_name" ON table_name
|
|
460
|
+
FOR SELECT TO anon
|
|
461
|
+
USING (
|
|
462
|
+
is_public = true
|
|
463
|
+
AND organisation_id IS NOT NULL
|
|
464
|
+
);
|
|
465
|
+
|
|
466
|
+
-- Authenticated access (with additional permissions)
|
|
467
|
+
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
468
|
+
FOR SELECT TO authenticated
|
|
469
|
+
USING (
|
|
470
|
+
(is_public = true AND organisation_id IS NOT NULL)
|
|
471
|
+
OR (
|
|
472
|
+
organisation_id IS NOT NULL
|
|
473
|
+
AND (
|
|
474
|
+
is_super_admin()
|
|
475
|
+
OR check_user_organisation_access(organisation_id)
|
|
476
|
+
)
|
|
477
|
+
)
|
|
478
|
+
);
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Complex Multi-Condition Policy
|
|
482
|
+
|
|
483
|
+
**Use Case:** Tables that need multiple access patterns (service role, public, organisation-scoped, user-scoped).
|
|
484
|
+
|
|
485
|
+
**Pattern:**
|
|
486
|
+
```sql
|
|
487
|
+
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
488
|
+
FOR SELECT
|
|
489
|
+
USING (
|
|
490
|
+
-- Service role can access all
|
|
491
|
+
is_service_role()
|
|
492
|
+
-- Public access
|
|
493
|
+
OR (is_public = true)
|
|
494
|
+
-- Organisation-scoped authenticated access
|
|
495
|
+
OR (
|
|
496
|
+
is_authenticated_user()
|
|
497
|
+
AND organisation_id IS NOT NULL
|
|
498
|
+
AND (
|
|
499
|
+
is_super_admin()
|
|
500
|
+
OR check_user_organisation_access(organisation_id)
|
|
501
|
+
)
|
|
502
|
+
)
|
|
503
|
+
-- User-scoped authenticated access
|
|
504
|
+
OR (
|
|
505
|
+
is_authenticated_user()
|
|
506
|
+
AND organisation_id IS NULL
|
|
507
|
+
AND get_effective_user_id() = user_id
|
|
508
|
+
)
|
|
509
|
+
);
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
**Example:** `file_references` (supports all access patterns)
|
|
513
|
+
|
|
514
|
+
**Notes:**
|
|
515
|
+
- Order matters: most permissive first (service_role), then public, then authenticated
|
|
516
|
+
- Each condition should be mutually exclusive where possible
|
|
517
|
+
- Use helper functions for all checks (never inline auth calls)
|
|
518
|
+
|
|
519
|
+
### Read-Only Type Table Policy
|
|
520
|
+
|
|
521
|
+
**Use Case:** Reference/lookup tables that authenticated users should be able to read but not modify.
|
|
522
|
+
|
|
523
|
+
**Pattern:**
|
|
524
|
+
```sql
|
|
525
|
+
CREATE POLICY "read_table_name" ON table_name
|
|
526
|
+
FOR SELECT
|
|
527
|
+
USING (is_authenticated_user());
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
**Example:** `pace_gender_type`, `pace_phone_type`, `medi_condition_type`
|
|
531
|
+
|
|
532
|
+
**Notes:**
|
|
533
|
+
- No INSERT/UPDATE/DELETE policies needed
|
|
534
|
+
- Super simple - just check if user is authenticated
|
|
535
|
+
- These tables typically don't have organisation_id
|
|
536
|
+
|
|
537
|
+
### Super Admin Only Policy
|
|
538
|
+
|
|
539
|
+
**Use Case:** Tables that only super admins should access.
|
|
540
|
+
|
|
541
|
+
**Pattern:**
|
|
542
|
+
```sql
|
|
543
|
+
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
544
|
+
FOR SELECT TO authenticated
|
|
545
|
+
USING (is_super_admin());
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
**Example:** `rbac_global_roles`, `rbac_policy_configs`
|
|
549
|
+
|
|
550
|
+
**Full CRUD Example:**
|
|
551
|
+
```sql
|
|
552
|
+
-- All operations restricted to super admin
|
|
553
|
+
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
554
|
+
FOR SELECT TO authenticated
|
|
555
|
+
USING (is_super_admin());
|
|
556
|
+
|
|
557
|
+
CREATE POLICY "rbac_insert_table_name" ON table_name
|
|
558
|
+
FOR INSERT TO authenticated
|
|
559
|
+
WITH CHECK (is_super_admin());
|
|
560
|
+
|
|
561
|
+
CREATE POLICY "rbac_update_table_name" ON table_name
|
|
562
|
+
FOR UPDATE TO authenticated
|
|
563
|
+
USING (is_super_admin())
|
|
564
|
+
WITH CHECK (is_super_admin());
|
|
565
|
+
|
|
566
|
+
CREATE POLICY "rbac_delete_table_name" ON table_name
|
|
567
|
+
FOR DELETE TO authenticated
|
|
568
|
+
USING (is_super_admin());
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### Common Patterns Summary
|
|
572
|
+
|
|
573
|
+
| Pattern | Use Case | Key Helper Functions |
|
|
574
|
+
|---------|----------|---------------------|
|
|
575
|
+
| Organisation-Scoped | Basic org membership | `check_user_organisation_access()` |
|
|
576
|
+
| RBAC Permission-Based | Page-level permissions | `check_rbac_permission_with_context()`, `get_app_id()` |
|
|
577
|
+
| Event-Scoped | Event membership | `check_user_event_access()` |
|
|
578
|
+
| User-Scoped | Personal data | `get_effective_user_id()` |
|
|
579
|
+
| Service Role | System operations | `is_service_role()` |
|
|
580
|
+
| Public Access | Anonymous users | `check_public_event_access()` or `is_public` flag |
|
|
581
|
+
| Read-Only Types | Reference tables | `is_authenticated_user()` |
|
|
582
|
+
| Super Admin Only | Admin-only tables | `is_super_admin()` |
|
|
583
|
+
|
|
584
|
+
### Policy Best Practices
|
|
585
|
+
|
|
586
|
+
1. **Always use helper functions** - Never inline `auth.uid()`, `auth.role()`, or `current_setting()`
|
|
587
|
+
2. **Check NULL first** - Always check `organisation_id IS NOT NULL` before using it
|
|
588
|
+
3. **Super admin first** - Super admin checks should come before other checks in OR conditions
|
|
589
|
+
4. **Service role first** - Service role checks should be the first condition in multi-condition policies
|
|
590
|
+
5. **Consistent naming** - Follow the naming convention: `rbac_{operation}_{table}_{scope}`
|
|
591
|
+
6. **Document exceptions** - If a policy deviates from standard patterns, add a comment explaining why
|
|
592
|
+
7. **Test thoroughly** - Test with different user roles (super_admin, org_admin, member, anon)
|
|
593
|
+
8. **Avoid `true OR ...`** - Never use `true OR ...` conditions as they bypass all security checks
|
|
594
|
+
|
|
595
|
+
### Common Pitfalls to Avoid
|
|
596
|
+
|
|
597
|
+
**❌ DON'T:**
|
|
598
|
+
```sql
|
|
599
|
+
-- Inline auth calls
|
|
600
|
+
USING (user_id = auth.uid())
|
|
601
|
+
|
|
602
|
+
-- Security bypass
|
|
603
|
+
USING (true OR check_user_organisation_access(organisation_id))
|
|
604
|
+
|
|
605
|
+
-- Missing NULL check
|
|
606
|
+
USING (check_user_organisation_access(organisation_id))
|
|
607
|
+
|
|
608
|
+
-- Direct current_setting
|
|
609
|
+
USING (organisation_id = current_setting('app.organisation_id')::UUID)
|
|
610
|
+
|
|
611
|
+
-- Public policy without proper checks
|
|
612
|
+
USING (true) -- Allows anyone!
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
**✅ DO:**
|
|
616
|
+
```sql
|
|
617
|
+
-- Use helper functions
|
|
618
|
+
USING (get_effective_user_id() = user_id)
|
|
619
|
+
|
|
620
|
+
-- Proper security checks
|
|
621
|
+
USING (check_user_organisation_access(organisation_id))
|
|
622
|
+
|
|
623
|
+
-- NULL check first
|
|
624
|
+
USING (organisation_id IS NOT NULL AND check_user_organisation_access(organisation_id))
|
|
625
|
+
|
|
626
|
+
-- Use helper function
|
|
627
|
+
USING (organisation_id = get_organisation_context())
|
|
628
|
+
|
|
629
|
+
-- Proper public policy
|
|
630
|
+
USING (is_public = true AND organisation_id IS NOT NULL)
|
|
631
|
+
```
|
|
632
|
+
|
|
233
633
|
## App Ownership
|
|
234
634
|
|
|
235
635
|
Tables are assigned to specific apps for RBAC permission checking:
|
|
@@ -333,6 +733,29 @@ Monitor:
|
|
|
333
733
|
|
|
334
734
|
## Migration Guidelines
|
|
335
735
|
|
|
736
|
+
### Migration Filename Requirements
|
|
737
|
+
|
|
738
|
+
**CRITICAL**: Migration filenames **MUST** use real timestamps, not guessed or placeholder dates.
|
|
739
|
+
|
|
740
|
+
1. **Always use the current timestamp** when creating migration files
|
|
741
|
+
2. **Format**: `YYYYMMDDHHMMSS_descriptive_name.sql`
|
|
742
|
+
3. **How to get the timestamp**:
|
|
743
|
+
```bash
|
|
744
|
+
date +"%Y%m%d%H%M%S"
|
|
745
|
+
```
|
|
746
|
+
4. **Never guess or use placeholder dates** - This causes migration ordering issues and conflicts
|
|
747
|
+
5. **Verify the timestamp is after the latest migration** in `supabase/migrations/`
|
|
748
|
+
|
|
749
|
+
**Example**:
|
|
750
|
+
```bash
|
|
751
|
+
# Get current timestamp
|
|
752
|
+
date +"%Y%m%d%H%M%S"
|
|
753
|
+
# Output: 20251201124800
|
|
754
|
+
|
|
755
|
+
# Use it in filename
|
|
756
|
+
20251201124800_allow_medi_action_plan_null_condition_id.sql
|
|
757
|
+
```
|
|
758
|
+
|
|
336
759
|
### Creating New RLS Policies
|
|
337
760
|
|
|
338
761
|
1. **Use helper functions** - Never inline `auth.uid()` or `current_setting()`
|
|
@@ -413,7 +413,7 @@ npm run build -- --debug
|
|
|
413
413
|
// Verify environment variables
|
|
414
414
|
console.log('Environment:', {
|
|
415
415
|
supabaseUrl: import.meta.env.VITE_SUPABASE_URL,
|
|
416
|
-
supabaseKey: import.meta.env.
|
|
416
|
+
supabaseKey: import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY,
|
|
417
417
|
appName: import.meta.env.VITE_APP_NAME,
|
|
418
418
|
});
|
|
419
419
|
```
|
|
@@ -431,7 +431,7 @@ console.log('Environment:', {
|
|
|
431
431
|
# Example deployment config
|
|
432
432
|
env:
|
|
433
433
|
VITE_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
|
|
434
|
-
|
|
434
|
+
VITE_SUPABASE_PUBLISHABLE_KEY: ${{ secrets.SUPABASE_PUBLISHABLE_KEY }}
|
|
435
435
|
VITE_APP_NAME: "My App"
|
|
436
436
|
```
|
|
437
437
|
|
|
@@ -403,7 +403,7 @@ VITE_DEBUG_MODE=true
|
|
|
403
403
|
|
|
404
404
|
# New environment variables
|
|
405
405
|
VITE_SUPABASE_URL=https://your-project.supabase.co
|
|
406
|
-
|
|
406
|
+
VITE_SUPABASE_PUBLISHABLE_KEY=your-publishable-key
|
|
407
407
|
VITE_APP_ENV=development
|
|
408
408
|
VITE_DEBUG=false
|
|
409
409
|
|
|
@@ -420,7 +420,7 @@ cp .env .env.backup
|
|
|
420
420
|
cat > .env << EOF
|
|
421
421
|
# Supabase Configuration
|
|
422
422
|
VITE_SUPABASE_URL=${VITE_SUPABASE_URL:-https://your-project.supabase.co}
|
|
423
|
-
|
|
423
|
+
VITE_SUPABASE_PUBLISHABLE_KEY=${VITE_SUPABASE_PUBLISHABLE_KEY:-your-publishable-key}
|
|
424
424
|
|
|
425
425
|
# Application Configuration
|
|
426
426
|
VITE_APP_ENV=${VITE_APP_ENV:-development}
|
|
@@ -706,7 +706,7 @@ export class MigrationValidation {
|
|
|
706
706
|
static validateConfiguration(config: any) {
|
|
707
707
|
const required = [
|
|
708
708
|
'VITE_SUPABASE_URL',
|
|
709
|
-
'
|
|
709
|
+
'VITE_SUPABASE_PUBLISHABLE_KEY',
|
|
710
710
|
];
|
|
711
711
|
|
|
712
712
|
const warnings = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jmruthers/pace-core",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.190",
|
|
4
4
|
"description": "Clean, modern React component library with Tailwind v4 styling and native utilities",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -155,7 +155,6 @@
|
|
|
155
155
|
"clean": "rimraf dist",
|
|
156
156
|
"_comment_test": "Test suite with various configurations",
|
|
157
157
|
"test": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=128\" vitest run --config ../../vitest.config.ts",
|
|
158
|
-
"test:memory-optimized": "node ../../scripts/run-tests-memory-optimized.js",
|
|
159
158
|
"test:watch": "vitest --watch --config ../../vitest.config.ts",
|
|
160
159
|
"test:coverage": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=128\" vitest run --coverage --config ../../vitest.config.ts --reporter=dot",
|
|
161
160
|
"test:ui": "vitest --ui --config ../../vitest.config.ts",
|
|
@@ -200,7 +199,6 @@
|
|
|
200
199
|
"@radix-ui/react-checkbox": "^1.0.0",
|
|
201
200
|
"@radix-ui/react-dialog": "^1.0.0",
|
|
202
201
|
"@radix-ui/react-label": "^2.0.0",
|
|
203
|
-
"@radix-ui/react-progress": "^1.0.0",
|
|
204
202
|
"@radix-ui/react-slot": "^1.0.0",
|
|
205
203
|
"@radix-ui/react-switch": "^1.1.0",
|
|
206
204
|
"@radix-ui/react-tabs": "^1.0.0",
|
|
@@ -567,7 +567,7 @@ function scanFile(filePath, manifest) {
|
|
|
567
567
|
// - Using in createClient
|
|
568
568
|
// - Comments/documentation
|
|
569
569
|
const supabaseUrlPattern = /(SUPABASE_URL|VITE_SUPABASE_URL|NEXT_PUBLIC_SUPABASE_URL|REACT_APP_SUPABASE_URL)/g;
|
|
570
|
-
const supabaseKeyPattern = /(SUPABASE_ANON_KEY|
|
|
570
|
+
const supabaseKeyPattern = /(SUPABASE_ANON_KEY|VITE_SUPABASE_PUBLISHABLE_KEY|NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY|REACT_APP_SUPABASE_PUBLISHABLE_KEY)/g;
|
|
571
571
|
const urlMatches = content.match(supabaseUrlPattern);
|
|
572
572
|
const keyMatches = content.match(supabaseKeyPattern);
|
|
573
573
|
|
|
@@ -213,7 +213,7 @@ function scanFile(filePath, manifest) {
|
|
|
213
213
|
|
|
214
214
|
// Check for Supabase URL/key configuration in multiple places
|
|
215
215
|
const supabaseUrlPattern = /(SUPABASE_URL|VITE_SUPABASE_URL|NEXT_PUBLIC_SUPABASE_URL|REACT_APP_SUPABASE_URL)/g;
|
|
216
|
-
const supabaseKeyPattern = /(SUPABASE_ANON_KEY|
|
|
216
|
+
const supabaseKeyPattern = /(SUPABASE_ANON_KEY|VITE_SUPABASE_PUBLISHABLE_KEY|NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY|REACT_APP_SUPABASE_PUBLISHABLE_KEY)/g;
|
|
217
217
|
const urlMatches = content.match(supabaseUrlPattern);
|
|
218
218
|
const keyMatches = content.match(supabaseKeyPattern);
|
|
219
219
|
|