Improve project reset#581
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAnalytics data-deletion preview and delete paths were added across backend and web app. Project settings now uses a dedicated delete-data modal, with updated proxy routing, action handling, and locale strings. The shared tab error boundary now resets on key changes and logs caught errors. ChangesAnalytics Deletion Flow
Shared Tab Error Boundary
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
web/app/pages/Project/View/components/TabErrorBoundary.tsx (1)
42-53: 📐 Maintainability & Code Quality | 🔵 TrivialForward caught errors to your monitoring pipeline.
Although React 19 logs caught errors to
console.errorby default, these are not automatically forwarded to production error tracking services. To ensure tab-load failures are observable in your telemetry, implementcomponentDidCatch(error, info)to send error and component stack details to your monitoring provider.Code example
// Add alongside getDerivedStateFromError componentDidCatch(error: Error, info: React.ErrorInfo) { // Example: logErrorToMonitoring(error, info) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/app/pages/Project/View/components/TabErrorBoundary.tsx` around lines 42 - 53, The TabErrorBoundary currently only sets error state via getDerivedStateFromError, so caught tab-load failures are not forwarded to monitoring. Add componentDidCatch(error, info) to TabErrorBoundary and send the error plus React.ErrorInfo component stack to your telemetry/monitoring provider alongside the existing TabErrorBoundary state handling.backend/apps/cloud/src/analytics/dto/data-deletion.dto.ts (1)
48-57: 🔒 Security & Privacy | 🔵 TrivialRecommended: Add
@IsInconstraint fortypesThe service currently filters invalid types and throws a generic error if none remain, preventing unsafe queries, but DTO-level validation offers better developer experience by rejecting invalid inputs immediately.
`@ApiProperty`({ required: false, type: [String], description: "Event types to delete. Any of: 'pageview', 'custom_event', 'error', 'performance', 'captcha'.", }) `@IsOptional`() `@IsArray`() + `@IsString`({ each: true }) + `@IsIn`(['pageview', 'custom_event', 'error', 'performance', 'captcha'], { each: true }) types?: string[]🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/apps/cloud/src/analytics/dto/data-deletion.dto.ts` around lines 48 - 57, Add DTO-level validation for the data-deletion request types. In data-deletion.dto.ts, update the DataDeletionDto.types field to validate each entry against the allowed event names using an `@IsIn` constraint alongside the existing `@IsOptional`, `@IsArray`, and `@IsString` decorators. Keep the allowed values aligned with the service’s accepted types so invalid inputs are rejected during validation instead of only being filtered later.backend/apps/cloud/src/analytics/analytics.service.ts (1)
1826-1846: 🩺 Stability & Availability | 🔵 TrivialReset completes asynchronously — consider waiting for the mutation.
clickhouse.command(ALTER TABLE ... DELETE ...)submits an async mutation and resolves immediately, so this method returns (and the UI reports success) while rows are still being removed in the background.deleteSessionReplayusesclickhouse_settings: { mutations_sync: '2' }for exactly this reason. If a user expects the project to be empty right after a reset, consider addingmutations_synchere (accepting the longer request time) or surfacing that deletion is in progress.Please confirm the intended UX: is eventual (background) deletion acceptable for this reset flow, or should the request block until the mutation finishes?
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/apps/cloud/src/analytics/analytics.service.ts` around lines 1826 - 1846, The reset flow in analytics.service’s delete/reset mutation path is still asynchronous because the clickhouse.command ALTER TABLE DELETE calls return before the mutation finishes, so the method can report success too early. Update the command execution in this reset logic to wait for mutation completion the same way deleteSessionReplay does, by using the appropriate clickhouse settings or equivalent synchronous mutation handling on the clickhouse.command calls. If background deletion is intended instead, make that behavior explicit in the UX; otherwise block until both the events and error_statuses deletions have finished.backend/apps/community/src/analytics/dto/data-deletion.dto.ts (1)
31-57: 🩺 Stability & Availability | 🔵 TrivialReplace
@IsStringwith stricter validation forfrom/toand constraintypesCurrently
fromandtoonly validate string presence, allowing "Invalid Date" to propagate todayjsand trigger a server error. Update these to use@IsDateStringcombined with@Length(10, 10)to ensure only strictYYYY-MM-DDformats are accepted, preventing malformed dates from reaching the service layer. Additionally, add a constraint (e.g.,@IsIn) ontypesto reject unsupported event names before they hit the allowlist logic.import { IsDateString, IsEnum, IsIn, Length } from 'class-validator'; // ... `@ApiProperty`({ ... }) // existing config `@IsOptional`() `@IsDateString`() // Accepts ISO 8601 `@Length`(10, 10) // Enforces YYYY-MM-DD strictly from?: string; `@ApiProperty`({ ... }) // existing config `@IsOptional`() `@IsDateString`() `@Length`(10, 10) to?: string; `@ApiProperty`({ ... }) // existing config `@IsOptional`() `@IsArray`() `@IsString`({ each: true }) `@IsIn`(['pageview', 'custom_event', 'error', 'performance', 'captcha'], { each: true }) types?: string[];🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/apps/community/src/analytics/dto/data-deletion.dto.ts` around lines 31 - 57, The DataDeletionDto validation is too permissive for the date range and event types, letting malformed inputs reach the service layer. In the DataDeletionDto class, replace the loose `from`/`to` string checks with stricter date validation using `IsDateString` plus `Length(10, 10)` so only `YYYY-MM-DD` values are accepted, and keep them optional. Also tighten `types` in the same DTO by adding an allowlist constraint such as `IsIn` with the supported event names, alongside the existing array validation, so unsupported values are rejected before the allowlist logic runs.backend/apps/community/src/analytics/analytics.controller.ts (1)
1147-1165: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueOptional: add a deletion log entry for parity with cloud.
The cloud
deleteDatalogs{ uid, pid, types }before deleting, which is useful for auditing destructive actions. The community variant performs the same deletion without any log line.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/apps/community/src/analytics/analytics.controller.ts` around lines 1147 - 1165, The community AnalyticsController.deleteData flow currently performs the deletion without an audit log, unlike the cloud variant. Add a log entry in deleteData before calling analyticsService.deleteData, using the same relevant fields for parity and auditing (uid, pid, types), and place it near the existing checkManageAccess/deleteData calls so the intent is easy to find even if lines move.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/apps/cloud/src/analytics/analytics.service.ts`:
- Around line 1807-1824: The date-deletion flow in analytics.service.ts drops a
one-sided range because hasRange only checks for both from and to, so a partial
input can remove the created bound entirely. Update the date handling around the
deletion/preview logic to either reject half-specified ranges up front or
convert them into an open-ended range, and make sure the code path using
dateCondition, params.from/params.to, and getDataDeletionPreview stays
consistent so deletion never runs unscoped.
In `@web/app/pages/Project/Settings/ProjectSettings.tsx`:
- Line 1546: The <DangerZone /> prop named setResetting is misleading because it
is used as a boolean state value, not a setter function. Rename the prop to
isResetting in DangerZoneProps and update the <DangerZone /> usage in
ProjectSettings so the boolean state is passed and consumed consistently,
including the loading and click-guard logic tied to that prop.
In `@web/app/pages/Project/View/components/TabErrorBoundary.tsx`:
- Around line 51-61: The TabErrorBoundary currently sets hasError to true in
getDerivedStateFromError but never clears it, so the fallback can get stuck
after recoverable updates. Update TabErrorBoundary to reset its error state when
the wrapped content changes, using a caller-provided resetKey or an equivalent
change-detection path tied to the children/titleKey props. Make the reset logic
live in TabErrorBoundary so render can return the fresh children again after the
underlying tab data changes.
---
Nitpick comments:
In `@backend/apps/cloud/src/analytics/analytics.service.ts`:
- Around line 1826-1846: The reset flow in analytics.service’s delete/reset
mutation path is still asynchronous because the clickhouse.command ALTER TABLE
DELETE calls return before the mutation finishes, so the method can report
success too early. Update the command execution in this reset logic to wait for
mutation completion the same way deleteSessionReplay does, by using the
appropriate clickhouse settings or equivalent synchronous mutation handling on
the clickhouse.command calls. If background deletion is intended instead, make
that behavior explicit in the UX; otherwise block until both the events and
error_statuses deletions have finished.
In `@backend/apps/cloud/src/analytics/dto/data-deletion.dto.ts`:
- Around line 48-57: Add DTO-level validation for the data-deletion request
types. In data-deletion.dto.ts, update the DataDeletionDto.types field to
validate each entry against the allowed event names using an `@IsIn` constraint
alongside the existing `@IsOptional`, `@IsArray`, and `@IsString` decorators. Keep the
allowed values aligned with the service’s accepted types so invalid inputs are
rejected during validation instead of only being filtered later.
In `@backend/apps/community/src/analytics/analytics.controller.ts`:
- Around line 1147-1165: The community AnalyticsController.deleteData flow
currently performs the deletion without an audit log, unlike the cloud variant.
Add a log entry in deleteData before calling analyticsService.deleteData, using
the same relevant fields for parity and auditing (uid, pid, types), and place it
near the existing checkManageAccess/deleteData calls so the intent is easy to
find even if lines move.
In `@backend/apps/community/src/analytics/dto/data-deletion.dto.ts`:
- Around line 31-57: The DataDeletionDto validation is too permissive for the
date range and event types, letting malformed inputs reach the service layer. In
the DataDeletionDto class, replace the loose `from`/`to` string checks with
stricter date validation using `IsDateString` plus `Length(10, 10)` so only
`YYYY-MM-DD` values are accepted, and keep them optional. Also tighten `types`
in the same DTO by adding an allowlist constraint such as `IsIn` with the
supported event names, alongside the existing array validation, so unsupported
values are rejected before the allowlist logic runs.
In `@web/app/pages/Project/View/components/TabErrorBoundary.tsx`:
- Around line 42-53: The TabErrorBoundary currently only sets error state via
getDerivedStateFromError, so caught tab-load failures are not forwarded to
monitoring. Add componentDidCatch(error, info) to TabErrorBoundary and send the
error plus React.ErrorInfo component stack to your telemetry/monitoring provider
alongside the existing TabErrorBoundary state handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: be42afc5-7f50-4163-91f3-7a3c4bd2df97
📒 Files selected for processing (23)
backend/apps/cloud/src/analytics/analytics.controller.tsbackend/apps/cloud/src/analytics/analytics.service.tsbackend/apps/cloud/src/analytics/dto/data-deletion.dto.tsbackend/apps/community/src/analytics/analytics.controller.tsbackend/apps/community/src/analytics/analytics.service.tsbackend/apps/community/src/analytics/dto/data-deletion.dto.tsweb/app/api/api.server.tsweb/app/hooks/useAnalyticsProxy.tsweb/app/pages/Project/Settings/ProjectSettings.tsxweb/app/pages/Project/Settings/components/DeleteDataModal.tsxweb/app/pages/Project/View/components/FilterRowsEditor.tsxweb/app/pages/Project/View/components/TabErrorBoundary.tsxweb/app/pages/Project/tabs/Errors/ErrorsView.tsxweb/app/pages/Project/tabs/Funnels/FunnelsView.tsxweb/app/pages/Project/tabs/Performance/PerformanceView.tsxweb/app/pages/Project/tabs/Replays/ReplaysView.tsxweb/app/pages/Project/tabs/SEO/SEOView.tsxweb/app/pages/Project/tabs/Sessions/SessionsView.tsxweb/app/pages/Project/tabs/Traffic/TrafficView.tsxweb/app/providers/CurrentProjectProvider.tsxweb/app/routes/api.analytics.tsweb/app/routes/projects.settings.$id.tsxweb/public/locales/en.json
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/apps/cloud/src/analytics/dto/data-deletion.dto.ts`:
- Around line 66-70: The DataDeletionDto currently leaves types optional, which
allows POST /data-deletion to silently fall back to a partial delete set. Update
the DTO and the controller/service flow so the destructive path explicitly
requires a delete-type selection, or split the request shapes into separate
preview and delete DTOs. Make sure DataDeletionDto and the handler that applies
the default types no longer permit omission to trigger an incomplete reset.
In `@web/app/pages/Project/View/components/TabErrorBoundary.tsx`:
- Around line 65-83: The reset logic in
TabErrorBoundary.getDerivedStateFromProps is too broad because it uses children
and titleKey as reset signals. Update the reset condition so the boundary only
clears hasError when resetKey changes, and stop storing/comparing children and
titleKey in state for recovery. Keep the fallback using this.props.titleKey, and
preserve the existing resetKey-based state update behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d2435d5f-58c1-4cd2-8eb2-d48c72bb17ce
📒 Files selected for processing (8)
backend/apps/cloud/src/analytics/analytics.service.tsbackend/apps/cloud/src/analytics/dto/data-deletion.dto.tsbackend/apps/community/src/analytics/analytics.controller.tsbackend/apps/community/src/analytics/analytics.service.tsbackend/apps/community/src/analytics/dto/data-deletion.dto.tsweb/app/pages/Project/Settings/ProjectSettings.tsxweb/app/pages/Project/Settings/tabs/DangerZone.tsxweb/app/pages/Project/View/components/TabErrorBoundary.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
- backend/apps/community/src/analytics/dto/data-deletion.dto.ts
- backend/apps/community/src/analytics/analytics.controller.ts
- web/app/pages/Project/Settings/ProjectSettings.tsx
- backend/apps/community/src/analytics/analytics.service.ts
- backend/apps/cloud/src/analytics/analytics.service.ts
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
web/app/pages/Project/View/components/TabErrorBoundary.tsx (1)
32-32: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winMake
resetKeymandatory or wire it from the tab wrappers.This recovery path is inert for the current callers shown in context:
web/app/pages/Project/tabs/Performance/PerformanceView.tsx:121andweb/app/pages/Project/tabs/Traffic/TrafficView.tsx:218still render<TabErrorBoundary ...>withoutresetKey. OncehasErrorflips totrue, bothprops.resetKeyandstate.resetKeystayundefined, so Line 65 keeps returningnulland the tab remains stuck on the fallback until a full reload.Suggested contract change in this file
interface TabErrorBoundaryProps { children: ReactNode /** Translation key for the title, e.g. `dashboard.failedToLoadTraffic`. Falls back to a generic title. */ titleKey?: string - resetKey?: unknown + resetKey: unknown }Also applies to: 61-72
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/app/pages/Project/View/components/TabErrorBoundary.tsx` at line 32, The TabErrorBoundary recovery path is inert because resetKey is optional and the current callers never pass it, so the fallback can stay stuck once hasError is set. Make resetKey required in TabErrorBoundary and wire it through the tab wrappers (such as PerformanceView and TrafficView) by passing a stable tab-specific key into the boundary so the reset logic in the component can actually clear the error state. Ensure the boundary’s reset handling uses that prop consistently in TabErrorBoundary.backend/apps/cloud/src/analytics/analytics.controller.ts (1)
2887-2924: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winThrottle data-deletion preview and delete requests.
These routes reach expensive ClickHouse preview queries and synchronous
ALTER TABLE ... DELETEmutations. Add per-user/per-projectcheckRateLimitcalls before invoking the service to avoid mutation/query floods from a manager account or compromised token.Suggested shape
async getDataDeletionPreview( `@Body`() body: DataDeletionPreviewDto, `@CurrentUserId`() uid: string, + `@Ip`() requestIp: string, ) { + await checkRateLimit(uid || requestIp || body.pid, 'data-deletion-preview-user', 30, 60) + await checkRateLimit(body.pid, 'data-deletion-preview-project', 60, 60) await this.analyticsService.checkManageAccess(body.pid, uid) async deleteData( `@Body`() body: DataDeletionDto, `@CurrentUserId`() uid: string, + `@Ip`() requestIp: string, ) { + await checkRateLimit(uid || requestIp || body.pid, 'data-deletion-user', 3, 3600) + await checkRateLimit(body.pid, 'data-deletion-project', 10, 3600) await this.analyticsService.checkManageAccess(body.pid, uid)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/apps/cloud/src/analytics/analytics.controller.ts` around lines 2887 - 2924, Throttle the expensive data-deletion endpoints by adding per-user/per-project rate limiting before the service calls in getDataDeletionPreview and deleteData. Use the existing analyticsService.checkRateLimit (or the same rate-limit helper used elsewhere in this controller) with uid and body.pid so both the ClickHouse preview query and the synchronous delete mutation are protected. Place the check after checkManageAccess and before getDataDeletionPreview/deleteData, and keep the rest of the controller flow unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@backend/apps/cloud/src/analytics/analytics.controller.ts`:
- Around line 2887-2924: Throttle the expensive data-deletion endpoints by
adding per-user/per-project rate limiting before the service calls in
getDataDeletionPreview and deleteData. Use the existing
analyticsService.checkRateLimit (or the same rate-limit helper used elsewhere in
this controller) with uid and body.pid so both the ClickHouse preview query and
the synchronous delete mutation are protected. Place the check after
checkManageAccess and before getDataDeletionPreview/deleteData, and keep the
rest of the controller flow unchanged.
In `@web/app/pages/Project/View/components/TabErrorBoundary.tsx`:
- Line 32: The TabErrorBoundary recovery path is inert because resetKey is
optional and the current callers never pass it, so the fallback can stay stuck
once hasError is set. Make resetKey required in TabErrorBoundary and wire it
through the tab wrappers (such as PerformanceView and TrafficView) by passing a
stable tab-specific key into the boundary so the reset logic in the component
can actually clear the error state. Ensure the boundary’s reset handling uses
that prop consistently in TabErrorBoundary.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6a460785-04d5-4d98-a374-028db207bf7f
📒 Files selected for processing (3)
backend/apps/cloud/src/analytics/analytics.controller.tsbackend/apps/cloud/src/analytics/dto/data-deletion.dto.tsweb/app/pages/Project/View/components/TabErrorBoundary.tsx
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/app/pages/Project/View/components/TabErrorBoundary.tsx (1)
61-73: 🩺 Stability & Availability | 🟠 MajorWire
resetKeyto tab refresh inputs, not a hard-coded tab name.TabErrorBoundaryonly resets whenresetKeychanges, but the current callers pass fixed literals ('traffic','performance','funnels','replays','seo','sessions','errors'). That means a recoverable revalidation/filter/date-range update inside the same tab will not clearhasError, so the fallback can stay stuck until a full reload. Use a value that changes with the tab’s reload/recovery path (for example, period/date range/filter or a revalidation token).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/app/pages/Project/View/components/TabErrorBoundary.tsx` around lines 61 - 73, The `TabErrorBoundary` reset behavior is too static because callers pass hard-coded tab names as `resetKey`, so `getDerivedStateFromProps` never clears `hasError` when the tab’s data refreshes. Update the callers of `TabErrorBoundary` to pass a `resetKey` that changes with the tab’s recovery inputs, such as the current date range, filters, period, or a revalidation token, so the boundary resets whenever `resetKey` changes instead of only when switching tabs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@web/app/pages/Project/View/components/TabErrorBoundary.tsx`:
- Around line 61-73: The `TabErrorBoundary` reset behavior is too static because
callers pass hard-coded tab names as `resetKey`, so `getDerivedStateFromProps`
never clears `hasError` when the tab’s data refreshes. Update the callers of
`TabErrorBoundary` to pass a `resetKey` that changes with the tab’s recovery
inputs, such as the current date range, filters, period, or a revalidation
token, so the boundary resets whenever `resetKey` changes instead of only when
switching tabs.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 20efe754-5e86-4fe7-9412-8002a5629c0f
📒 Files selected for processing (9)
backend/apps/cloud/src/analytics/analytics.controller.tsweb/app/pages/Project/View/components/TabErrorBoundary.tsxweb/app/pages/Project/tabs/Errors/ErrorsView.tsxweb/app/pages/Project/tabs/Funnels/FunnelsView.tsxweb/app/pages/Project/tabs/Performance/PerformanceView.tsxweb/app/pages/Project/tabs/Replays/ReplaysView.tsxweb/app/pages/Project/tabs/SEO/SEOView.tsxweb/app/pages/Project/tabs/Sessions/SessionsView.tsxweb/app/pages/Project/tabs/Traffic/TrafficView.tsx
✅ Files skipped from review due to trivial changes (1)
- web/app/pages/Project/tabs/Sessions/SessionsView.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- backend/apps/cloud/src/analytics/analytics.controller.ts
Changes
If applicable, please describe what changes were made in this pull request.
Community Edition support
Database migrations
Documentation
Summary by CodeRabbit