Skip to content

Comments

feat: add self-hosting improvements and rule import/export#1237

Merged
elie222 merged 22 commits intomainfrom
pr-1139
Jan 8, 2026
Merged

feat: add self-hosting improvements and rule import/export#1237
elie222 merged 22 commits intomainfrom
pr-1139

Conversation

@elie222
Copy link
Owner

@elie222 elie222 commented Jan 8, 2026

Generated description

Below is a concise technical summary of the changes proposed in this PR:

graph LR
move_folder_("move_folder"):::modified
EmailProvider_("EmailProvider"):::modified
lazyUpdateActionFolderId_("lazyUpdateActionFolderId"):::added
PRISMA_("PRISMA"):::modified
importRulesAction_("importRulesAction"):::added
importRulesBody_("importRulesBody"):::added
resolveActionLabels_("resolveActionLabels"):::modified
getActionsFromCategoryAction_("getActionsFromCategoryAction"):::modified
move_folder_ -- "Uses new provider method to resolve folderName to ID." --> EmailProvider_
move_folder_ -- "Saves resolved folderId to DB for future runs." --> lazyUpdateActionFolderId_
lazyUpdateActionFolderId_ -- "Updates actions by folderName, setting folderId via Prisma." --> PRISMA_
importRulesAction_ -- "Creates/updates rules and actions in DB via Prisma." --> PRISMA_
importRulesAction_ -- "Validates imported JSON against new importRulesBody schema." --> importRulesBody_
resolveActionLabels_ -- "Resolves folderName to ID using provider's new method." --> EmailProvider_
getActionsFromCategoryAction_ -- "Resolves onboarding ruleName to folder ID via provider." --> EmailProvider_
classDef added stroke:#15AA7A
classDef removed stroke:#CD5270
classDef modified stroke:#EDAC4C
linkStyle default stroke:#CBD5E1,font-size:13px
Loading

Introduces a comprehensive rule import and export system, allowing users to backup, restore, and share their email automation rules, alongside significant refactoring of folder ID resolution for improved rule action reliability. Enhances the application's self-hosting capabilities by enabling feature flags to be configured directly via environment variables, providing greater deployment flexibility.

TopicDetails
Rule Management Implement the ability to import and export user-defined email rules as JSON files, providing a robust mechanism for backup, restoration, and sharing of rule configurations. This includes adding a new settings tab, backend logic for processing imported rules (creating or updating existing ones), and defining validation schemas for the imported data. Additionally, refactor the email provider interface and rule action logic to use a generic getOrCreateFolderIdByName method, improving consistency and reliability for folder-related actions across different email services and AI-driven rule processing.
Modified files (14)
  • .claude/commands/write-tests.md
  • apps/web/__tests__/mocks/email-provider.mock.ts
  • apps/web/app/(app)/[emailAccountId]/assistant/AssistantTabs.tsx
  • apps/web/app/(app)/[emailAccountId]/assistant/settings/RuleImportExportSetting.tsx
  • apps/web/app/(app)/[emailAccountId]/settings/ResetAnalyticsSection.tsx
  • apps/web/app/(app)/[emailAccountId]/settings/page.tsx
  • apps/web/utils/__mocks__/email-provider.ts
  • apps/web/utils/actions/rule.ts
  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/ai/actions.ts
  • apps/web/utils/email/google.ts
  • apps/web/utils/email/microsoft.ts
  • apps/web/utils/email/types.ts
  • apps/web/utils/rule/rule.ts
Latest Contributors(1)
UserCommitDate
elie222add-write-tests-commandJanuary 08, 2026
Self-Hosting Config Enhance self-hosting capabilities by allowing various feature flags, such as NEXT_PUBLIC_CLEANER_ENABLED, to be configured via environment variables. This involves updating the application's environment variable schema, modifying feature flag hooks to prioritize environment variables, and adjusting Docker build and startup scripts to correctly pass and apply these variables during deployment, ensuring greater control and flexibility for self-hosted instances.
Modified files (5)
  • apps/web/env.ts
  • apps/web/hooks/useFeatureFlags.ts
  • docker/Dockerfile.prod
  • docker/scripts/start.sh
  • turbo.json
