Skip to content

Conversation

@arjunkomath
Copy link
Member

@arjunkomath arjunkomath commented Aug 13, 2025

Summary by CodeRabbit

  • New Features

    • Press N to open the inline task creator (disabled while typing).
    • Keyboard shortcut hint added to the Add Task button (visible on medium+ screens).
    • Submitting a task now closes the form and clears the input.
  • Documentation

    • Contributor guidance rewritten with strict build/test restrictions and alternative validation approaches.
  • Refactor

    • Permissions now use a unified context and standardize permission error handling.

@github-advanced-security
Copy link

This pull request sets up GitHub code scanning for this repository. Once the scans have completed and the checks have passed, the analysis results for this pull request branch will appear on this overview. Once you merge this pull request, the 'Security' tab will show more code scanning analysis results (for example, for the default branch). Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. For more information about GitHub code scanning, check out the documentation.

@vercel
Copy link

vercel bot commented Aug 13, 2025

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

Project Deployment Preview Updated (UTC)
manage Ready Ready Preview Aug 17, 2025 2:06am

@coderabbitai
Copy link

coderabbitai bot commented Aug 13, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Reworks permission helpers to accept a PermissionContext and short-circuit org admins; updates TRPC routers to call the new signatures and return TRPCError on denials. Adds a Kbd component and an "N" global shortcut to open the inline task form; expands CLAUDE.md with strict build/test restrictions.

Changes

Cohort / File(s) Summary
Documentation policy update
CLAUDE.md
Replaces Development Workflow Guidance with a comprehensive "CRITICAL BUILD AND TEST RESTRICTIONS" section (duplicated in two locations), reorganizing following sections. No code changes.
UI: Kbd component
components/ui/kbd.tsx
Adds Kbd forwardRef component wrapping <kbd> with default styling and exported as Kbd.
Task form UX + shortcut
components/form/task.tsx
Adds global keydown listener for plain "N" (ignores inputs/textarea/contentEditable) to open inline task creation; shows Kbd "N" in Add Task button on md+; submitting closes form and clears input; imports useEffect and Kbd.
Permissions core (ctx-based)
lib/permissions/index.ts
Adds PermissionContext type ({ db, userId, isOrgAdmin }); changes signatures to canEditProject(ctx, projectId) and canViewProject(ctx, projectId); uses ctx.db/ctx.userId and short-circuits when ctx.isOrgAdmin.
TRPC routers → ctx permissions & errors
trpc/routers/events.ts
Replaces legacy permission calls with canViewProject(ctx, projectId) / canEditProject(ctx, projectId); imports TRPCError and throws TRPCError({ code: "FORBIDDEN", ... }) on denials for affected procedures (getByDate, getByWeek, delete, upsert).
TRPC routers → ctx permissions & errors
trpc/routers/projects.ts
Migrates permission checks to ctx-based helpers; introduces TRPCError for several forbidden paths; optimizes internal canEdit computation in getProjectById to avoid an extra DB call.
TRPC routers → ctx permissions
trpc/routers/tasks.ts
Updates all permission checks to canViewProject(ctx, ...) / canEditProject(ctx, ...); adds TRPCError imports and uses FORBIDDEN for initial checks (getTaskLists, createTaskList); other error flows mostly preserved.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Browser
  participant TaskForm
  User->>Browser: Press "N"
  Browser->>TaskForm: keydown (N) handler (ignores inputs/contentEditable)
  TaskForm->>TaskForm: setIsCreating(true)
  User->>TaskForm: Submit task
  TaskForm->>TaskForm: save -> setIsCreating(false), clear input
Loading
sequenceDiagram
  participant Client
  participant TRPCRouter
  participant Permissions
  participant DB
  Client->>TRPCRouter: Project action (e.g., update)
  TRPCRouter->>Permissions: canEditProject(ctx, projectId)
  Permissions->>Permissions: if ctx.isOrgAdmin then return true
  Permissions->>DB: checkProjectPermission(ctx.db, ctx.userId)
  DB-->>Permissions: permission result
  Permissions-->>TRPCRouter: allow / deny
  TRPCRouter-->>Client: proceed or throw TRPCError FORBIDDEN
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • feat: Permissions #160 — Modifies project permissions schema/helpers; directly related to the ctx-based permission signature changes.
  • fix: Enforce permissions #162 — Adjusts permission checks in server routers (events/tasks/projects); overlaps with router updates here.
  • Setup tRPC #99 — Introduced ctx-based TRPC setup and router-context usage; relevant to migrating helpers to PermissionContext.

Poem

I tapped N, a tiny key,
A task popped up for only me.
The gatekeeper checks with a twitching whisker,
"Admins pass" — the rules grow crisper.
I nibble docs and hop with glee. 🐰✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch main

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@arjunkomath
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Aug 13, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@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: 4

🔭 Outside diff range comments (2)
components/form/task.tsx (1)

40-44: Close-on-submit without error handling risks data loss and double-submit.

If action() throws, the dialog still closes and input clears. Also no submit in-flight guard. Recommend adding isSaving + try/catch and disabling Save/Enter until completion.

Outside the changed lines, adapt as follows:

// state
const [isSaving, setIsSaving] = useState(false);

// handler
const handleSubmit = useCallback(async () => {
  if (isSaving) return;
  const name = value.trim();
  if (!name) return;
  setIsSaving(true);
  try {
    await action(name);
    setValue("");
    setIsCreating(false);
  } catch (err) {
    // TODO: surface a toast or error state
    console.error("Failed to create task", err);
  } finally {
    setIsSaving(false);
  }
}, [action, value, isSaving]);

// input Enter handler
onKeyDown={(e) => {
  if (e.key === "Enter" && !e.shiftKey) {
    e.preventDefault();
    handleSubmit();
  }
}}

// Save button
<Button type="button" onClick={handleSubmit} disabled={isSaving || !value.trim()}>
  {isSaving ? "Saving..." : "Save"}
</Button>
trpc/routers/events.ts (1)

126-136: Missing permission check in getByMonth exposes events across projects

Unlike getByDate/getByWeek, getByMonth performs no access check. This can leak event data to unauthorized users.

