-
Notifications
You must be signed in to change notification settings - Fork 925
Outlook support #537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Outlook support #537
Conversation
Outlook webhook POC
Claude encountered an error —— View job I'll analyze this and get back to you. |
Claude encountered an error —— View job I'll analyze this and get back to you. |
There was a problem hiding this 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
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
README.md
(5 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
!{.cursor/rules/*.mdc}
📄 CodeRabbit Inference Engine (.cursor/rules/cursor-rules.mdc)
Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location
Files:
README.md
*{TASKS,ASSISTANT_CHAT,*.md}
📄 CodeRabbit Inference Engine (.cursor/rules/task-list.mdc)
*{TASKS,ASSISTANT_CHAT,*.md}
: Create task lists in a markdown file in the project root, usingTASKS.md
or a descriptive name relevant to the feature (e.g.,ASSISTANT_CHAT.md
), and include a clear title and description of the feature being implemented.
Structure the task list markdown file with sections: Completed Tasks, In Progress Tasks, Future Tasks, Implementation Plan, and Relevant Files.
Update the task list as you progress: mark tasks as completed by changing[ ]
to[x]
, add new tasks as identified, and move tasks between sections as appropriate.
Keep the 'Relevant Files' section updated with file paths, brief descriptions of each file's purpose, and status indicators (e.g., ✅) for completed components.
Add implementation details to the task list markdown file, including architecture decisions, data flow descriptions, technical components needed, and environment configuration.
When working with task lists, regularly update the task list file after implementing significant components, mark completed tasks with [x], add new tasks discovered during implementation, maintain the 'Relevant Files' section, and document implementation details.
When implementing tasks one by one, first check which task to implement next, and after implementing a task, update the file to reflect progress.
Files:
README.md
!pages/_document.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
!pages/_document.{js,jsx,ts,tsx}
: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.
Files:
README.md
🧠 Learnings (2)
📓 Common learnings
Learnt from: elie222
PR: elie222/inbox-zero#537
File: apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx:30-34
Timestamp: 2025-07-08T13:14:07.449Z
Learning: The clean onboarding page in apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx is intentionally Gmail-specific and should show an error for non-Google email accounts rather than attempting to support multiple providers.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.890Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/index.mdc:0-0
Timestamp: 2025-07-18T15:05:56.618Z
Learning: Guidelines for working with Gmail API
README.md (11)
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to */.env : Never use predictable or weak cron secrets (e.g., 'secret', 'password', 'cron', or short/simple strings) in environment variables.
Learnt from: CR
PR: elie222/inbox-zero#0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-07-18T15:04:30.448Z
Learning: Applies to apps/web/**/{.env.example,env.ts} : Client-side environment variables: Prefix with NEXT_PUBLIC_
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Never expose secrets or sensitive data in code or version control; store all secrets in environment variables.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/environment-variables.mdc:0-0
Timestamp: 2025-07-18T15:04:50.510Z
Learning: Applies to apps/web/env.ts : Client-side environment variables must be prefixed with NEXT_PUBLIC_
and added to both the client
and experimental__runtimeEnv
sections in apps/web/env.ts
.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : Do not hardcode weak or plaintext secrets in API route files; secrets must not be directly assigned as string literals.
Learnt from: garnertb
PR: #580
File: apps/web/.env.example:4-7
Timestamp: 2025-07-19T15:06:43.707Z
Learning: In apps/web/.env.example, boolean environment variables follow an unquoted convention (e.g., LOG_ZOD_ERRORS=true, AUTH_TRUST_HOST=true). Logical grouping of related variables (like auth variables together) is preferred over strict alphabetical ordering for better developer experience.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/environment-variables.mdc:0-0
Timestamp: 2025-07-18T15:04:50.510Z
Learning: Applies to apps/web/.env.example : When adding a new environment variable, add it to .env.example
with an example value (e.g., NEW_VARIABLE=value_example).
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/environment-variables.mdc:0-0
Timestamp: 2025-07-18T15:04:50.510Z
Learning: Applies to apps/web/env.ts : When adding a new environment variable, add it to apps/web/env.ts
in the appropriate section: use server
for server-only variables, and for client-side variables, use the client
section and also add to experimental__runtimeEnv
.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/index.mdc:0-0
Timestamp: 2025-07-18T15:05:56.618Z
Learning: Guidelines for working with Gmail API
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : All cron endpoints in API routes must use hasCronSecret or hasPostCronSecret for authentication.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : Cron endpoints MUST use withError
middleware and validate the cron secret using hasCronSecret(request)
or hasPostCronSecret(request)
.
🪛 markdownlint-cli2 (0.17.2)
README.md
168-168: Trailing punctuation in heading
Punctuation: ':'
(MD026, no-trailing-punctuation)
🔇 Additional comments (3)
README.md (3)
108-111
: Verify env-variable propagation
EMAIL_ENCRYPT_SECRET
/EMAIL_ENCRYPT_SALT
replace the old Google-specific names here.
Please make sure they are:
- Added to
apps/web/.env.example
(guidelines demand every new var appear there).- Declared in the
server
section ofapps/web/env.ts
, and, if ever exposed client side, duplicated underclient
+experimental__runtimeEnv
.Failure to sync these files will break type-safe env validation at boot.
168-226
: Fix MD026 & double-check new Microsoft vars
- Markdown-lint flags the trailing colon in the heading (MD026).
-### Updating .env file with Microsoft OAuth credentials:
+### Updating .env file with Microsoft OAuth credentials2. Same env-propagation checklist applies: ensure `MICROSOFT_CLIENT_ID/SECRET` land in `.env.example`, `env.ts`, and `experimental__runtimeEnv` (if ever needed on the client). [ suggest_nitpick ][ request_verification ] --- `324-335`: **Unified watch endpoint – confirm route exists & docs fully updated** Docs now reference `/api/watch/all` (cron + manual link). Please verify: 1. `apps/web/app/api/watch/all/route.ts` (or equivalent) exists and handles all providers. 2. All residual references to the old `/api/google/watch/all` path have been scrubbed to avoid confusion. A quick `rg '/api/google/watch/all'` in the repo will catch stragglers. </details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
Claude encountered an error —— View job I'll analyze this and get back to you. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🔭 Outside diff range comments (1)
apps/web/utils/types.ts (1)
47-61
: Abstract provider-agnostic email message away from Gmail API typesBased on our search,
ParsedMessage
inapps/web/utils/types.ts
still extendsgmail_v1.Schema$Message
and is consumed by both the Gmail and Outlook providers (e.g.apps/web/utils/outlook/*.ts
). This forces every provider to fit its raw data into Gmail’s shape. To decouple our core logic from Gmail-specific types and make it easier to add or adjust providers:• In
apps/web/utils/types.ts
, extract a newBaseParsedMessage
interface containing only generic fields:
- id, threadId, subject, date, snippet, attachments, inline, headers, textPlain, textHtml, etc.
• Rename the existingParsedMessage
toGmailParsedMessage
and have it extend bothBaseParsedMessage
andgmail_v1.Schema$Message
.
• Create anOutlookParsedMessage
(or similar) that extendsBaseParsedMessage
without touching Gmail types, and update the Outlook provider to return that.
• Change yourEmailProvider
interface and consumers to referenceBaseParsedMessage
instead ofParsedMessage
.This split will keep provider-specific details isolated and allow truly provider-agnostic handling in our UI and business logic.
♻️ Duplicate comments (3)
apps/web/utils/outlook/message.ts (3)
183-187
: Critical: SQL injection vulnerability still present in combined filter.The query parameter is still being directly interpolated into the OData filter without proper escaping, maintaining the injection vulnerability flagged in previous reviews.
Apply the fix from previous review:
const folderFilter = `(parentFolderId eq '${inboxFolderId}' or parentFolderId eq '${archiveFolderId}')`; - const combinedFilter = query.trim() - ? `${query.trim()} and ${folderFilter}` - : folderFilter; + const escapedQuery = query.trim().replace(/'/g, "''"); + const combinedFilter = escapedQuery + ? `${escapedQuery} and ${folderFilter}` + : folderFilter;
245-245
: Critical: SQL injection vulnerability still present in folder filter.The folderId parameter is still being directly interpolated without validation, maintaining the injection vulnerability flagged in previous reviews.
Apply the validation fix from previous review:
if (folderId) { + // Validate folderId format (should be a GUID) + if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(folderId)) { + throw new Error("Invalid folder ID format"); + } request = request.filter(`parentFolderId eq '${folderId}'`); } else {
366-368
: Critical: SQL injection vulnerability in query filter.The query parameter is directly interpolated into the filter string without proper escaping, similar to the issues in queryBatchMessages.
Apply this fix to escape the query:
if (options.query) { - request = request.filter(`contains(subject, '${options.query}')`); + const escapedQuery = options.query.replace(/'/g, "''"); + request = request.filter(`contains(subject, '${escapedQuery}')`); }
🧹 Nitpick comments (1)
apps/web/utils/types.ts (1)
50-50
: Document the purpose of the newisReplyInThread
property.The new boolean property lacks documentation explaining its purpose and how it differs from other thread-related logic in the system.
Add a comment explaining the property:
+ /** Indicates if this message is a reply within an existing thread */ isReplyInThread: boolean;
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
(3 hunks)apps/web/prisma/schema.prisma
(1 hunks)apps/web/utils/ai/choose-rule/match-rules.ts
(7 hunks)apps/web/utils/ai/choose-rule/run-rules.ts
(7 hunks)apps/web/utils/date.ts
(1 hunks)apps/web/utils/mail.ts
(2 hunks)apps/web/utils/outlook/message.ts
(1 hunks)apps/web/utils/thread.ts
(0 hunks)apps/web/utils/types.ts
(2 hunks)
📓 Path-based instructions (8)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}
: Use TypeScript with strict null checks
Path aliases: Use@/
for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
!{.cursor/rules/*.mdc}
📄 CodeRabbit Inference Engine (.cursor/rules/cursor-rules.mdc)
Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
**/*.ts
📄 CodeRabbit Inference Engine (.cursor/rules/form-handling.mdc)
**/*.ts
: The same validation should be done in the server action too
Define validation schemas using Zod
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/logging.mdc)
**/*.{ts,tsx}
: UsecreateScopedLogger
for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when usingcreateScopedLogger
Only use.with()
on a logger instance within a specific function, not for a global loggerImport Prisma in the project using
import prisma from "@/utils/prisma";
**/*.{ts,tsx}
: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
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 parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
apps/web/utils/**
📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)
Create utility functions in
utils/
folder for reusable logic
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
apps/web/utils/**/*.ts
📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)
apps/web/utils/**/*.ts
: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}
: Don't useelements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
!pages/_document.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
!pages/_document.{js,jsx,ts,tsx}
: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: elie222
PR: elie222/inbox-zero#537
File: apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx:30-34
Timestamp: 2025-07-08T13:14:07.449Z
Learning: The clean onboarding page in apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx is intentionally Gmail-specific and should show an error for non-Google email accounts rather than attempting to support multiple providers.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.890Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/index.mdc:0-0
Timestamp: 2025-07-18T15:05:56.618Z
Learning: Guidelines for working with Gmail API
apps/web/utils/outlook/message.ts (16)
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.890Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Extract common patterns into utility functions in LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Include relevant context in log messages for LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Define clear interfaces for complex input/output structures in LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Use proper error types and logging in LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-19T17:50:28.259Z
Learning: The utils
folder also contains core app logic such as Next.js Server Actions and Gmail API requests.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Use descriptive scoped loggers for each LLM feature.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : All Prisma queries in API routes must include user/account filtering (e.g., emailAccountId or userId in WHERE clauses) to prevent unauthorized data access.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Implement fallbacks for AI failures in LLM-related functions.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : All parameters used in API routes must be validated before use; do not use parameters from 'params' or request bodies directly in queries without validation.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : ALL database queries in API routes MUST be scoped to the authenticated user/account (e.g., include userId or emailAccountId in query filters).
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : Never use direct object references in API routes without ownership checks (prevent IDOR vulnerabilities).
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : Prevent mass assignment vulnerabilities by only allowing explicitly whitelisted fields in update operations in API routes.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : Do not hardcode weak or plaintext secrets in API route files; secrets must not be directly assigned as string literals.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : All findUnique
and findFirst
Prisma calls in API routes MUST include ownership filters (e.g., userId or emailAccountId).
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : Review all new withError usage in API routes to ensure custom authentication is implemented where required.
apps/web/utils/types.ts (1)
Learnt from: edulelis
PR: #576
File: packages/resend/emails/digest.tsx:78-83
Timestamp: 2025-07-17T04:19:57.099Z
Learning: In packages/resend/emails/digest.tsx, the DigestEmailProps type uses [key: string]: DigestItem[] | undefined | string | Date | undefined
instead of intersection types like & Record<string, DigestItem[] | undefined>
due to implementation constraints. This was the initial implementation approach and cannot be changed to more restrictive typing.
💤 Files with no reviewable changes (1)
- apps/web/utils/thread.ts
🚧 Files skipped from review as they are similar to previous changes (6)
- apps/web/utils/date.ts
- apps/web/utils/mail.ts
- apps/web/prisma/schema.prisma
- apps/web/app/(app)/[emailAccountId]/assistant/RuleForm.tsx
- apps/web/utils/ai/choose-rule/run-rules.ts
- apps/web/utils/ai/choose-rule/match-rules.ts
🧰 Additional context used
📓 Path-based instructions (8)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}
: Use TypeScript with strict null checks
Path aliases: Use@/
for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
!{.cursor/rules/*.mdc}
📄 CodeRabbit Inference Engine (.cursor/rules/cursor-rules.mdc)
Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
**/*.ts
📄 CodeRabbit Inference Engine (.cursor/rules/form-handling.mdc)
**/*.ts
: The same validation should be done in the server action too
Define validation schemas using Zod
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/logging.mdc)
**/*.{ts,tsx}
: UsecreateScopedLogger
for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when usingcreateScopedLogger
Only use.with()
on a logger instance within a specific function, not for a global loggerImport Prisma in the project using
import prisma from "@/utils/prisma";
**/*.{ts,tsx}
: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
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 parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
apps/web/utils/**
📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)
Create utility functions in
utils/
folder for reusable logic
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
apps/web/utils/**/*.ts
📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)
apps/web/utils/**/*.ts
: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}
: Don't useelements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
!pages/_document.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
!pages/_document.{js,jsx,ts,tsx}
: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.
Files:
apps/web/utils/outlook/message.ts
apps/web/utils/types.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: elie222
PR: elie222/inbox-zero#537
File: apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx:30-34
Timestamp: 2025-07-08T13:14:07.449Z
Learning: The clean onboarding page in apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx is intentionally Gmail-specific and should show an error for non-Google email accounts rather than attempting to support multiple providers.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.890Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/index.mdc:0-0
Timestamp: 2025-07-18T15:05:56.618Z
Learning: Guidelines for working with Gmail API
apps/web/utils/outlook/message.ts (16)
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.890Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Extract common patterns into utility functions in LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Include relevant context in log messages for LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Define clear interfaces for complex input/output structures in LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Use proper error types and logging in LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-19T17:50:28.259Z
Learning: The utils
folder also contains core app logic such as Next.js Server Actions and Gmail API requests.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Use descriptive scoped loggers for each LLM feature.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : All Prisma queries in API routes must include user/account filtering (e.g., emailAccountId or userId in WHERE clauses) to prevent unauthorized data access.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Implement fallbacks for AI failures in LLM-related functions.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : All parameters used in API routes must be validated before use; do not use parameters from 'params' or request bodies directly in queries without validation.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : ALL database queries in API routes MUST be scoped to the authenticated user/account (e.g., include userId or emailAccountId in query filters).
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : Never use direct object references in API routes without ownership checks (prevent IDOR vulnerabilities).
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : Prevent mass assignment vulnerabilities by only allowing explicitly whitelisted fields in update operations in API routes.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : Do not hardcode weak or plaintext secrets in API route files; secrets must not be directly assigned as string literals.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : All findUnique
and findFirst
Prisma calls in API routes MUST include ownership filters (e.g., userId or emailAccountId).
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : Review all new withError usage in API routes to ensure custom authentication is implemented where required.
apps/web/utils/types.ts (1)
Learnt from: edulelis
PR: #576
File: packages/resend/emails/digest.tsx:78-83
Timestamp: 2025-07-17T04:19:57.099Z
Learning: In packages/resend/emails/digest.tsx, the DigestEmailProps type uses [key: string]: DigestItem[] | undefined | string | Date | undefined
instead of intersection types like & Record<string, DigestItem[] | undefined>
due to implementation constraints. This was the initial implementation approach and cannot be changed to more restrictive typing.
🔇 Additional comments (8)
apps/web/utils/outlook/message.ts (8)
1-11
: LGTM: Clean imports and proper logger setup.The imports are well-structured, the scoped logger follows coding guidelines, and the module-level folder cache is appropriate for this use case.
12-24
: LGTM: Robust helper function with proper error handling.The function correctly handles base64 decoding errors and provides safe fallback behavior with appropriate logging.
26-34
: LGTM: Well-defined constants with proper TypeScript usage.Good use of
as const
for type safety and comprehensive coverage of standard email folders.
36-68
: LGTM: Efficient folder ID fetching with proper caching and error handling.The function uses parallel requests, graceful error handling, and caching to optimize performance while providing good observability through logging.
70-114
: LGTM: Comprehensive label mapping with proper null/undefined handling.The function correctly maps Outlook message properties to standardized labels, handles edge cases appropriately, and provides complete coverage of label types.
116-129
: LGTM: Well-structured query function with proper rate limiting and pagination.The function correctly implements different query strategies (OData filters, search, and basic queries) with appropriate pagination handling and rate limiting protection. The logging provides good observability for debugging.
Also applies to: 130-134, 136-178, 188-237, 238-275
278-310
: LGTM: Comprehensive message conversion with proper fallback handling.The function correctly filters drafts, maps all required fields, and handles optional/undefined values safely with appropriate fallbacks.
312-347
: LGTM: Proper single message retrieval with folder ID mapping.The function correctly fetches folder IDs to ensure proper label mapping for the retrieved message.
Claude encountered an error —— View job I'll analyze this and get back to you. |
Claude encountered an error —— View job I'll analyze this and get back to you. |
There was a problem hiding this 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
🔭 Outside diff range comments (1)
apps/web/utils/scheduled-actions/executor.ts (1)
134-143
: Provider-specific error handling needs abstractionThe error handling checks for a Gmail-specific error message "Requested entity was not found." This won't work correctly for other email providers like Outlook, which may have different error messages for missing emails.
Consider creating a provider-agnostic way to handle "not found" errors:
} catch (error: unknown) { - if ( - error instanceof Error && - error.message === "Requested entity was not found." - ) { + // Check if it's a "not found" error using provider-agnostic logic + if (client.isNotFoundError(error)) { logger.info("Email not found during validation", { messageId: scheduledAction.messageId, scheduledActionId: scheduledAction.id, }); return null; } throw error; }Alternatively, update the EmailProvider interface to return null for non-existent messages instead of throwing an error.
🧹 Nitpick comments (3)
apps/web/app/api/outlook/webhook/process-history-item.ts (2)
26-91
: Consider extracting message parsing logic into a helper function.The function has good structure with proper logging and deduplication checks. However, the message parsing logic (lines 76-82) could be extracted into a reusable helper function to improve maintainability.
+function parseMessageHeaders(message: Message) { + const from = message.from?.emailAddress?.address; + const to = message.toRecipients + ?.map((r) => r.emailAddress?.address) + .filter(Boolean) || []; + const subject = message.subject || ""; + + return { from, to, subject }; +} // Then in the main function: - const from = message.from?.emailAddress?.address; - const to = - message.toRecipients - ?.map((r) => r.emailAddress?.address) - .filter(Boolean) || []; - const subject = message.subject || ""; + const { from, to, subject } = parseMessageHeaders(message);
197-241
: Consider optimizing database query for sender categorization.The sender categorization logic is functionally correct, but the database query could be optimized by combining the existence check with the categorization logic.
if (emailAccount.autoCategorizeSenders) { const sender = extractEmailAddress(from); - const existingSender = await prisma.newsletter.findUnique({ - where: { - email_emailAccountId: { email: sender, emailAccountId }, - }, - select: { category: true }, - }); - if (!existingSender?.category) { - await categorizeSenderWithProvider(sender, emailAccount, emailProvider); - } + // Only categorize if sender doesn't exist or has no category + const shouldCategorize = await prisma.newsletter.findFirst({ + where: { + email: sender, + emailAccountId, + category: null, + }, + select: { id: true }, + }); + + if (shouldCategorize || !(await prisma.newsletter.findUnique({ + where: { email_emailAccountId: { email: sender, emailAccountId } }, + select: { id: true }, + }))) { + await categorizeSenderWithProvider(sender, emailAccount, emailProvider); + } }Actually, let me reconsider this - the original approach is clearer and the performance impact is minimal for this use case.
apps/web/utils/scheduled-actions/executor.ts (1)
1-1
: Remove unused Gmail importThe
gmail_v1
type import from@googleapis/gmail
is no longer used in this file after the provider abstraction refactoring.-import type { gmail_v1 } from "@googleapis/gmail";
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
apps/web/app/api/outlook/webhook/process-history-item.ts
(1 hunks)apps/web/app/api/scheduled-actions/execute/route.ts
(3 hunks)apps/web/utils/ai/choose-rule/match-rules.ts
(7 hunks)apps/web/utils/mail.ts
(2 hunks)apps/web/utils/outlook/message.ts
(1 hunks)apps/web/utils/scheduled-actions/executor.ts
(8 hunks)apps/web/utils/thread.ts
(1 hunks)apps/web/utils/types.ts
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- apps/web/utils/types.ts
- apps/web/utils/mail.ts
- apps/web/utils/thread.ts
- apps/web/utils/ai/choose-rule/match-rules.ts
- apps/web/utils/outlook/message.ts
🧰 Additional context used
📓 Path-based instructions (12)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}
: Use TypeScript with strict null checks
Path aliases: Use@/
for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX
Files:
apps/web/app/api/scheduled-actions/execute/route.ts
apps/web/utils/scheduled-actions/executor.ts
apps/web/app/api/outlook/webhook/process-history-item.ts
apps/web/app/**
📄 CodeRabbit Inference Engine (apps/web/CLAUDE.md)
NextJS app router structure with (app) directory
Files:
apps/web/app/api/scheduled-actions/execute/route.ts
apps/web/app/api/outlook/webhook/process-history-item.ts
apps/web/app/api/**/route.ts
📄 CodeRabbit Inference Engine (apps/web/CLAUDE.md)
apps/web/app/api/**/route.ts
: UsewithAuth
for user-level operations
UsewithEmailAccount
for email-account-level operations
Do NOT use POST API routes for mutations - use server actions instead
No need for try/catch in GET routes when using middleware
Export response types from GET routes
apps/web/app/api/**/route.ts
: Wrap all GET API route handlers withwithAuth
orwithEmailAccount
middleware for authentication and authorization.
Export response types from GET API routes for type-safe client usage.
Do not use try/catch in GET API routes when using authentication middleware; rely on centralized error handling.
Files:
apps/web/app/api/scheduled-actions/execute/route.ts
!{.cursor/rules/*.mdc}
📄 CodeRabbit Inference Engine (.cursor/rules/cursor-rules.mdc)
Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location
Files:
apps/web/app/api/scheduled-actions/execute/route.ts
apps/web/utils/scheduled-actions/executor.ts
apps/web/app/api/outlook/webhook/process-history-item.ts
**/*.ts
📄 CodeRabbit Inference Engine (.cursor/rules/form-handling.mdc)
**/*.ts
: The same validation should be done in the server action too
Define validation schemas using Zod
Files:
apps/web/app/api/scheduled-actions/execute/route.ts
apps/web/utils/scheduled-actions/executor.ts
apps/web/app/api/outlook/webhook/process-history-item.ts
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/logging.mdc)
**/*.{ts,tsx}
: UsecreateScopedLogger
for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when usingcreateScopedLogger
Only use.with()
on a logger instance within a specific function, not for a global loggerImport Prisma in the project using
import prisma from "@/utils/prisma";
**/*.{ts,tsx}
: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
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 parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.
Files:
apps/web/app/api/scheduled-actions/execute/route.ts
apps/web/utils/scheduled-actions/executor.ts
apps/web/app/api/outlook/webhook/process-history-item.ts
**/api/**/route.ts
📄 CodeRabbit Inference Engine (.cursor/rules/security.mdc)
**/api/**/route.ts
: ALL API routes that handle user data MUST use appropriate authentication and authorization middleware (withAuth or withEmailAccount).
ALL database queries in API routes MUST be scoped to the authenticated user/account (e.g., include userId or emailAccountId in query filters).
Always validate that resources belong to the authenticated user before performing operations (resource ownership validation).
UsewithEmailAccount
middleware for API routes that operate on a specific email account (i.e., use or requireemailAccountId
).
UsewithAuth
middleware for API routes that operate at the user level (i.e., use or require onlyuserId
).
UsewithError
middleware (with proper validation) for public endpoints, custom authentication, or cron endpoints.
Cron endpoints MUST usewithError
middleware and validate the cron secret usinghasCronSecret(request)
orhasPostCronSecret(request)
.
Cron endpoints MUST capture unauthorized attempts withcaptureException
and return a 401 status for unauthorized requests.
All parameters in API routes MUST be validated for type, format, and length before use.
Request bodies in API routes MUST be validated using Zod schemas before use.
All Prisma queries in API routes MUST only return necessary fields and never expose sensitive data.
Error messages in API routes MUST not leak internal information or sensitive data; use generic error messages and SafeError where appropriate.
API routes MUST use a consistent error response format, returning JSON with an error message and status code.
AllfindUnique
andfindFirst
Prisma calls in API routes MUST include ownership filters (e.g., userId or emailAccountId).
AllfindMany
Prisma calls in API routes MUST be scoped to the authenticated user's data.
Never use direct object references in API routes without ownership checks (prevent IDOR vulnerabilities).
Prevent mass assignment vulnerabilities by only allowing explicitly whitelisted fields in update operations in AP...
Files:
apps/web/app/api/scheduled-actions/execute/route.ts
apps/web/app/api/**/*.{ts,js}
📄 CodeRabbit Inference Engine (.cursor/rules/security-audit.mdc)
apps/web/app/api/**/*.{ts,js}
: All API route handlers in 'apps/web/app/api/' must use authentication middleware: withAuth, withEmailAccount, or withError (with custom authentication logic).
All Prisma queries in API routes must include user/account filtering (e.g., emailAccountId or userId in WHERE clauses) to prevent unauthorized data access.
All parameters used in API routes must be validated before use; do not use parameters from 'params' or request bodies directly in queries without validation.
Request bodies in API routes should use Zod schemas for validation.
API routes should only return necessary fields using Prisma's 'select' and must not include sensitive data in error messages.
Error messages in API routes must not reveal internal details; use generic errors and SafeError for user-facing errors.
All QStash endpoints (API routes called via publishToQstash or publishToQstashQueue) must use verifySignatureAppRouter to verify request authenticity.
All cron endpoints in API routes must use hasCronSecret or hasPostCronSecret for authentication.
Do not hardcode weak or plaintext secrets in API route files; secrets must not be directly assigned as string literals.
Review all new withError usage in API routes to ensure custom authentication is implemented where required.
Files:
apps/web/app/api/scheduled-actions/execute/route.ts
apps/web/app/api/outlook/webhook/process-history-item.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}
: Don't useelements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...
Files:
apps/web/app/api/scheduled-actions/execute/route.ts
apps/web/utils/scheduled-actions/executor.ts
apps/web/app/api/outlook/webhook/process-history-item.ts
!pages/_document.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/ultracite.mdc)
!pages/_document.{js,jsx,ts,tsx}
: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.
Files:
apps/web/app/api/scheduled-actions/execute/route.ts
apps/web/utils/scheduled-actions/executor.ts
apps/web/app/api/outlook/webhook/process-history-item.ts
apps/web/utils/**
📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)
Create utility functions in
utils/
folder for reusable logic
Files:
apps/web/utils/scheduled-actions/executor.ts
apps/web/utils/**/*.ts
📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)
apps/web/utils/**/*.ts
: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size
Files:
apps/web/utils/scheduled-actions/executor.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: elie222
PR: elie222/inbox-zero#537
File: apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx:30-34
Timestamp: 2025-07-08T13:14:07.449Z
Learning: The clean onboarding page in apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx is intentionally Gmail-specific and should show an error for non-Google email accounts rather than attempting to support multiple providers.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.890Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/index.mdc:0-0
Timestamp: 2025-07-18T15:05:56.618Z
Learning: Guidelines for working with Gmail API
apps/web/app/api/scheduled-actions/execute/route.ts (13)
Learnt from: CR
PR: elie222/inbox-zero#0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-07-18T15:04:30.448Z
Learning: Applies to apps/web/app/api/**/route.ts : Use withEmailAccount
for email-account-level operations
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.220Z
Learning: Applies to apps/web/utils/actions/*.ts : Use actionClient
when both authenticated user context and a specific emailAccountId
are needed. The emailAccountId
must be bound when calling the action from the client.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : Use withEmailAccount
middleware for API routes that operate on a specific email account (i.e., use or require emailAccountId
).
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-07-18T15:05:16.118Z
Learning: Applies to apps/web/utils/actions/**/*.ts : Use server actions (with next-safe-action
) for all mutations (create/update/delete operations); do NOT use POST API routes for mutations.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-07-20T09:00:41.952Z
Learning: Applies to apps/web/app/api/**/*.{ts,js} : All Prisma queries in API routes must include user/account filtering (e.g., emailAccountId or userId in WHERE clauses) to prevent unauthorized data access.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-07-18T15:05:26.685Z
Learning: Applies to app/api/**/route.ts : Always wrap the handler with withAuth
or withEmailAccount
for consistent error handling and authentication in GET API routes.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : ALL database queries in API routes MUST be scoped to the authenticated user/account (e.g., include userId or emailAccountId in query filters).
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-07-18T15:05:26.685Z
Learning: Applies to app/api/**/route.ts : Use Prisma for database queries in GET API routes.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.220Z
Learning: Applies to apps/web/utils/actions/*.ts : Access necessary context (like userId
, emailAccountId
, etc.) provided by the safe action client via the ctx
object in the .action()
handler.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.220Z
Learning: Applies to apps/web/utils/actions/*.ts : Implement all server actions using the next-safe-action
library for type safety, input validation, context management, and error handling. Refer to apps/web/utils/actions/safe-action.ts
for client definitions (actionClient
, actionClientUser
, adminActionClient
).
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/prisma.mdc:0-0
Timestamp: 2025-06-23T12:26:53.882Z
Learning: In this project, Prisma should be imported using 'import prisma from "@/utils/prisma";' in TypeScript files.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-19T17:50:28.259Z
Learning: The utils
folder also contains core app logic such as Next.js Server Actions and Gmail API requests.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : All findUnique
and findFirst
Prisma calls in API routes MUST include ownership filters (e.g., userId or emailAccountId).
apps/web/utils/scheduled-actions/executor.ts (11)
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.220Z
Learning: Applies to apps/web/utils/actions/*.ts : Use actionClient
when both authenticated user context and a specific emailAccountId
are needed. The emailAccountId
must be bound when calling the action from the client.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.220Z
Learning: Applies to apps/web/utils/actions/*.ts : Use adminActionClient
for actions restricted to admin users.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.890Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.220Z
Learning: Applies to apps/web/utils/actions/*.ts : Use actionClientUser
when only authenticated user context (userId
) is needed.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.220Z
Learning: Applies to apps/web/utils/actions/*.ts : Access necessary context (like userId
, emailAccountId
, etc.) provided by the safe action client via the ctx
object in the .action()
handler.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.220Z
Learning: Applies to apps/web/utils/actions/*.ts : Implement all server actions using the next-safe-action
library for type safety, input validation, context management, and error handling. Refer to apps/web/utils/actions/safe-action.ts
for client definitions (actionClient
, actionClientUser
, adminActionClient
).
Learnt from: CR
PR: elie222/inbox-zero#0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-07-18T15:04:30.448Z
Learning: Applies to apps/web/app/api/**/route.ts : Use withEmailAccount
for email-account-level operations
Learnt from: elie222
PR: #537
File: apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx:30-34
Timestamp: 2025-07-08T13:14:07.449Z
Learning: The clean onboarding page in apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx is intentionally Gmail-specific and should show an error for non-Google email accounts rather than attempting to support multiple providers.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-07-18T15:05:16.118Z
Learning: Applies to apps/web/utils/actions/**/*.ts : Use server actions (with next-safe-action
) for all mutations (create/update/delete operations); do NOT use POST API routes for mutations.
Learnt from: CR
PR: elie222/inbox-zero#0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-07-18T15:04:30.448Z
Learning: Applies to apps/web/utils/actions/**/*.ts : Use server actions for all mutations (create/update/delete operations)
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-07-18T17:27:46.378Z
Learning: Applies to /api//route.ts : Use withEmailAccount
middleware for API routes that operate on a specific email account (i.e., use or require emailAccountId
).
apps/web/app/api/outlook/webhook/process-history-item.ts (10)
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.890Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Include relevant context in log messages for LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Document complex AI logic with clear comments in LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Implement fallbacks for AI failures in LLM-related functions.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Follow the standard structure for LLM-related functions: use a scoped logger, define a Zod schema for output, validate inputs early, separate system and user prompts, log inputs and outputs, call chatCompletionObject with proper configuration, and return validated results.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Define clear interfaces for complex input/output structures in LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Remove excessive whitespace and truncate long inputs in LLM prompts.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Keep system prompts and user prompts separate in LLM-related code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-07-18T15:06:40.243Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.ts : Implement early returns for invalid inputs in LLM-related functions.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/task-list.mdc:0-0
Timestamp: 2025-07-18T17:28:14.611Z
Learning: Applies to {TASKS,ASSISTANT_CHAT,.md} : Keep the 'Relevant Files' section updated with file paths, brief descriptions of each file's purpose, and status indicators (e.g., ✅) for completed components.
🧬 Code Graph Analysis (2)
apps/web/app/api/scheduled-actions/execute/route.ts (2)
apps/web/utils/email/provider.ts (1)
createEmailProvider
(1609-1624)apps/web/utils/scheduled-actions/executor.ts (1)
executeScheduledAction
(25-102)
apps/web/utils/scheduled-actions/executor.ts (2)
apps/web/utils/logger.ts (1)
createScopedLogger
(17-65)apps/web/utils/ai/types.ts (1)
EmailForAction
(4-13)
⏰ 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). (4)
- GitHub Check: Static Code Analysis Js
- GitHub Check: Jit Security
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (10)
apps/web/app/api/outlook/webhook/process-history-item.ts (7)
1-24
: LGTM! Clean import organization and proper provider abstraction.The imports are well-organized and correctly use the provider-agnostic utilities as intended. The use of
type
imports for TypeScript types follows best practices.
93-135
: Good assistant email handling with proper early returns.The assistant email detection and processing logic is well-structured with appropriate early returns and proper logging. The message transformation for the
processAssistantEmail
function is comprehensive.
137-150
: Verify outbound detection logic is case-insensitive.The outbound detection uses
toLowerCase()
which is correct for email comparison. The delegation tohandleOutbound
is appropriate.
152-195
: Excellent defensive programming with proper error handling.The unsubscribed email blocking and cold email detection logic is well-structured with appropriate conditional checks and proper logging. The use of
shouldRunColdEmailBlocker
helper function improves readability.
242-255
: Robust error handling with appropriate message filtering.The error handling correctly identifies and handles specific Outlook API errors (ItemNotFound, ResourceNotFound) while allowing other errors to propagate. This is appropriate for webhook processing where messages may be deleted between notification and processing.
257-342
: Well-structured outbound message handling with proper error isolation.The
handleOutbound
function demonstrates excellent error handling patterns:
- Uses
Promise.allSettled
to prevent one operation from blocking another- Logs errors without throwing to maintain processing flow
- Proper sequential execution where cleanup must happen after tracking/outbound handling
344-354
: Clean utility function with clear logic.The
shouldRunColdEmailBlocker
function is well-structured with clear boolean logic and proper type checking.apps/web/app/api/scheduled-actions/execute/route.ts (1)
47-57
: Security: Enforce ownership filter on scheduledAction lookupThe
findUnique
call isn’t scoping to the owningemailAccountId
, which can lead to cross-account data exposure if someone obtains a validscheduledActionId
. Update the query to include theemailAccountId
filter and handle “not found” as unauthorized.– File:
apps/web/app/api/scheduled-actions/execute/route.ts
– Location: theprisma.scheduledAction
lookup (around lines 47–57)Suggested change:
- const scheduledAction = await prisma.scheduledAction.findUnique({ - where: { id: payload.scheduledActionId }, - include: { - emailAccount: { include: { account: true } }, - executedRule: true, - }, - }); + const scheduledAction = await prisma.scheduledAction.findFirst({ + where: { + id: payload.scheduledActionId, + emailAccountId: payload.emailAccountId, + }, + include: { + emailAccount: { include: { account: true } }, + executedRule: true, + }, + }); + if (!scheduledAction) { + return new NextResponse(null, { status: 404 }); + }This ensures only the scheduled action belonging to the given
emailAccountId
is returned, preventing unauthorized access.⛔ Skipped due to learnings
Learnt from: CR PR: elie222/inbox-zero#0 File: .cursor/rules/security-audit.mdc:0-0 Timestamp: 2025-07-20T09:00:41.952Z Learning: Applies to apps/web/app/api/**/*.{ts,js} : Review all new withError usage in API routes to ensure custom authentication is implemented where required.
Learnt from: CR PR: elie222/inbox-zero#0 File: .cursor/rules/security.mdc:0-0 Timestamp: 2025-07-18T17:27:46.378Z Learning: Applies to **/api/**/route.ts : All `findUnique` and `findFirst` Prisma calls in API routes MUST include ownership filters (e.g., userId or emailAccountId).
Learnt from: CR PR: elie222/inbox-zero#0 File: .cursor/rules/security-audit.mdc:0-0 Timestamp: 2025-07-20T09:00:41.952Z Learning: Applies to apps/web/app/api/**/*.{ts,js} : All Prisma queries in API routes must include user/account filtering (e.g., emailAccountId or userId in WHERE clauses) to prevent unauthorized data access.
Learnt from: CR PR: elie222/inbox-zero#0 File: .cursor/rules/security.mdc:0-0 Timestamp: 2025-07-18T17:27:46.378Z Learning: Applies to **/api/**/route.ts : ALL database queries in API routes MUST be scoped to the authenticated user/account (e.g., include userId or emailAccountId in query filters).
Learnt from: CR PR: elie222/inbox-zero#0 File: .cursor/rules/security.mdc:0-0 Timestamp: 2025-07-18T17:27:46.378Z Learning: Applies to **/api/**/route.ts : Never use direct object references in API routes without ownership checks (prevent IDOR vulnerabilities).
Learnt from: CR PR: elie222/inbox-zero#0 File: .cursor/rules/security-audit.mdc:0-0 Timestamp: 2025-07-20T09:00:41.952Z Learning: During code review, verify that all new API routes follow security patterns: middleware usage, user scoping, input validation, and error handling.
Learnt from: CR PR: elie222/inbox-zero#0 File: .cursor/rules/security-audit.mdc:0-0 Timestamp: 2025-07-20T09:00:41.952Z Learning: Applies to apps/web/app/api/**/*.{ts,js} : All QStash endpoints (API routes called via publishToQstash or publishToQstashQueue) must use verifySignatureAppRouter to verify request authenticity.
Learnt from: CR PR: elie222/inbox-zero#0 File: .cursor/rules/fullstack-workflow.mdc:0-0 Timestamp: 2025-07-18T15:05:16.118Z Learning: Applies to apps/web/utils/actions/**/*.ts : Use server actions (with `next-safe-action`) for all mutations (create/update/delete operations); do NOT use POST API routes for mutations.
Learnt from: CR PR: elie222/inbox-zero#0 File: apps/web/CLAUDE.md:0-0 Timestamp: 2025-07-18T15:04:30.448Z Learning: Applies to apps/web/app/api/**/route.ts : Use `withEmailAccount` for email-account-level operations
Learnt from: CR PR: elie222/inbox-zero#0 File: .cursor/rules/security.mdc:0-0 Timestamp: 2025-07-18T17:27:46.378Z Learning: Applies to **/api/**/route.ts : All `findMany` Prisma calls in API routes MUST be scoped to the authenticated user's data.
Learnt from: CR PR: elie222/inbox-zero#0 File: .cursor/rules/server-actions.mdc:0-0 Timestamp: 2025-07-18T17:27:58.220Z Learning: Applies to apps/web/utils/actions/*.ts : Use `actionClient` when both authenticated user context and a specific `emailAccountId` are needed. The `emailAccountId` must be bound when calling the action from the client.
apps/web/utils/scheduled-actions/executor.ts (2)
25-28
: Good refactoring to support multiple email providersThe function signature change to accept a generic
EmailProvider
client is a clean abstraction that enables support for multiple email providers. The implementation correctly passes the client to all dependent functions.
205-206
: No action needed: Header mapping is consistent
Both Gmail and Outlook providers normalize the raw header arrays into aheaders
object with directsubject
anddate
properties. AccessingemailMessage.headers.subject
andemailMessage.headers.date
inexecuteDelayedAction
is therefore safe across providers, and the existing fallbacks guard against any rare missing values.
Claude encountered an error —— View job I'll analyze this and get back to you. |
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Documentation
Chores
Style
Tests