Latest Contributors(2)
UserCommitDate
elie222chore-rename-LOG_ZOD_E...January 08, 2026
eduardoleliss@gmail.comCopilot-deployment-ins...November 25, 2025
This pull request is reviewed by Baz. Review like a pro on (Baz).

rsnodgrass and others added 18 commits December 30, 2025 01:15
- Add Import/Export buttons to Rules UI for backup and restore
- Import is idempotent: matches by systemType or name, updates existing
- Add runtime placeholder support for feature flags in Docker:
  - NEXT_PUBLIC_CLEANER_ENABLED
  - NEXT_PUBLIC_MEETING_BRIEFS_ENABLED
  - NEXT_PUBLIC_INTEGRATIONS_ENABLED
  - NEXT_PUBLIC_DIGEST_ENABLED
- Change useCleanerEnabled() to use env var instead of PostHog flag
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
- Create RuleImportExportSetting component in assistant/settings
- Add import/export to SettingsTab at the bottom
- Remove import/export buttons from Rules table header
- Reduces UI clutter in the main rules view
…p field

- Add categoryFilterType to create and update operations in importRulesAction
- Remove group field from export since groupId is not persisted on import
- Add comment explaining why group associations are not exported
The import/export rules feature was added but the Settings tab
wasn't visible in the Assistant tabs navigation.
Export and import assistant rules as JSON for backup, sharing, or
migrating between environments.

Features:
- Export all rules to JSON file with one click
- Import rules from JSON with validation
- Idempotent import: matches by systemType or name, updates existing rules
- Validates imported rules have at least one condition
- Preserves categoryFilterType, url, and delayInMinutes fields

UI:
- Added Settings tab to Assistant with Import/Export section
- Clean separation from main Rules table

Files:
- RuleImportExportSetting.tsx: Import/export UI component
- rule.ts: Server actions for import/export
- rule.validation.ts: Zod schemas for validation

Guided-by: Sage-Ox <ox@sageox.ai>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Address code review feedback for rule import/export:

- move_folder action now resolves folderName to folderId at runtime,
  matching the pattern used by label action. This ensures imported rules
  with folder names work correctly even without pre-resolved IDs.

- importedAction validation now uses validateLabelNameBasic to enforce
  Gmail label name rules (length limits, character restrictions, reserved
  names) during import, preventing invalid labels from being imported.

- Added validation for FORWARD (requires to), CALL_WEBHOOK (requires url),
  and MOVE_FOLDER (requires folderName) actions during import.
# Conflicts:
#	apps/web/utils/actions/rule.validation.ts
…vider-agnostic

Address code review feedback from @coderabbitai:

- Add template variable validation for folderName in move_folder action,
  matching the pattern used by the label action (lines 107-110)

- Rename getOrCreateOutlookFolderIdByName to getOrCreateFolderIdByName
  in the EmailProvider interface for provider-agnostic naming. The
  internal Outlook implementation remains unchanged.
@vercel
Copy link

vercel bot commented Jan 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
inbox-zero Ready Ready Preview Jan 8, 2026 4:04pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 8, 2026

Warning

Rate limit exceeded

@elie222 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 12 minutes and 32 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 777d094 and 441ca10.

📒 Files selected for processing (2)
  • apps/web/utils/actions/rule.ts
  • turbo.json
📝 Walkthrough

Walkthrough

Introduces rule import/export UI and server action, renames provider folder helper from getOrCreateOutlookFolderIdByName → getOrCreateFolderIdByName across types, providers, mocks and call sites, extends move_folder to accept folderName with lazy resolution, adds a Settings tab, and adds feature-flag env overrides and Docker placeholders.

Changes

Cohort / File(s) Summary
Email provider interface & implementations
apps/web/utils/email/types.ts, apps/web/utils/email/google.ts, apps/web/utils/email/microsoft.ts
Renamed getOrCreateOutlookFolderIdByNamegetOrCreateFolderIdByName in the EmailProvider interface and provider classes; adjusted logs/calls.
Mocks
apps/web/__tests__/mocks/email-provider.mock.ts, apps/web/utils/__mocks__/email-provider.ts
Updated test mocks to expose getOrCreateFolderIdByName (preserves return values).
Move-folder / AI action changes
apps/web/utils/ai/actions.ts, apps/web/utils/rule/rule.ts
Extended move_folder signature to accept folderName, added resolution flow and lazyUpdateActionFolderId; swapped calls to the renamed folder helper.
Rule import/export feature
apps/web/app/(app)/[emailAccountId]/assistant/settings/RuleImportExportSetting.tsx, apps/web/utils/actions/rule.ts, apps/web/utils/actions/rule.validation.ts
Added UI for import/export, new importRulesAction (upsert/duplicate detection) and comprehensive import validation schemas/types.
Assistant UI & settings page
apps/web/app/(app)/[emailAccountId]/assistant/AssistantTabs.tsx, apps/web/app/(app)/[emailAccountId]/settings/page.tsx
Added Settings tab to Assistant and inserted RuleImportExportSetting into settings layout; updated headings and layout to use SettingCard.
Settings section refactor
apps/web/app/(app)/[emailAccountId]/settings/ResetAnalyticsSection.tsx
Replaced FormSection layout with SettingCard; preserved reset action and toast behavior.
Feature flag env & hook
apps/web/env.ts, apps/web/hooks/useFeatureFlags.ts
Added NEXT_PUBLIC_CLEANER_ENABLED to client env and made useCleanerEnabled honor the env override.
Docker & start script
docker/Dockerfile.prod, docker/scripts/start.sh
Added ARG/ENV placeholders and start.sh replacements for feature-flag env vars (CLEANER, MEETING_BRIEFS, INTEGRATIONS, DIGEST).
Docs / misc
.claude/commands/write-tests.md
Minor editorial change renaming a section and adding a row for “Simple Zod schemas.”

Sequence Diagrams

sequenceDiagram
    participant User
    participant UI as Rule Import/Export Component
    participant Hooks as useRules/useAccount
    participant Action as importRulesAction
    participant DB as Database

    User->>UI: Upload JSON / Click Export
    UI->>UI: Parse & validate JSON (zod)
    UI->>Action: importRulesAction(rules, emailAccountId)
    Action->>DB: Query existing rules (by name/systemType)
    Action->>DB: Create or update rules (upsert)
    Action-->>UI: Return {created, updated, skipped}
    UI->>Hooks: mutate() to refresh rules
    UI-->>User: Show toast with counts
Loading
sequenceDiagram
    participant AIAction as move_folder
    participant EmailProvider
    participant FolderHelper
    participant DB as Database

    AIAction->>AIAction: Check folderId
    alt no folderId but folderName provided
        AIAction->>EmailProvider: getOrCreateFolderIdByName(folderName)
        EmailProvider->>FolderHelper: Resolve folderName
        FolderHelper-->>EmailProvider: folderId
        EmailProvider-->>AIAction: folderId
        AIAction->>DB: Move thread to folderId
        AIAction->>AIAction: Schedule lazyUpdateActionFolderId (async)
        AIAction->>DB: Update Action record with folderId
    else folderId provided
        AIAction->>DB: Move thread to folderId
    end
    AIAction-->>AIAction: Done
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~55 minutes

Possibly related PRs

Suggested reviewers

  • edulelis
  • baz-reviewer

"🐇
I hopped through folders, renamed a name,
Exported rules dancing, imported the same.
Tabs found their Settings, flags sprouted wings,
Mocks followed suit and the CI softly sings.
Cheers from the rabbit — code carrots and strings!"

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the two main objectives: adding self-hosting improvements (environment variables, Docker configuration) and implementing rule import/export functionality (new component and server action).
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @apps/web/env.ts:
- Line 193: The new feature flag NEXT_PUBLIC_CLEANER_ENABLED is validated in
code but missing from example and build env; add a commented entry "#
NEXT_PUBLIC_CLEANER_ENABLED=true" into the Feature flags section of the
.env.example used by the web app and add the string
"NEXT_PUBLIC_CLEANER_ENABLED" to the tasks.build.env array in turbo.json
alongside the other NEXT_PUBLIC_* feature flags so the variable is available
during builds.
🧹 Nitpick comments (2)
apps/web/app/(app)/[emailAccountId]/assistant/settings/RuleImportExportSetting.tsx (1)

125-141: Add type="button" to prevent unintended form submissions.

Per accessibility guidelines, all button elements should include a type attribute. While these buttons are not inside a form, adding explicit types improves clarity and prevents potential issues if the component is ever used within a form context.

🛠️ Suggested improvement
          <Button
+           type="button"
            size="sm"
            variant="outline"
            onClick={() => fileInputRef.current?.click()}
          >
            <UploadIcon className="mr-2 size-4" />
            Import
          </Button>
          <Button
+           type="button"
            size="sm"
            variant="outline"
            onClick={exportRules}
            disabled={!data?.length}
          >
            <DownloadIcon className="mr-2 size-4" />
            Export
          </Button>
apps/web/utils/actions/rule.validation.ts (1)

360-360: Use z.enum() for categoryFilterType validation.

The field has a finite set of valid values (INCLUDE and EXCLUDE) defined in the Prisma enum CategoryFilterType. Replace z.string().nullish() with z.enum(["INCLUDE", "EXCLUDE"]).nullish() to catch invalid values during import and maintain consistency with similar constrained fields in this file (e.g., conditionalOperator).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/web/utils/actions/rule.ts (1)

1014-1035: Consider adding emailAccountId to the update WHERE clause for defense-in-depth.

While existingRuleId is obtained from a query scoped to the user's emailAccountId, including the ownership check directly in the update statement provides an extra layer of protection against IDOR vulnerabilities.

♻️ Suggested change
           if (existingRuleId) {
             // Update existing rule
             await prisma.rule.update({
-              where: { id: existingRuleId },
+              where: { id: existingRuleId, emailAccountId },
               data: {
                 instructions: rule.instructions,

Based on coding guidelines requiring ownership filters in WHERE clauses.

apps/web/utils/actions/rule.validation.ts (1)

345-379: The group field is validated but ignored during import.

The group field (line 365) is accepted by the schema but the importRulesAction sets groupId: null for all imported rules. Consider either removing it from the schema or documenting that groups are not imported (since they're account-specific).

♻️ Option 1: Remove unused field
     categoryFilterType: z
       .enum([CategoryFilterType.INCLUDE, CategoryFilterType.EXCLUDE])
       .nullish(),
     actions: z.array(importedAction).min(1),
-    group: z.string().nullish(),
   })
♻️ Option 2: Add comment explaining the behavior
     actions: z.array(importedAction).min(1),
+    // Note: group is accepted for export compatibility but not used during import
+    // (groups are account-specific and cannot be transferred)
     group: z.string().nullish(),
   })
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d61d34d and 777d094.

📒 Files selected for processing (2)
  • apps/web/utils/actions/rule.ts
  • apps/web/utils/actions/rule.validation.ts
🧰 Additional context used
📓 Path-based instructions (19)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)

**/*.{ts,tsx}: For API GET requests to server, use the swr package
Use result?.serverError with toastError from @/components/Toast for error handling in async operations

**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls

**/*.{ts,tsx}: For early access feature flags, create hooks using the naming convention use[FeatureName]Enabled that return a boolean from useFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming convention use[FeatureName]Variant that define variant types, use useFeatureFlagVariantKey() with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g., inbox-cleaner, pricing-options-2)
Always define types for A/B test variant flags (e.g., type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting

**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the ! postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Use as const instead of literal types and type annotations
Use either T[] or Array<T> consistently
Initialize each enum member value explicitly
Use export type for types
Use `impo...

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
**/*.validation.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.validation.{ts,tsx}: Define validation schemas using Zod
Use descriptive error messages in validation schemas

Files:

  • apps/web/utils/actions/rule.validation.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)

Always import Prisma enums from @/generated/prisma/enums instead of @/generated/prisma/client to avoid Next.js bundling errors in client components

Import Prisma using the project's centralized utility: import prisma from '@/utils/prisma'

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
apps/web/utils/actions/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

apps/web/utils/actions/**/*.ts: Server actions must be located in apps/web/utils/actions folder
Server action files must start with use server directive

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Import specific lodash functions rather than entire lodash library to minimize bundle size (e.g., import groupBy from 'lodash/groupBy')

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Do not export types/interfaces that are only used within the same file. Export later if needed
Infer types from Zod schemas using z.infer<typeof schema> instead of duplicating as separate interfaces
Centralize types in dedicated type files when shared across multiple files
Use SWR for client-side data fetching with pattern useSWR<GetExampleResponse>("/api/user/example")
Call mutate() after successful mutations or use revalidatePath in server actions for cache invalidation

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/security.mdc)

**/*.ts: ALL database queries MUST be scoped to the authenticated user/account by including user/account filtering in WHERE clauses to prevent unauthorized data access
Always validate that resources belong to the authenticated user before performing operations, using ownership checks in WHERE clauses or relationships
Always validate all input parameters for type, format, and length before using them in database queries
Use SafeError for error responses to prevent information disclosure. Generic error messages should not reveal internal IDs, logic, or resource ownership details
Only return necessary fields in API responses using Prisma's select option. Never expose sensitive data such as password hashes, private keys, or system flags
Prevent Insecure Direct Object References (IDOR) by validating resource ownership before operations. All findUnique/findFirst calls MUST include ownership filters
Prevent mass assignment vulnerabilities by explicitly whitelisting allowed fields in update operations instead of accepting all user-provided data
Prevent privilege escalation by never allowing users to modify system fields, ownership fields, or admin-only attributes through user input
All findMany queries MUST be scoped to the user's data by including appropriate WHERE filters to prevent returning data from other users
Use Prisma relationships for access control by leveraging nested where clauses (e.g., emailAccount: { id: emailAccountId }) to validate ownership

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
apps/web/utils/actions/*.validation.ts

📄 CodeRabbit inference engine (.cursor/rules/server-actions.mdc)

apps/web/utils/actions/*.validation.ts: Create separate validation files for server actions using the naming convention apps/web/utils/actions/NAME.validation.ts containing Zod schemas and inferred types
Define input validation schemas using Zod in .validation.ts files and export both the schema and its inferred TypeScript type

Files:

  • apps/web/utils/actions/rule.validation.ts
apps/web/utils/actions/*.ts

📄 CodeRabbit inference engine (.cursor/rules/server-actions.mdc)

apps/web/utils/actions/*.ts: Create corresponding server action implementation files using the naming convention apps/web/utils/actions/NAME.ts with 'use server' directive
Use 'use server' directive at the top of server action implementation files
Implement all server actions using the next-safe-action library with actionClient, actionClientUser, or adminActionClient for type safety and validation
Use actionClientUser when only authenticated user context (userId) is needed
Use actionClient when both authenticated user context and a specific emailAccountId are needed, with emailAccountId bound when calling from the client
Use adminActionClient for actions restricted to admin users
Add metadata with a meaningful action name using .metadata({ name: "actionName" }) for Sentry instrumentation and monitoring
Use .schema() method with Zod validation schemas from corresponding .validation.ts files in next-safe-action configuration
Access context (userId, emailAccountId, etc.) via the ctx object parameter in the .action() handler
Use revalidatePath or revalidateTag from 'next/cache' within server action handlers when mutations modify data displayed elsewhere

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)

**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Use next/image package for images
For API GET requests to server, use the swr package with hooks like useSWR to fetch data
For text inputs, use the Input component with registerProps for form integration and error handling

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
**/*.{tsx,ts,css}

📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)

Implement responsive design with Tailwind CSS using a mobile-first approach

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use accessKey attribute on any HTML element
Don't set aria-hidden="true" on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like <marquee> or <blink>
Only use the scope prop on <th> elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assign tabIndex to non-interactive HTML elements
Don't use positive integers for tabIndex property
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include a title element for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
Assign tabIndex to non-interactive HTML elements with aria-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include a type attribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden with aria-hidden)
Always include a lang attribute on the html element
Always include a title attribute for iframe elements
Accompany onClick with at least one of: onKeyUp, onKeyDown, or onKeyPress
Accompany onMouseOver/onMouseOut with onFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
!(pages/_document).{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

Don't use the next/head module in pages/_document.js on Next.js projects

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)

**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g., import groupBy from 'lodash/groupBy')

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
**/{utils,helpers,lib}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)

Logger should be passed as a parameter to helper functions instead of creating their own logger instances

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
apps/web/utils/actions/**/*.validation.ts

📄 CodeRabbit inference engine (.cursor/rules/fullstack-workflow.mdc)

Create Zod validation schemas at apps/web/utils/actions/{feature}.validation.ts for all server action input validation

Files:

  • apps/web/utils/actions/rule.validation.ts
apps/web/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx,js,jsx}: Use @/ path aliases for imports from project root instead of relative paths
Use proper error handling with try/catch blocks
Add helper functions to the bottom of files, not the top
All imports go at the top of files, no mid-file dynamic imports
Use NEXT_PUBLIC_ prefix for client-side environment variables

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
apps/web/**/utils/actions/**/*.ts

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

Use server actions with next-safe-action for all mutations (create/update/delete operations), not POST API routes

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
apps/web/**/utils/actions/**/*.validation.ts

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

Create validation schemas with Zod in separate validation files (e.g., example.validation.ts)

Files:

  • apps/web/utils/actions/rule.validation.ts
apps/web/utils/actions/!(*.validation).ts

📄 CodeRabbit inference engine (.cursor/rules/fullstack-workflow.mdc)

apps/web/utils/actions/!(*.validation).ts: Use next-safe-action for all server actions with actionClient, .metadata(), .inputSchema(), and .action() chain pattern
Add 'use server' directive at the top of all server action files

Files:

  • apps/web/utils/actions/rule.ts
🧠 Learnings (16)
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.validation.ts : Create separate validation files for server actions using the naming convention `apps/web/utils/actions/NAME.validation.ts` containing Zod schemas and inferred types

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.validation.ts : Define input validation schemas using Zod in `.validation.ts` files and export both the schema and its inferred TypeScript type

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2026-01-08T15:09:06.726Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2026-01-08T15:09:06.726Z
Learning: Applies to apps/web/utils/actions/**/*.validation.ts : Create Zod validation schemas at `apps/web/utils/actions/{feature}.validation.ts` for all server action input validation

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2026-01-08T15:09:16.739Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2026-01-08T15:09:16.739Z
Learning: Applies to apps/web/**/utils/actions/**/*.validation.ts : Create validation schemas with Zod in separate validation files (e.g., `example.validation.ts`)

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `.schema()` method with Zod validation schemas from corresponding `.validation.ts` files in next-safe-action configuration

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*.validation.ts : Define validation schemas using Zod

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*.validation.{ts,tsx} : Define validation schemas using Zod

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : LLM feature functions must import from `zod` for schema validation, use `createScopedLogger` from `@/utils/logger`, `chatCompletionObject` and `createGenerateObject` from `@/utils/llms`, and import `EmailAccountWithAI` type from `@/utils/llms/types`

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*.validation.ts : Use descriptive error messages in Zod validation schemas

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2025-11-25T14:39:08.150Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-11-25T14:39:08.150Z
Learning: Applies to apps/web/app/api/**/*.{ts,tsx} : Request bodies should use Zod schemas for validation to ensure type safety and prevent injection attacks

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2026-01-08T15:09:16.739Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2026-01-08T15:09:16.739Z
Learning: Applies to apps/web/**/*.{ts,tsx} : Infer types from Zod schemas using `z.infer<typeof schema>` instead of duplicating as separate interfaces

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2026-01-04T00:25:22.311Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/notes.mdc:0-0
Timestamp: 2026-01-04T00:25:22.311Z
Learning: Applies to **/*.{ts,tsx} : Infer types from Zod schemas using `z.infer<typeof schema>` instead of duplicating as separate interfaces

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Create corresponding server action implementation files using the naming convention `apps/web/utils/actions/NAME.ts` with 'use server' directive

Applied to files:

  • apps/web/utils/actions/rule.ts
📚 Learning: 2025-12-17T02:38:41.499Z
Learnt from: elie222
Repo: elie222/inbox-zero PR: 1103
File: apps/web/utils/actions/rule.ts:447-457
Timestamp: 2025-12-17T02:38:41.499Z
Learning: In apps/web/utils/actions/rule.ts, revalidatePath is not needed for toggleAllRulesAction because rules data is fetched client-side using SWR, not server-side. Server-side cache revalidation is only needed when using Next.js server components or server-side data fetching.

Applied to files:

  • apps/web/utils/actions/rule.ts
📚 Learning: 2026-01-08T15:09:16.739Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2026-01-08T15:09:16.739Z
Learning: Applies to apps/web/**/utils/actions/**/*.ts : Use server actions with `next-safe-action` for all mutations (create/update/delete operations), not POST API routes

Applied to files:

  • apps/web/utils/actions/rule.ts
📚 Learning: 2025-11-25T14:38:42.022Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/prisma.mdc:0-0
Timestamp: 2025-11-25T14:38:42.022Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Import Prisma using the project's centralized utility: `import prisma from '@/utils/prisma'`

Applied to files:

  • apps/web/utils/actions/rule.ts
🧬 Code graph analysis (2)
apps/web/utils/actions/rule.validation.ts (1)
apps/web/utils/gmail/label-validation.ts (1)
  • validateLabelNameBasic (83-122)
apps/web/utils/actions/rule.ts (2)
apps/web/utils/actions/safe-action.ts (1)
  • actionClient (84-138)
apps/web/utils/actions/rule.validation.ts (1)
  • importRulesBody (381-383)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Baz Reviewer
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: test
🔇 Additional comments (8)
apps/web/utils/actions/rule.ts (5)

19-20: LGTM!

Import addition for the new validation schema is appropriate.


676-683: LGTM!

Method rename from getOrCreateOutlookFolderIdByName to getOrCreateFolderIdByName aligns with the PR's goal of generalizing folder management across email providers.


838-852: LGTM!

Folder resolution logic for MOVE_FOLDER actions correctly resolves folder IDs when only the name is provided.


931-947: LGTM!

Consistent method rename for folder resolution during onboarding flow.


965-1073: Well-structured import action with appropriate security controls.

The implementation correctly:

  • Uses actionClient for authorization
  • Scopes existing rules query to emailAccountId
  • Clears account-specific IDs (labelId, folderId) for portability
  • Handles errors gracefully with skip counting
  • Matches rules by systemType first, then by name (case-insensitive)
apps/web/utils/actions/rule.validation.ts (3)

2-7: LGTM!

Import of CategoryFilterType follows the coding guideline to import Prisma enums from @/generated/prisma/enums.


283-343: LGTM!

The importedAction schema appropriately:

  • Uses a flatter structure suitable for JSON import
  • Validates required fields per action type using superRefine
  • Only requires folderName for MOVE_FOLDER (not folderId) since IDs are account-specific and will be resolved during execution
  • Reuses validateLabelNameBasic for consistent label validation

381-385: LGTM!

The schema and types correctly:

  • Use z.infer<typeof schema> for type inference (per coding guidelines)
  • Export only the necessary types (ImportRulesBody, ImportedRule)
  • Keep internal schemas (importedAction, importedRule) unexported

@elie222 elie222 merged commit 307b490 into main Jan 8, 2026
7 of 9 checks passed
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 17 files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants