Skip to content

Comments

Add debug rules page#1102

Merged
elie222 merged 2 commits intomainfrom
feat/debug-rules-page
Dec 17, 2025
Merged

Add debug rules page#1102
elie222 merged 2 commits intomainfrom
feat/debug-rules-page

Conversation

@elie222
Copy link
Owner

@elie222 elie222 commented Dec 17, 2025

Add a Debug Rules page and API to view rules JSON and bulk-toggle all rules for an email account

Introduce /debug/rules with a client page that fetches from /api/user/debug/rules, adds a global toggle wired to actions.rule.toggleAllRulesAction, and renders/copies rules JSON; include a new GET handler in apps/web/app/api/user/debug/rules/route.ts.

📍Where to Start

Start with the GET handler and getDebugRules in apps/web/app/api/user/debug/rules/route.ts, then review the client page in apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx.


Macroscope summarized 3ecd319.

Summary by CodeRabbit

  • New Features

    • Rules debugging interface: view all rules with status labels, toggle all rules on/off, copy/export JSON, and see loading/error states.
    • Added a "Rules" button in the Debug page for quick access.
  • Style

    • Improved text wrapping for long action fields.
    • Ensured hover card content properly hides overflow while preserving custom styles.
  • Chores

    • Version bumped to v2.23.6.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 17, 2025

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

Project Deployment Review Updated (UTC)
inbox-zero Ready Ready Preview Dec 17, 2025 0:15am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 17, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a Debug "Rules" UI and backing API: a new DebugRulesPage client component, a GET API route returning rule data, a server action to toggle all rules, supporting validation, and a small UI tweak plus a version bump.

Changes

Cohort / File(s) Change Summary
Debug UI — pages
apps/web/app/(app)/[emailAccountId]/debug/page.tsx, apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
Added a "Rules" button to the debug page and introduced DebugRulesPage (client) that fetches rules via SWR, shows enable/disable status, provides a toggle-all switch bound to an action, and a JSON viewer with copy-to-clipboard.
API — debug rules
apps/web/app/api/user/debug/rules/route.ts
New GET handler wrapped with withEmailAccount that calls getDebugRules({ emailAccountId }), queries Prisma for rules and related actions/groups, maps to simplified objects (including learnedPatternsCount), and returns JSON. Exports DebugRulesResponse, GET, and getDebugRules.
Server actions & validation
apps/web/utils/actions/rule.ts, apps/web/utils/actions/rule.validation.ts
Added toggleAllRulesAction server action and toggleAllRulesBody zod schema (and ToggleAllRulesBody type) to support bulk toggling of rules.
UI tweak
apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx, apps/web/components/HoverCard.tsx
Added break-all to action display fields and ensured HoverCardContent includes overflow-hidden via cn helper.
Version
version.txt
Bumped version v2.23.5 → v2.23.6.

Sequence Diagram(s)

sequenceDiagram
    participant Browser as Client (DebugRulesPage)
    participant SWR as SWR Cache
    participant API as /api/user/debug/rules (GET)
    participant ServerAction as toggleAllRulesAction (mutation)
    participant DB as Prisma/Database

    Browser->>SWR: request rules (useSWR)
    SWR->>API: GET /api/user/debug/rules
    API->>DB: query rules, include actions & group counts
    DB-->>API: rule rows
    API-->>SWR: JSON response
    SWR-->>Browser: populated data

    alt User toggles "All" switch
        Browser->>ServerAction: POST toggleAllRulesAction (emailAccountId, enabled)
        ServerAction->>DB: update rules set enabled
        DB-->>ServerAction: update result
        ServerAction-->>Browser: success response
        Browser->>SWR: mutate() / revalidate
        SWR->>API: fresh GET /api/user/debug/rules
        API->>DB: query updated rules
        DB-->>API: updated rows
        API-->>SWR: updated JSON
        SWR-->>Browser: refreshed data
    else Error
        ServerAction-->>Browser: error (message)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review Prisma query in getDebugRules for correct selections, includes, and ordering.
  • Verify mapping of nested action fields and fallback for learnedPatternsCount.
  • Inspect toggleAllRulesAction for transactional safety, permission checks, and revalidation behavior.
  • Validate toggleAllRulesBody schema aligns with action input handling and client usage.
  • Check SWR error/loading handling and UX edge cases in DebugRulesPage.

Poem

🐇 I hopped to rules with curious paws,
Flipped every switch to see the cause,
JSON crumbs in a tidy heap,
Copy, toast, and data leap—
Debugging carrots for all those bugs!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding a new debug page for rules with UI, API endpoint, and toggle functionality.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/debug-rules-page

📜 Recent 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 cb797cc and 3ecd319.

📒 Files selected for processing (2)
  • apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx (1 hunks)
  • apps/web/components/HoverCard.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (15)
apps/web/**/*.{ts,tsx}

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

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Use @/ path aliases for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Follow consistent naming conventions using PascalCase for components
Centralize shared types in dedicated type files

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

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
apps/web/app/**/*.{ts,tsx}

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

Follow NextJS app router structure with (app) directory

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
apps/web/**/*.tsx

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

apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks over class components
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Use LoadingContent component for async data with loading and error states

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
**/*.{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/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
apps/web/app/(app)/**/*.{ts,tsx}

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

apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put in page.tsx, or in the apps/web/app/(app)/PAGE_NAME folder
If we're in a deeply nested component we will use swr to fetch via API
If you need to use onClick in a component, that component is a client component and file must start with use client

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
**/*.{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/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
**/*.{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/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
**/*.{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/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
**/*.tsx

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

**/*.tsx: Use the LoadingContent component to handle loading states instead of manual loading state management
For text areas, use the Input component with type='text', autosizeTextarea prop set to true, and registerProps for form integration

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
**/*.{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/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use both children and dangerouslySetInnerHTML props on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use <>...</> instead of <Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't use target="_blank" without rel="noopener"
Don't use <img> elements in Next.js projects
Don't use <head> elements in Next.js projects

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
!(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/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
**/*.{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/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
  • apps/web/components/HoverCard.tsx
apps/web/components/**/*.tsx

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

apps/web/components/**/*.tsx: Use React Hook Form with Zod validation for form components
Use result?.serverError with toastError and toastSuccess for error handling in form submissions

Use LoadingContent component to consistently handle loading and error states, passing loading, error, and children props

Use PascalCase for component file names (e.g., components/Button.tsx)

Files:

  • apps/web/components/HoverCard.tsx
**/{pages,routes,components}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/gmail-api.mdc)

Never call Gmail API directly from routes or components - always use wrapper functions from the utils folder

Files:

  • apps/web/components/HoverCard.tsx
🧠 Learnings (8)
📚 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 : Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
📚 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 **/*Form.{ts,tsx} : Show validation errors inline next to form fields

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
📚 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 **/*Form.{ts,tsx} : Show validation errors inline next to form fields in the UI

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Accompany `onMouseOver`/`onMouseOut` with `onFocus`/`onBlur`

Applied to files:

  • apps/web/components/HoverCard.tsx
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/**/*.tsx : Use shadcn/ui components when available

Applied to files:

  • apps/web/components/HoverCard.tsx
📚 Learning: 2025-11-25T14:42:08.869Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-11-25T14:42:08.869Z
Learning: Applies to **/*.{ts,tsx} : Use consistent accessibility modifiers on class properties and methods

Applied to files:

  • apps/web/components/HoverCard.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : Use Shadcn UI and Tailwind for components and styling

Applied to files:

  • apps/web/components/HoverCard.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : Use Shadcn UI and Tailwind for components and styling

Applied to files:

  • apps/web/components/HoverCard.tsx
⏰ 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). (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: test
🔇 Additional comments (2)
apps/web/app/(app)/[emailAccountId]/assistant/ResultDisplay.tsx (1)

216-219: LGTM! Good addition for handling long values.

The break-all class addition properly prevents overflow of long field values (email addresses, URLs, content strings) by allowing breaks at any character. This improves the display without affecting functionality.

apps/web/components/HoverCard.tsx (1)

6-6: The cn utility import and className composition pattern are correctly implemented.

Adding cn("overflow-hidden", props.className) to HoverCardContent is sound—overflow-hidden prevents content overflow while allowing override through props. The implementation properly merges classes using clsx and twMerge. All existing usages (PlanBadge, PremiumCard, ResultDisplay) are compatible with this default and don't conflict.


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: 0

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

447-457: Consider adding revalidatePath after the mutation.

The action correctly scopes the update to the authenticated user's emailAccountId. However, unlike other mutation actions in this file (e.g., enableDraftRepliesAction, deleteRuleAction), this action doesn't call revalidatePath after modifying data. While the debug page uses mutate() to refresh, other pages displaying rule status may show stale data.

 export const toggleAllRulesAction = actionClient
   .metadata({ name: "toggleAllRules" })
   .inputSchema(toggleAllRulesBody)
   .action(async ({ ctx: { emailAccountId }, parsedInput: { enabled } }) => {
     await prisma.rule.updateMany({
       where: { emailAccountId },
       data: { enabled },
     });
 
+    revalidatePath(prefixPath(emailAccountId, "/assistant"));
+
     return { success: true };
   });
apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx (1)

42-48: Add error handling for clipboard API.

The clipboard API can fail (e.g., permissions denied, not supported in some contexts). Consider wrapping in try/catch to handle failures gracefully.

   const handleCopy = useCallback(() => {
     if (!data) return;
-    navigator.clipboard.writeText(JSON.stringify(data, null, 2));
-    setCopied(true);
-    toastSuccess({ description: "Copied to clipboard" });
-    setTimeout(() => setCopied(false), 2000);
+    navigator.clipboard
+      .writeText(JSON.stringify(data, null, 2))
+      .then(() => {
+        setCopied(true);
+        toastSuccess({ description: "Copied to clipboard" });
+        setTimeout(() => setCopied(false), 2000);
+      })
+      .catch(() => {
+        toastError({ description: "Failed to copy to clipboard" });
+      });
   }, [data]);
apps/web/app/api/user/debug/rules/route.ts (1)

5-5: Follow the Get[Feature]Response naming convention.

As per coding guidelines, response types from GET routes should be named with the Get prefix for consistency across the codebase.

-export type DebugRulesResponse = Awaited<ReturnType<typeof getDebugRules>>;
+export type GetDebugRulesResponse = Awaited<ReturnType<typeof getDebugRules>>;
📜 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 d72f70d and cb797cc.

📒 Files selected for processing (6)
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx (1 hunks)
  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx (1 hunks)
  • apps/web/app/api/user/debug/rules/route.ts (1 hunks)
  • apps/web/utils/actions/rule.ts (2 hunks)
  • apps/web/utils/actions/rule.validation.ts (1 hunks)
  • version.txt (1 hunks)
🧰 Additional context used
📓 Path-based instructions (26)
!(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:

  • version.txt
  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
  • apps/web/app/api/user/debug/rules/route.ts
  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
apps/web/**/*.{ts,tsx}

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

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Use @/ path aliases for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Follow consistent naming conventions using PascalCase for components
Centralize shared types in dedicated type files

Import specific lodash functions rather than entire lodash library 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
  • apps/web/app/api/user/debug/rules/route.ts
  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
apps/web/utils/actions/**/*.validation.ts

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

Use Zod schemas for validation and export both schema and inferred types in validation files

Files:

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

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

apps/web/utils/actions/**/*.ts: Use next-safe-action with actionClient for server actions with Zod schema validation
Call revalidatePath in server actions after mutations to invalidate cache

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
**/*.{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
  • apps/web/app/api/user/debug/rules/route.ts
  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
**/*.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
apps/web/utils/actions/*.ts

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

apps/web/utils/actions/*.ts: Use next-safe-action with Zod schemas for all server actions (create/update/delete mutations), storing validation schemas in apps/web/utils/actions/*.validation.ts
Server actions should use 'use server' directive and automatically receive authentication context (emailAccountId) from the actionClient

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
apps/web/utils/actions/*.validation.ts

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

apps/web/utils/actions/*.validation.ts: Define Zod validation schemas in separate *.validation.ts files and export both the schema and inferred type (e.g., CreateExampleBody)
Export types from Zod schemas using z.infer<> to maintain type safety between validation and client usage

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
**/{server,api,actions,utils}/**/*.ts

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

**/{server,api,actions,utils}/**/*.ts: Use createScopedLogger from "@/utils/logger" for logging in backend code
Add the createScopedLogger instantiation at the top of the file with an appropriate scope name
Use .with() method to attach context variables only within specific functions, not on global loggers
For large functions with reused variables, use createScopedLogger().with() to attach context once and reuse the logger without passing variables repeatedly

Files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
  • apps/web/app/api/user/debug/rules/route.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/app/api/user/debug/rules/route.ts
  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
**/*.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/app/api/user/debug/rules/route.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
  • apps/web/app/api/user/debug/rules/route.ts
  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
**/*.{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
  • apps/web/app/api/user/debug/rules/route.ts
  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
**/*.{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
  • apps/web/app/api/user/debug/rules/route.ts
  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
**/*.{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
  • apps/web/app/api/user/debug/rules/route.ts
  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
apps/web/app/**/*.{ts,tsx}

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

Follow NextJS app router structure with (app) directory

Files:

  • apps/web/app/api/user/debug/rules/route.ts
  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
apps/web/app/api/**/*.ts

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

apps/web/app/api/**/*.ts: Wrap GET API routes with withAuth or withEmailAccount middleware for authentication
Export response types from GET API routes using Awaited<ReturnType<>> pattern for type-safe client usage

Files:

  • apps/web/app/api/user/debug/rules/route.ts
apps/web/app/api/**/route.ts

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

apps/web/app/api/**/route.ts: Create GET API routes using withAuth or withEmailAccount middleware in apps/web/app/api/*/route.ts, export response types as GetExampleResponse type alias for client-side type safety
Always export response types from GET routes as Get[Feature]Response using type inference from the data fetching function for type-safe client consumption
Do NOT use POST API routes for mutations - always use server actions with next-safe-action instead

Files:

  • apps/web/app/api/user/debug/rules/route.ts
**/app/**/route.ts

📄 CodeRabbit inference engine (.cursor/rules/get-api-route.mdc)

**/app/**/route.ts: Always wrap GET API route handlers with withAuth or withEmailAccount middleware for consistent error handling and authentication in Next.js App Router
Infer and export response type for GET API routes using Awaited<ReturnType<typeof functionName>> pattern in Next.js
Use Prisma for database queries in GET API routes
Return responses using NextResponse.json() in GET API routes
Do not use try/catch blocks in GET API route handlers when using withAuth or withEmailAccount middleware, as the middleware handles error handling

Files:

  • apps/web/app/api/user/debug/rules/route.ts
apps/web/app/**/[!.]*/route.{ts,tsx}

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

Use kebab-case for route directories in Next.js App Router (e.g., api/hello-world/route)

Files:

  • apps/web/app/api/user/debug/rules/route.ts
apps/web/app/api/**/*.{ts,tsx}

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

apps/web/app/api/**/*.{ts,tsx}: API routes must use withAuth, withEmailAccount, or withError middleware for authentication
All database queries must include user scoping with emailAccountId or userId filtering in WHERE clauses
Request parameters must be validated before use; avoid direct parameter usage without type checking
Use generic error messages instead of revealing internal details; throw SafeError instead of exposing user IDs, resource IDs, or system information
API routes should only return necessary fields using select in database queries to prevent unintended information disclosure
Cron endpoints must use hasCronSecret or hasPostCronSecret to validate cron requests and prevent unauthorized access
Request bodies should use Zod schemas for validation to ensure type safety and prevent injection attacks

Files:

  • apps/web/app/api/user/debug/rules/route.ts
**/app/api/**/*.ts

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

**/app/api/**/*.ts: ALL API routes that handle user data MUST use appropriate middleware: use withEmailAccount for email-scoped operations, use withAuth for user-scoped operations, or use withError with proper validation for public/custom auth endpoints
Use withEmailAccount middleware for operations scoped to a specific email account, including reading/writing emails, rules, schedules, or any operation using emailAccountId
Use withAuth middleware for user-level operations such as user settings, API keys, and referrals that use only userId
Use withError middleware only for public endpoints, custom authentication logic, or cron endpoints. For cron endpoints, MUST use hasCronSecret() or hasPostCronSecret() validation
Cron endpoints without proper authentication can be triggered by anyone. CRITICAL: All cron endpoints MUST validate cron secret using hasCronSecret(request) or hasPostCronSecret(request) and capture unauthorized attempts with captureException()
Always validate request bodies using Zod schemas to ensure type safety and prevent invalid data from reaching database operations
Maintain consistent error response format across all API routes to avoid information disclosure while providing meaningful error feedback

Files:

  • apps/web/app/api/user/debug/rules/route.ts
apps/web/**/*.tsx

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

apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks over class components
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Use LoadingContent component for async data with loading and error states

Files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
apps/web/app/(app)/**/*.{ts,tsx}

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

apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put in page.tsx, or in the apps/web/app/(app)/PAGE_NAME folder
If we're in a deeply nested component we will use swr to fetch via API
If you need to use onClick in a component, that component is a client component and file must start with use client

Files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
**/*.tsx

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

**/*.tsx: Use the LoadingContent component to handle loading states instead of manual loading state management
For text areas, use the Input component with type='text', autosizeTextarea prop set to true, and registerProps for form integration

Files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
**/*.{jsx,tsx}

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

**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use both children and dangerouslySetInnerHTML props on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use <>...</> instead of <Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't use target="_blank" without rel="noopener"
Don't use <img> elements in Next.js projects
Don't use <head> elements in Next.js projects

Files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
🧠 Learnings (43)
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/utils/actions/*.validation.ts : Define Zod validation schemas in separate `*.validation.ts` files and export both the schema and inferred type (e.g., `CreateExampleBody`)

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/*.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:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/utils/actions/**/*.validation.ts : Use Zod schemas for validation and export both schema and inferred types in validation files

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/*.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: 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:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/utils/actions/*.validation.ts : Export types from Zod schemas using `z.infer<>` to maintain type safety between validation and client usage

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2025-11-25T14:39:23.326Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:23.326Z
Learning: Applies to app/api/**/*.ts : All input parameters must be validated - check for presence, type, and format before use; use Zod schemas to validate request bodies with type guards and constraints

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: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `next-safe-action` with Zod schemas for all server actions (create/update/delete mutations), storing validation schemas in `apps/web/utils/actions/*.validation.ts`

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
  • apps/web/utils/actions/rule.ts
📚 Learning: 2025-11-25T14:39:27.909Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:27.909Z
Learning: Applies to **/app/api/**/*.ts : Always validate request bodies using Zod schemas to ensure type safety and prevent invalid data from reaching database operations

Applied to files:

  • apps/web/utils/actions/rule.validation.ts
📚 Learning: 2025-11-25T14:40:00.833Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-25T14:40:00.833Z
Learning: Applies to **/*.test.{ts,tsx} : Use test helpers `getEmail`, `getEmailAccount`, and `getRule` from `@/__tests__/helpers` for mocking emails, accounts, and rules

Applied to files:

  • apps/web/utils/actions/rule.ts
  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/utils/actions/**/*.ts : Use `next-safe-action` with `actionClient` for server actions with Zod schema validation

Applied to files:

  • apps/web/utils/actions/rule.ts
📚 Learning: 2025-11-25T14:37:11.434Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-11-25T14:37:11.434Z
Learning: Applies to **/app/**/route.ts : Always wrap GET API route handlers with `withAuth` or `withEmailAccount` middleware for consistent error handling and authentication in Next.js App Router

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/app/api/**/route.ts : Create GET API routes using `withAuth` or `withEmailAccount` middleware in `apps/web/app/api/*/route.ts`, export response types as `GetExampleResponse` type alias for client-side type safety

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:37:11.434Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-11-25T14:37:11.434Z
Learning: Applies to **/app/**/route.ts : Infer and export the response type for GET API routes using `export type GetResponse = Awaited<ReturnType<typeof getData>>` pattern in Next.js

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:37:22.822Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-11-25T14:37:22.822Z
Learning: Applies to **/app/**/route.ts : Infer and export response type for GET API routes using `Awaited<ReturnType<typeof functionName>>` pattern in Next.js

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/app/**/[!.]*/route.{ts,tsx} : Use kebab-case for route directories in Next.js App Router (e.g., `api/hello-world/route`)

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:36:18.416Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-11-25T14:36:18.416Z
Learning: Applies to apps/web/app/api/**/*.ts : Wrap GET API routes with `withAuth` or `withEmailAccount` middleware for authentication

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:37:22.822Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-11-25T14:37:22.822Z
Learning: Applies to **/app/**/route.ts : Do not use try/catch blocks in GET API route handlers when using `withAuth` or `withEmailAccount` middleware, as the middleware handles error handling

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/app/api/**/route.ts : Always export response types from GET routes as `Get[Feature]Response` using type inference from the data fetching function for type-safe client consumption

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:37:11.434Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-11-25T14:37:11.434Z
Learning: Applies to **/app/**/route.ts : Do not use try/catch blocks in GET API route handlers as `withAuth` and `withEmailAccount` middleware handle error handling

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:39:23.326Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:23.326Z
Learning: Applies to app/api/**/*.ts : Use `withEmailAccount` middleware for operations scoped to a specific email account (reading/writing emails, rules, schedules, etc.) - provides `emailAccountId`, `userId`, and `email` in `request.auth`

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:39:27.909Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:27.909Z
Learning: Applies to **/app/api/**/*.ts : Use `withEmailAccount` middleware for operations scoped to a specific email account, including reading/writing emails, rules, schedules, or any operation using `emailAccountId`

Applied to files:

  • apps/web/app/api/user/debug/rules/route.ts
📚 Learning: 2025-11-25T14:38:23.265Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/page-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:23.265Z
Learning: Applies to apps/web/app/(app)/*/page.tsx : Create new pages at `apps/web/app/(app)/PAGE_NAME/page.tsx`

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
📚 Learning: 2025-11-25T14:38:18.874Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/page-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:18.874Z
Learning: Applies to apps/web/app/(app)/**/page.tsx : Create new pages at `apps/web/app/(app)/PAGE_NAME/page.tsx`

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
  • apps/web/app/(app)/[emailAccountId]/debug/page.tsx
📚 Learning: 2025-11-25T14:38:18.874Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/page-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:18.874Z
Learning: Applies to apps/web/app/(app)/**/*.tsx : Components for pages are either put in `page.tsx`, or in the `apps/web/app/(app)/PAGE_NAME` folder

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/app/(app)/*/page.tsx : Create new pages at `apps/web/app/(app)/PAGE_NAME/page.tsx` with components either colocated in the same folder or in `page.tsx`

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:38:23.265Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/page-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:23.265Z
Learning: Applies to apps/web/app/(app)/**/*.{ts,tsx} : Components for the page are either put in `page.tsx`, or in the `apps/web/app/(app)/PAGE_NAME` folder

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/components/ui/**/*.tsx : Shadcn UI components are located in `components/ui` directory

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Applies to apps/web/app/*/page.tsx : Pages must be Server components that load data directly

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:39:23.326Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:23.326Z
Learning: Applies to app/api/**/*.ts : Use `SafeError` for error responses to prevent information disclosure - provide generic messages (e.g., 'Rule not found' not 'Rule {id} does not exist for user {userId}') without revealing internal IDs or ownership details

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:38:18.874Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/page-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:18.874Z
Learning: Applies to apps/web/app/(app)/**/*.tsx : If you need to use `onClick` in a component, that component must be a client component and file must start with `use client` directive

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:37:56.430Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm-test.mdc:0-0
Timestamp: 2025-11-25T14:37:56.430Z
Learning: Applies to apps/web/__tests__/**/*.test.ts : Use `console.debug()` for outputting generated LLM content in tests, e.g., `console.debug("Generated content:\n", result.content);`

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:37:30.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/hooks.mdc:0-0
Timestamp: 2025-11-25T14:37:30.660Z
Learning: Applies to apps/web/hooks/use*.ts : Create dedicated hooks for specific data types (e.g., `useAccounts`, `useLabels`) that wrap `useSWR`, handle the API endpoint URL, and return data, loading state, error state, and the `mutate` function

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For API get requests to server, use the `swr` package with `useSWR` hook

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:38:18.874Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/page-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:18.874Z
Learning: Applies to apps/web/app/(app)/**/*.tsx : If nested deeply in components, use `swr` to fetch via API instead of loading data directly

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:36:36.276Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:36.276Z
Learning: For mutating data, use Next.js server actions instead of SWR

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/hooks/use*.ts : Use SWR hooks for client-side data fetching, with hooks stored in `apps/web/hooks/use*.ts` that return typed responses from GET API routes

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:37:35.343Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/hooks.mdc:0-0
Timestamp: 2025-11-25T14:37:35.343Z
Learning: Applies to apps/web/hooks/use*.ts : Create dedicated hooks for specific data types (e.g., `useAccounts`, `useLabels`) to wrap `useSWR` for individual API endpoints

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:36:40.146Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-11-25T14:36:40.146Z
Learning: Applies to **/*{.action,.server}.{ts,tsx} : For mutating data, use Next.js server actions

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:37:30.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/hooks.mdc:0-0
Timestamp: 2025-11-25T14:37:30.660Z
Learning: Applies to apps/web/hooks/use*.ts : For data fetching, prefer using `useSWR` and follow the data-fetching guidelines

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-06-05T09:49:12.168Z
Learnt from: elie222
Repo: elie222/inbox-zero PR: 485
File: apps/web/app/(landing)/login/page.tsx:41-43
Timestamp: 2025-06-05T09:49:12.168Z
Learning: In Next.js App Router, components that use the `useSearchParams` hook require a Suspense boundary to handle the asynchronous nature of search parameter access. The Suspense wrapper is necessary and should not be removed when a component uses useSearchParams.

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : For API GET requests to server, use the `swr` package with hooks like `useSWR` to fetch data

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx
🧬 Code graph analysis (3)
apps/web/utils/actions/rule.ts (2)
apps/web/utils/actions/safe-action.ts (1)
  • actionClient (77-128)
apps/web/utils/actions/rule.validation.ts (1)
  • toggleAllRulesBody (270-272)
apps/web/app/api/user/debug/rules/route.ts (1)
apps/web/utils/middleware.ts (1)
  • withEmailAccount (398-416)
apps/web/app/(app)/[emailAccountId]/debug/page.tsx (1)
apps/web/components/new-landing/icons/Link.tsx (1)
  • Link (1-18)
⏰ 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). (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: test
🔇 Additional comments (8)
version.txt (1)

1-1: LGTM!

Version bump to v2.23.6 is appropriate for the new debug rules feature.

apps/web/app/(app)/[emailAccountId]/debug/page.tsx (1)

17-19: LGTM!

The new "Rules" navigation button follows the same pattern as the existing buttons and integrates well with the debug page navigation.

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

270-273: LGTM!

The validation schema follows the established pattern in this file and correctly exports both the Zod schema and inferred TypeScript type. Based on learnings, this aligns with the validation file conventions.

apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx (2)

18-40: LGTM!

The component correctly uses SWR for data fetching, useAction from next-safe-action for mutations, and properly handles loading/error states via LoadingContent. The action is correctly bound to emailAccountId from the account provider. As per coding guidelines, this follows the pattern for client components with onClick handlers.


54-95: LGTM!

The UI follows good practices:

  • Switch is properly associated with Label via htmlFor
  • LoadingContent handles loading/error states
  • Button states (disabled, copied) are handled correctly
  • JSON display provides useful debugging information
apps/web/app/api/user/debug/rules/route.ts (3)

1-3: LGTM!

Imports are correctly structured using @/ path aliases and include the appropriate middleware and Prisma client.


7-11: LGTM!

The GET handler correctly uses withEmailAccount middleware for authentication, properly extracts emailAccountId from the auth context, and returns the response using NextResponse.json(). Based on learnings, this follows the established patterns.


13-64: LGTM!

The data fetching function is well-structured:

  • Database query is properly scoped to emailAccountId for security
  • Explicit field mapping in the return prevents unintended data exposure and provides API stability
  • The learnedPatternsCount derivation with optional chaining handles missing group data gracefully

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.

1 issue found across 6 files

Prompt for AI agents (all 1 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx">

<violation number="1" location="apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx:20">
P2: Use `useSWRWithEmailAccount` instead of `useSWR` to ensure the fetch only happens when `emailAccountId` is available. This matches the pattern used in other hooks like `useRules.tsx` and prevents premature API calls before account context is ready.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR


export default function DebugRulesPage() {
const { emailAccountId } = useAccount();
const { data, isLoading, error, mutate } = useSWR<DebugRulesResponse>(
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Dec 17, 2025

Choose a reason for hiding this comment

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

P2: Use useSWRWithEmailAccount instead of useSWR to ensure the fetch only happens when emailAccountId is available. This matches the pattern used in other hooks like useRules.tsx and prevents premature API calls before account context is ready.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/app/(app)/[emailAccountId]/debug/rules/page.tsx, line 20:

<comment>Use `useSWRWithEmailAccount` instead of `useSWR` to ensure the fetch only happens when `emailAccountId` is available. This matches the pattern used in other hooks like `useRules.tsx` and prevents premature API calls before account context is ready.</comment>

<file context>
@@ -0,0 +1,96 @@
+
+export default function DebugRulesPage() {
+  const { emailAccountId } = useAccount();
+  const { data, isLoading, error, mutate } = useSWR&lt;DebugRulesResponse&gt;(
+    &quot;/api/user/debug/rules&quot;,
+  );
</file context>
Fix with Cubic

@elie222 elie222 merged commit d2c02d4 into main Dec 17, 2025
13 checks passed
This was referenced Dec 17, 2025
@elie222 elie222 deleted the feat/debug-rules-page branch December 18, 2025 23:02
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.

1 participant