Apply this diff to enforce view permissions:

       .query(async ({ ctx, input }) => {
         const { date, projectId } = input;

+        // Check if user has permission to view this project
+        const hasAccess = await canViewProject(ctx, projectId);
+        if (!hasAccess) {
+          throw new Error("Project access denied");
+        }
+
         const { start, end } = getStartEndMonthRangeInUtc(ctx.timezone, date);

If you adopt TRPCError (see separate comment), switch the throw to TRPCError with FORBIDDEN.

🧹 Nitpick comments (5)
CLAUDE.md (1)

150-226: Clarify audience and scope; otherwise solid guidance.

The new “CRITICAL BUILD AND TEST RESTRICTIONS” section is clear and aligns with the repository’s long-term learning about not rebuilding unless asked. Two small improvements:

  • Make it explicit this policy applies to assistants/automation (not human contributors), to avoid misinterpretation by new devs scanning docs.
  • If this guidance appears elsewhere in the file, deduplicate and link to a single canonical section to reduce drift.

This aligns with the retrieved learning: “Do not build the app after every change… only rebuild when asked or after large changes.”

components/ui/kbd.tsx (1)

4-16: Type the component to the intrinsic "kbd" element; minor class cleanup.

Using HTMLElement works, but typing to the intrinsic element improves correctness and IntelliSense. Also, “opacity-100” is redundant.

Apply:

-const Kbd = React.forwardRef<
-	HTMLElement,
-	React.HTMLAttributes<HTMLElement>
->(({ className, ...props }, ref) => (
+const Kbd = React.forwardRef<
+  React.ElementRef<"kbd">,
+  React.ComponentPropsWithoutRef<"kbd">
+>(({ className, ...props }, ref) => (
   <kbd
     ref={ref}
     className={cn(
-      "pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100",
+      "pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground",
       className,
     )}
     {...props}
   />
 ))
components/form/task.tsx (1)

49-61: Expose the shortcut to assistive tech.

Add aria-keyshortcuts so screen readers can discover the “N” shortcut. Keep the visual Kbd.

-        <Button
+        <Button
           type="button"
           size="sm"
+          aria-keyshortcuts="N"
           onClick={(e) => {
             e.preventDefault();
             setIsCreating(true);
           }}
           className="flex items-center gap-2"
         >
           Add task
           <Kbd className="hidden md:inline-flex">N</Kbd>
         </Button>
trpc/routers/events.ts (1)

104-112: Use computed start-of-week for full weekly coverage

Currently start is now, which omits earlier days in the same week. Use the helper’s computed start for the entire week window.

-      const now = new Date();
-      const { end } = getStartEndWeekRangeInUtc(
-        ctx.timezone,
-        now,
-      );
+      const { start, end } = getStartEndWeekRangeInUtc(
+        ctx.timezone,
+        new Date(),
+      );
 
       const events = await ctx.db.query.calendarEvent
-        .findMany(buildEventsQuery(projectId, now, end))
+        .findMany(buildEventsQuery(projectId, start, end))
         .execute();
lib/permissions/index.ts (1)

48-66: Add per-request memoization to cut duplicate DB calls

Routers often call canViewProject/canEditProject multiple times in a single request. Memoize results per (userId, projectId) to avoid redundant queries.

Example approach (conceptual):

  • Add a Map<string, boolean> on ctx (e.g., ctx.permissionCache).
  • Key format: ${ctx.userId}:${projectId}:view|edit.
  • Check cache before queries; write-through on miss.

This keeps behavior the same while reducing DB overhead under repeated checks.

Also applies to: 68-86

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2480862 and b868d0c.

📒 Files selected for processing (7)
  • CLAUDE.md (1 hunks)
  • components/form/task.tsx (3 hunks)
  • components/ui/kbd.tsx (1 hunks)
  • lib/permissions/index.ts (2 hunks)
  • trpc/routers/events.ts (4 hunks)
  • trpc/routers/projects.ts (5 hunks)
  • trpc/routers/tasks.ts (8 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-07T13:08:07.363Z
Learnt from: CR
PR: techulus/manage#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-07T13:08:07.363Z
Learning: Do not build the app after every change you make, only rebuild the app when asked or after making large changes spanning many files

Applied to files:

  • CLAUDE.md
🧬 Code Graph Analysis (5)
trpc/routers/tasks.ts (1)
lib/permissions/index.ts (2)
  • canViewProject (68-86)
  • canEditProject (48-66)
trpc/routers/events.ts (1)
lib/permissions/index.ts (2)
  • canViewProject (68-86)
  • canEditProject (48-66)
trpc/routers/projects.ts (1)
lib/permissions/index.ts (2)
  • canEditProject (48-66)
  • canViewProject (68-86)
lib/permissions/index.ts (2)
drizzle/types.ts (1)
  • Database (15-15)
drizzle/schema.ts (1)
  • project (34-45)
components/form/task.tsx (1)
components/ui/kbd.tsx (1)
  • Kbd (19-19)
🔇 Additional comments (8)
trpc/routers/tasks.ts (1)

31-31: Permission API Migration Complete — No Legacy Calls Detected

All canViewProject / canEditProject invocations now use the new two-argument signature (ctx, projectId), and imports reference @/lib/permissions. A search found no remaining three-argument usages. Confirm that your TRPC context still populates isOrgAdmin as expected; otherwise, everything’s ready to merge.

trpc/routers/events.ts (4)

73-76: Switched to ctx-based view permission check — good alignment with new API

Using canViewProject(ctx, projectId) matches the new PermissionContext-based helpers and enables org-admin short-circuiting.


99-102: Consistent ctx-based permission in getByWeek — looks good

Same as above; the migration is correct and semantically equivalent with the new permission model.


156-156: Edit permission check switched to ctx — correct

Deletion now benefits from org-admin bypass and consistent permission semantics.


213-213: Edit permission check switched to ctx — correct

Upsert now uses the new helper signature; this is consistent with other routers.

lib/permissions/index.ts (3)

48-54: Org-admin short-circuit is correct and well-placed

Early return for admins reduces DB work and expresses intent clearly.


56-66: Permission check + creator fallback LGTM

checkProjectPermission first, then creator fallback preserves backward compatibility. Good sequencing.


69-86: View permission mirrors edit semantics correctly

Admin bypass, explicit permission, then creator fallback — consistent and predictable.

@arjunkomath
Copy link
Member Author

@coderabbitai Please review

@coderabbitai
Copy link

coderabbitai bot commented Aug 16, 2025

@arjunkomath I'll conduct a comprehensive review of your PR that adds keyboard shortcuts for creating tasks. This includes the new Kbd component, keyboard shortcut implementation, and the significant permission system refactoring.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (4)
trpc/routers/tasks.ts (1)

253-286: Missing authorization check in getListById leaks data

getListById returns task list details (with tasks and user info) without verifying that the caller can view the project. This is an authorization gap.

Add a canViewProject(ctx, data.projectId) check with TRPCError:

 		.query(async ({ ctx, input }) => {
 			const data = await ctx.db.query.taskList
 				.findFirst({
 					where: eq(taskList.id, +input.id),
 					with: {
 						tasks: {
 							orderBy: [asc(task.position)],
 							with: {
 								creator: {
 									columns: {
 										firstName: true,
 										imageUrl: true,
 									},
 								},
 								assignee: {
 									columns: {
 										firstName: true,
 										imageUrl: true,
 									},
 								},
 							},
 						},
 					},
 				})
 				.execute();
 
 			if (!data) {
 				throw new Error(`TaskList with id ${input.id} not found`);
 			}
 
+			const hasAccess = await canViewProject(ctx, data.projectId);
+			if (!hasAccess) {
+				throw new TRPCError({
+					code: "FORBIDDEN",
+					message: "Project access denied",
+				});
+			}
 
 			return data;
 		}),
trpc/routers/events.ts (1)

131-141: Missing authorization check in getByMonth leaks calendar events

getByMonth does not verify view permission before returning events. Add canViewProject(ctx, projectId) and throw TRPCError on denial, mirroring getByDate/getByWeek.

 		.query(async ({ ctx, input }) => {
 			const { date, projectId } = input;
 
+			const hasAccess = await canViewProject(ctx, projectId);
+			if (!hasAccess) {
+				throw new TRPCError({
+					code: "FORBIDDEN",
+					message: "Project access denied",
+				});
+			}
+
 			const { start, end } = getStartEndMonthRangeInUtc(ctx.timezone, date);
 
 			const events = await ctx.db.query.calendarEvent
 				.findMany(buildEventsQuery(projectId, start, end))
 				.execute();
 
 			return events;
 		}),
trpc/routers/projects.ts (2)

250-258: getComments lacks authorization; add view check (and consider aligning input with addComment)

Anyone authenticated can fetch comments for any roomId. Add canViewProject(ctx, …) to prevent data leaks. Since addComment requires projectId already, consider accepting projectId here too for consistent checks.

-	getComments: protectedProcedure
-		.input(
-			z.object({
-				roomId: z.string(),
-			}),
-		)
+	getComments: protectedProcedure
+		.input(
+			z.object({
+				roomId: z.string(),
+				projectId: z.number(),
+			}),
+		)
 		.query(async ({ ctx, input }) => {
+			const hasAccess = await canViewProject(ctx, input.projectId);
+			if (!hasAccess) {
+				throw new TRPCError({
+					code: "FORBIDDEN",
+					message: "Project access denied",
+				});
+			}
 			const comments = await ctx.db.query.comment.findMany({
 				where: eq(comment.roomId, input.roomId),
 				orderBy: desc(comment.createdAt),
 				with: {
 					creator: true,
 				},
 			});
 
 			return comments;
 		}),

335-355: getActivities lacks authorization; add view check

Prevent activity feed leaks by ensuring the caller can view the project.

 		.query(async ({ ctx, input }) => {
+			const hasAccess = await canViewProject(ctx, input.projectId);
+			if (!hasAccess) {
+				throw new TRPCError({
+					code: "FORBIDDEN",
+					message: "Project access denied",
+				});
+			}
 			const activities = await ctx.db.query.activity
 				.findMany({
 					with: {
 						actor: {
 							columns: {
 								id: true,
 								firstName: true,
 								imageUrl: true,
 							},
 						},
 					},
 					where: eq(activity.projectId, input.projectId),
 					orderBy: [desc(activity.createdAt)],
 					limit: 25,
 					offset: input.offset,
 				})
 				.execute();
 
 			return activities;
 		}),
🧹 Nitpick comments (9)
trpc/routers/tasks.ts (7)

2-2: Import looks good; consider applying TRPCError consistently across this router

You’ve introduced TRPCError; several permission-denial paths below still throw generic Error. Follow-up comments include targeted diffs to standardize.


174-179: Prefer TRPCError for authorization failures

Return proper error codes to clients instead of generic Error.

Apply this diff:

-      throw new Error(
-        "You don't have permission to update task lists in this project",
-      );
+      throw new TRPCError({
+        code: "FORBIDDEN",
+        message: "Project edit access denied",
+      });

227-232: Prefer TRPCError for authorization failures

Keep error semantics consistent with the rest of the router.

-      throw new Error(
-        "You don't have permission to delete task lists in this project",
-      );
+      throw new TRPCError({
+        code: "FORBIDDEN",
+        message: "Project edit access denied",
+      });

316-321: Prefer TRPCError for authorization failures

Align createTask with the TRPCError usage adopted elsewhere.

-      throw new Error(
-        "You don't have permission to add tasks to this project",
-      );
+      throw new TRPCError({
+        code: "FORBIDDEN",
+        message: "Project edit access denied",
+      });

437-442: Prefer TRPCError for authorization failures

Use FORBIDDEN for consistent client behavior.

-      throw new Error(
-        "You don't have permission to update tasks in this project",
-      );
+      throw new TRPCError({
+        code: "FORBIDDEN",
+        message: "Project edit access denied",
+      });

508-513: Prefer TRPCError for authorization failures

Consistent error semantics across endpoints.

-      throw new Error(
-        "You don't have permission to delete tasks in this project",
-      );
+      throw new TRPCError({
+        code: "FORBIDDEN",
+        message: "Project edit access denied",
+      });

545-550: Prefer TRPCError for authorization failures

Standardize to TRPCError(FORBIDDEN).

-      throw new Error(
-        "You don't have permission to modify tasks in this project",
-      );
+      throw new TRPCError({
+        code: "FORBIDDEN",
+        message: "Project edit access denied",
+      });
trpc/routers/projects.ts (2)

271-276: Prefer TRPCError for authorization failures in addComment

Standardize error semantics across the router.

-      throw new Error(
-        "You don't have permission to add comments to this project",
-      );
+      throw new TRPCError({
+        code: "FORBIDDEN",
+        message: "Project edit access denied",
+      });

320-327: Ensure Authorization on Comment Deletion

The deleteComment mutation currently trusts the caller’s input.projectId, allowing any authenticated user to delete arbitrary comments by supplying a project they can edit. Instead, we must:

  • Fetch the comment by input.id, including its createdByUser and roomId.
  • Derive the actual projectId from the associated Room.
  • Enforce “author OR project-editor” authorization.
  • Delete the comment and log activity with the derived projectId.
   .mutation(async ({ ctx, input }) => {
-    await ctx.db.delete(comment).where(eq(comment.id, input.id));
+    // 1) Load comment, including its owner and room
+    const existing = await ctx.db.query.comment.findFirst({
+      where: eq(comment.id, input.id),
+      columns: { createdByUser: true, roomId: true },
+    });
+    if (!existing) {
+      throw new TRPCError({ code: "NOT_FOUND", message: "Comment not found" });
+    }
+
+    // 2) Derive actual projectId from the room
+    const { projectId: actualProjectId } = await ctx.db.query.room.findFirstOrThrow({
+      where: eq(room.id, existing.roomId),
+      columns: { projectId: true },
+    });
+
+    // 3) Author‐or‐editor check
+    if (
+      existing.createdByUser !== ctx.userId &&
+      !(await canEditProject(ctx, actualProjectId))
+    ) {
+      throw new TRPCError({
+        code: "FORBIDDEN",
+        message: "Insufficient permissions to delete this comment",
+      });
+    }
+
+    // 4) Safe delete
+    await ctx.db.delete(comment).where(eq(comment.id, input.id));
     await logActivity({
       action: "deleted",
       type: "comment",
-      projectId: input.projectId,
+      projectId: actualProjectId,
     });
   }),

I wasn’t able to locate any roomIdprojectId mapping in the codebase automatically. Please confirm which field on comment links it to a Room and how that room maps to a project so we can fully lock down this mutation.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b868d0c and cbf9af3.

📒 Files selected for processing (5)
  • components/form/task.tsx (3 hunks)
  • lib/permissions/index.ts (2 hunks)
  • trpc/routers/events.ts (5 hunks)
  • trpc/routers/projects.ts (7 hunks)
  • trpc/routers/tasks.ts (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/permissions/index.ts
  • components/form/task.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-07T13:08:07.393Z
Learnt from: CR
PR: techulus/manage#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-07T13:08:07.393Z
Learning: Applies to trpc/routers/**/*.ts : tRPC procedures that require authentication must use `protectedProcedure`

Applied to files:

  • trpc/routers/events.ts
🧬 Code Graph Analysis (3)
trpc/routers/events.ts (1)
lib/permissions/index.ts (2)
  • canViewProject (68-86)
  • canEditProject (48-66)
trpc/routers/tasks.ts (1)
lib/permissions/index.ts (2)
  • canViewProject (68-86)
  • canEditProject (48-66)
trpc/routers/projects.ts (1)
lib/permissions/index.ts (2)
  • canEditProject (48-66)
  • canViewProject (68-86)
🔇 Additional comments (12)
trpc/routers/tasks.ts (2)

31-37: Good: standardized permission check and TRPCError on view denial

Using canViewProject(ctx, …) and TRPCError(FORBIDDEN) aligns with the new PermissionContext and tRPC semantics.


74-80: Good: standardized edit check and TRPCError on denial

This matches the ctx-based permission helpers and returns structured errors to clients.

trpc/routers/events.ts (4)

1-1: Import looks good; aligns with structured error handling

TRPCError is properly imported for standardized error responses.


73-79: Good: permission check with TRPCError(FORBIDDEN) in getByDate

This matches the ctx-based helpers and consistent error semantics.


101-107: Good: permission check with TRPCError(FORBIDDEN) in getByWeek

Consistent with the rest of the router.


160-166: Good: delete enforces edit permission with TRPCError

Checks against the event’s projectId and returns FORBIDDEN on denial.

trpc/routers/projects.ts (6)

2-2: TRPCError import aligns with the new error handling approach

Import is used consistently below.


36-39: Good: createProject enforces org-admin requirement with TRPCError

Clear semantics and consistent error code.


115-121: Good: updateProject uses ctx-based permission and TRPCError

Matches the new PermissionContext helpers and standard error semantics.


175-181: Good: deleteProject uses ctx-based permission and TRPCError

Consistent with the rest of the codebase.


210-216: Good: getProjectById uses view-permission with TRPCError(FORBIDDEN)

Consistent with other routers.


235-236: Nice optimization: compute canEdit in-memory using fetched data and userRole

Avoids an extra DB round-trip. Good call.

@arjunkomath arjunkomath merged commit 14032ff into release Aug 17, 2025
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants