Skip to content

OUT-2898 | Show tasks assigned to clients within a company on company details page#1205

Merged
arpandhakal merged 3 commits intomainfrom
OUT-2898
May 7, 2026
Merged

OUT-2898 | Show tasks assigned to clients within a company on company details page#1205
arpandhakal merged 3 commits intomainfrom
OUT-2898

Conversation

@arpandhakal
Copy link
Copy Markdown
Collaborator

@arpandhakal arpandhakal commented May 6, 2026

Summary

  • When an internal user enters CRM preview mode for a company, also include tasks assigned to clients of that company (TEAM TASKS) and IU tasks shared with those clients (SHARED WITH TEAM). Previously only tasks assigned to the company itself and IU tasks shared with the company were visible.
  • Mirrored the same access rule in CommentService so comments stay aligned with task visibility (and fixed a latent strict parse(clientId) that would have thrown for any company-only auth context).
  • The shared task/comment filter is now async; copilot.getCompanyClients is only called in the new IU-company-preview branch and the result is memoized per request to avoid duplicate calls.

Context

Linear: OUT-2898

Today the company-details CRM view shows:

  1. Tasks assigned to the company
  2. IU tasks shared with the company

This PR adds:
3. Tasks assigned to clients within the company
4. IU tasks shared with those clients

Other flows (client preview, CU portal, normal IU listing) skip the new branch entirely, so they incur no extra I/O — only an await on a synchronously resolved promise.

Test plan

  • As an IU, enter CRM preview for a company that has clients with their own tasks → confirm those tasks now appear in the company task list
  • In the same view, confirm IU-assigned tasks shared with one of the company's clients appear (SHARED WITH TEAM)
  • Existing visibility unchanged: tasks assigned to the company and IU tasks shared with the company still appear
  • Open one of the new tasks and confirm comments load (CommentService access path)
  • Client preview (an actual CU) still sees only their own + company-shared tasks — no leakage of other clients' tasks
  • CU portal user (no internalUserId) does not gain access to other clients' tasks
  • Normal IU board listing performance unchanged (no extra Copilot calls in non-preview flows)

Testing

image Task assigned to a client of the company is also visible for company CRM. image Task associated with a client of the company is also visible for company CRM.

🤖 Generated with Claude Code

…M company preview

When an internal user enters CRM preview mode for a company, also include
tasks assigned to clients of that company (TEAM TASKS) and IU tasks shared
with those clients (SHARED WITH TEAM). Previously only company-level tasks
and IU tasks shared with the company itself were visible.

The shared task/comment filter is now async and fetches the company's
clients via copilot.getCompanyClients only when the new IU-company-preview
branch fires; the result is memoized per request to avoid duplicate calls.
Other flows (client preview, CU portal, normal IU) skip the new branch
entirely, so they incur no extra I/O — only an await on a synchronously
resolved promise.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 6, 2026

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 6, 2026

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

Project Deployment Actions Updated (UTC)
tasks-app Ready Ready Preview, Comment May 7, 2026 6:16am

Request Review

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 6, 2026

Greptile Summary

This PR extends the IU company-preview CRM view to include tasks assigned to the company's individual clients (TEAM TASKS) and IU tasks shared with those clients (SHARED WITH TEAM), in addition to the previously visible company-level tasks. CommentService is updated in parallel to keep comment access aligned with task visibility, and the latent parse(clientId) bug is fixed in both places.

  • getClientOrCompanyAssigneeFilter becomes async in both TasksSharedService and CommentService, adding a new isIuCompanyPreview branch that calls getCompanyClients and expands the Prisma OR filter to cover client-assigned tasks and client associations.
  • All call sites in tasks.service.ts and public/public.service.ts are updated to await the now-async buildTaskPermissions.
  • Per-request memoization via _companyClientIdsPromise prevents duplicate Copilot API calls when both the task and comment filters run in the same request.

Confidence Score: 4/5

Safe to merge; the new IU-company-preview branch is isolated and does not affect CU portal or normal IU flows.

The new isIuCompanyPreview branch is correctly gated and the two findings are edge-case hardening items that do not affect correct-token requests in normal operation.

tasksShared.service.ts and comment.service.ts both carry the parse(companyId) asymmetry and duplicate memoization cache.

Important Files Changed

Filename Overview
src/app/api/tasks/tasksShared.service.ts Adds async getClientOrCompanyAssigneeFilter with isIuCompanyPreview branch and memoized getCompanyClientIds; minor: parse(companyId) could throw raw ZodError in an invalid-token edge case, and the memoization cache doesn't key by companyId
src/app/api/comments/comment.service.ts Mirrors the task visibility fix for comments; fixes the latent strict parse(clientId) in this copy of the filter; same parse(companyId) asymmetry remains
src/app/api/tasks/tasks.service.ts Mechanically adds await to all buildTaskPermissions call sites; no logic changes
src/app/api/tasks/public/public.service.ts Mechanically adds await to all buildTaskPermissions call sites; no logic changes

Reviews (1): Last reviewed commit: "feat(OUT-2898): show tasks assigned to c..." | Re-trigger Greptile

protected getClientOrCompanyAssigneeFilter(includeAssociatedTask: boolean = true): Prisma.TaskWhereInput {
protected async getClientOrCompanyAssigneeFilter(includeAssociatedTask: boolean = true): Promise<Prisma.TaskWhereInput> {
const clientId = z.string().uuid().safeParse(this.user.clientId).data
const companyId = z.string().uuid().parse(this.user.companyId)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Strict parse(companyId) not patched alongside clientId

The PR explicitly fixed parse(clientId)safeParse(clientId).data to handle the company-only auth context. The adjacent z.string().uuid().parse(this.user.companyId) is still strict: if the guard user.clientId || user.companyId fires with only clientId set (e.g., a client token that somehow lacks a companyId), this throws a raw ZodError (500) instead of a clean APIError. The same issue exists at the same line in comment.service.ts.

Comment thread src/app/api/tasks/tasksShared.service.ts Outdated
@arpandhakal arpandhakal self-assigned this May 6, 2026
Comment thread src/app/api/comments/comment.service.ts Outdated
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 7, 2026

Deployment failed with the following error:

Deploying Serverless Functions to multiple regions is restricted to the Pro and Enterprise plans.

Learn More: https://vercel.link/multiple-function-regions

Copy link
Copy Markdown
Collaborator

@priosshrsth priosshrsth left a comment

Choose a reason for hiding this comment

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

lgtm

@arpandhakal arpandhakal merged commit 4d62187 into main May 7, 2026
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