Skip to content

Conversation

@drifter089
Copy link
Owner

@drifter089 drifter089 commented Dec 29, 2025

Summary

Consolidates repeated cache invalidation patterns into a shared utility and standardizes user name function naming across the codebase.

Key Changes

  • Add invalidateDashboardCache() utility to cache-strategy.ts
  • Update 5 routers and 1 service to use the new utility (12 call sites consolidated)
  • Standardize user name functions: client-side getUserDisplayName(), server-side fetchUserDisplayName()
  • Add shared internal helpers for role enrichment in organization-members.ts
  • Update CLAUDE.md to document new utilities and remove outdated duplication notes

Summary by CodeRabbit

  • Refactor
    • Consolidated cache invalidation logic across dashboard operations for improved consistency and reduced redundancy.
    • Streamlined user display name resolution to minimize unnecessary server calls while standardizing name formatting.

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

@vercel
Copy link

vercel bot commented Dec 29, 2025

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

Project Deployment Review Updated (UTC)
org-os Ready Ready Preview, Comment Dec 29, 2025 8:29pm

@coderabbitai
Copy link

coderabbitai bot commented Dec 29, 2025

📝 Walkthrough

Walkthrough

This PR consolidates cache invalidation for dashboard mutations across multiple routers by introducing a centralized invalidateDashboardCache helper function. It also refactors user display name helpers (renaming client and server versions for clarity) and consolidates role enrichment logic to reduce duplication and unnecessary API calls.

Changes

Cohort / File(s) Summary
Cache Invalidation Consolidation
src/server/api/utils/cache-strategy.ts
New exported function invalidateDashboardCache that wraps tag construction and delegates to invalidateCacheByTags, replacing manual cache tag assembly across routers.
Cache Invalidation in Routers
src/server/api/routers/dashboard.ts, metric.ts, manual-metric.ts, pipeline.ts
Replaced invalidateCacheByTags calls with invalidateDashboardCache(db, organizationId, teamId), removing manual tag construction in all mutation handlers.
Cache Invalidation in Services
src/server/api/services/transformation/chart-generator.ts
Updated chart transformers to use invalidateDashboardCache instead of building dashboard cache tags manually.
User Display Name Client Helper
src/lib/helpers/get-user-name.ts
Renamed exported function from getUserName to getUserDisplayName for clarity and consistency.
User Display Name Server Helper
src/server/api/utils/get-user-display-name.ts
Renamed async function from getUserDisplayName to fetchUserDisplayName to distinguish server-side async lookup from client-side helper.
User Display Name Usage Updates
src/components/metric/role-assignment.tsx, src/hooks/use-optimistic-role-update.ts, src/server/api/routers/role.ts
Updated imports and calls to use getUserDisplayName (client) or fetchUserDisplayName (server) as appropriate. Removed internal getAssignedUserName helper.
Role Enrichment Consolidation
src/server/api/utils/organization-members.ts
Introduced internal helpers enrichRoleWithName and getMemberNameMapIfNeeded to reduce duplicated logic in enrichRolesWithUserNames and enrichChartRolesWithUserNames, avoiding unnecessary API calls.
Documentation
CLAUDE.md
Updated to reflect consolidated component approach and single dashboard cache invalidation strategy.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A rabbit's cheer for cleaner code,
Cache tags gathered on one happy road,
Names now fetchèd and displayed just right,
Roles enriched with nary a duplicate bite!
Consolidation makes this burrow bright! 🌟

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objectives of the PR: consolidating cache invalidation patterns and standardizing user name functions across the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 92.31% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 607d95f and 7b37a5b.

📒 Files selected for processing (13)
  • CLAUDE.md
  • src/components/metric/role-assignment.tsx
  • src/hooks/use-optimistic-role-update.ts
  • src/lib/helpers/get-user-name.ts
  • src/server/api/routers/dashboard.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/utils/cache-strategy.ts
  • src/server/api/utils/get-user-display-name.ts
  • src/server/api/utils/organization-members.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Use TypeScript 5.9 with strict type checking for all frontend and backend code

Use tRPC dual API pattern: in Server Components, make direct calls using import { api } from '@/trpc/server'; in Client Components, use React hooks with TanStack Query using import { api } from '@/trpc/react'. Server calls are 10x faster than client-side queries.

Files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/utils/get-user-display-name.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/lib/helpers/get-user-name.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
src/server/api/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

For tRPC cache invalidation after mutations, use the invalidateCacheByTags() utility with appropriate cache tags (e.g., team_${teamId}) to ensure cache consistency.

Files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/utils/get-user-display-name.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use pre-commit hooks (Husky + lint-staged) which automatically run ESLint auto-fix and Prettier formatting on staged files. Configure import sorting with @trivago/prettier-plugin-sort-imports using inline type imports.

Files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/utils/get-user-display-name.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/lib/helpers/get-user-name.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
src/server/api/routers/**/*.ts

📄 CodeRabbit inference engine (GEMINI.md)

src/server/api/routers/**/*.ts: In tRPC procedures, never assume authentication; always use helpers like getTeamAndVerifyAccess to verify access before operations
Be careful when modifying team save logic related to EditSession model, which handles locking for concurrent team editing

Always use protectedProcedure or workspaceProcedure for tRPC routes, and include authorization checks using helpers from src/server/api/utils/authorization.ts (getMetricAndVerifyAccess, getRoleAndVerifyAccess, getTeamAndVerifyAccess) to verify resources belong to the user's organization.

Files:

  • src/server/api/routers/role.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
src/hooks/**/*.ts{,x}

📄 CodeRabbit inference engine (CLAUDE.md)

src/hooks/**/*.ts{,x}: For role mutations with TanStack Query, implement optimistic updates using the pattern: 1) onMutate with optimistic update, 2) setData with server response (critical - use server response before invalidate), 3) invalidate for background refresh, 4) onError with rollback to previousData. Use the shared use-optimistic-role-update.ts hook.
For dashboard role-metric assignments, update both the role cache (role.getByTeamId) and dashboard cache (dashboard.getDashboardCharts) optimistically during mutations to maintain consistency across both views.

Files:

  • src/hooks/use-optimistic-role-update.ts
src/**/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Prefer Server Components for initial data fetching; use Client Components ('use client') only for interactivity

Files:

  • src/components/metric/role-assignment.tsx
src/**/*/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Client Components must use import { api } from '@/trpc/react' for standard HTTP/Hooks wrapper

Files:

  • src/components/metric/role-assignment.tsx
src/components/**/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Place colocated components in _components/ folders next to their parent component

Files:

  • src/components/metric/role-assignment.tsx
**/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Use Tailwind CSS 4 for styling with shadcn/ui and Radix UI primitive components

Files:

  • src/components/metric/role-assignment.tsx
src/components/metric/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Extract shared dashboard card patterns by consolidating dashboard-metric-card.tsx and public-dashboard-metric-card.tsx into a single component with a readOnly mode instead of maintaining separate components.

Files:

  • src/components/metric/role-assignment.tsx
**/*.md

📄 CodeRabbit inference engine (GEMINI.md)

Do not create random .md documentation files unless explicitly asked; use CLAUDE.md or GEMINI.md for reference documentation

Do not create random .md documentation files when implementing features. Provide explanations in chat messages, add comments in code where necessary, and only update existing documentation (CLAUDE.md, README.md) if required. Only create documentation files if explicitly requested.

Files:

  • CLAUDE.md
🧠 Learnings (28)
📓 Common learnings
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/dashboard/[teamId]/**/*.{ts,tsx} : Dashboard cache updates for role-metric assignments must update both `role.getByTeamId` and `dashboard.getDashboardCharts` caches during mutations. Use onMutate for optimistic updates on both caches, then invalidate both on success.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/hooks/**/*.ts{,x} : For dashboard role-metric assignments, update both the role cache (`role.getByTeamId`) and dashboard cache (`dashboard.getDashboardCharts`) optimistically during mutations to maintain consistency across both views.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/**/*role*mutation*.{ts,tsx} : For role mutations, use cache pipeline with two operations: (1) onMutate for optimistic update, (2) onSuccess with both setData(updatedRole) using server response AND invalidate() for background refresh. Always use server response data in setData before invalidate to ensure Prisma Accelerate cache consistency.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/server/api/routers/**/*.ts : After mutations, invalidate cache tags using `invalidateCacheByTags(ctx.db, [``tag_${id}``])` to trigger background cache updates with Prisma Accelerate.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/server/api/**/*.ts : For tRPC cache invalidation after mutations, use the `invalidateCacheByTags()` utility with appropriate cache tags (e.g., `team_${teamId}`) to ensure cache consistency.
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/server/api/**/*.ts : For tRPC cache invalidation after mutations, use the `invalidateCacheByTags()` utility with appropriate cache tags (e.g., `team_${teamId}`) to ensure cache consistency.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/dashboard/[teamId]/**/*.{ts,tsx} : Dashboard cache updates for role-metric assignments must update both `role.getByTeamId` and `dashboard.getDashboardCharts` caches during mutations. Use onMutate for optimistic updates on both caches, then invalidate both on success.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • CLAUDE.md
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/server/api/routers/**/*.ts : After mutations, invalidate cache tags using `invalidateCacheByTags(ctx.db, [``tag_${id}``])` to trigger background cache updates with Prisma Accelerate.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/hooks/**/*.ts{,x} : For dashboard role-metric assignments, update both the role cache (`role.getByTeamId`) and dashboard cache (`dashboard.getDashboardCharts`) optimistically during mutations to maintain consistency across both views.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • CLAUDE.md
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : For canvas node types that reference other entities (e.g., role nodes), store only the ID in node data and fetch display data from TanStack Query cache using dedicated hooks to avoid data duplication and ensure cache consistency.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • CLAUDE.md
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : Canvas auto-save system: Changes trigger markDirty() → Debounce 2s → serializeNodes/Edges → tRPC mutation. Include beforeunload sendBeacon fallback for unsaved changes.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/app/teams/[teamId]/**/*.ts{,x} : Implement auto-save for canvas changes using the pattern: Canvas changes → markDirty() → Debounce 2s → serializeNodes/Edges → tRPC mutation, with beforeunload sendBeacon as fallback.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/app/teams/[teamId]/_components/**/*.tsx : Extract shared role node patterns by consolidating `role-node.tsx` and `public-role-node.tsx` (75% identical) into a single `RoleNodeTemplate` component with an `isEditable` prop.

Applied to files:

  • src/server/api/routers/role.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • CLAUDE.md
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : Cache-first node system: Role nodes store only `roleId` in node.data. Display data must be fetched from TanStack Query cache using the `useRoleData()` hook which queries the `role.getByTeamId` procedure.

Applied to files:

  • src/server/api/routers/role.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/utils/organization-members.ts
  • CLAUDE.md
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/hooks/use-optimistic-role-update.ts : The `use-optimistic-role-update` hook provides shared logic for all role mutations with proper cache layer handling for TanStack Query and Prisma Accelerate. Use this hook in canvas-specific wrappers to add markDirty side effects.

Applied to files:

  • src/server/api/routers/role.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/components/metric/role-assignment.tsx
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/hooks/**/*.ts{,x} : For role mutations with TanStack Query, implement optimistic updates using the pattern: 1) onMutate with optimistic update, 2) setData with server response (critical - use server response before invalidate), 3) invalidate for background refresh, 4) onError with rollback to previousData. Use the shared `use-optimistic-role-update.ts` hook.

Applied to files:

  • src/server/api/routers/role.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/components/metric/role-assignment.tsx
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/**/*role*mutation*.{ts,tsx} : For role mutations, use cache pipeline with two operations: (1) onMutate for optimistic update, (2) onSuccess with both setData(updatedRole) using server response AND invalidate() for background refresh. Always use server response data in setData before invalidate to ensure Prisma Accelerate cache consistency.

Applied to files:

  • src/server/api/routers/role.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/teams/[teamId]/_components/role-node.tsx,src/app/teams/[teamId]/_components/public-role-node.tsx : These role node components are 75% identical and should be consolidated. Extract shared `RoleNodeTemplate` component with `isEditable` prop to DRY up the code.

Applied to files:

  • src/server/api/routers/role.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/lib/metrics/**/*.ts : Metric transformation logic should be organized in `src/lib/metrics/` to support the 3-stage pipeline: Ingestion → Aggregation → Visualization

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to **/*.{ts,tsx} : Use tRPC dual API pattern: in Server Components, make direct calls using `import { api } from '@/trpc/server'`; in Client Components, use React hooks with TanStack Query using `import { api } from '@/trpc/react'`. Server calls are 10x faster than client-side queries.

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/**/*.ts : Server Components must use `import { api } from '@/trpc/server'` for direct DB calls without HTTP overhead

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to **/*.{ts,tsx} : For client components using tRPC, use the React Query pattern with `import { api } from '@/trpc/react'` and access data via `api.[router].[procedure].useQuery()`. For server components, use direct calls with `import { api } from '@/trpc/server'` and await the result.

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: The Metrics Pipeline processes data through 3 stages: DataIngestionTransformer (Raw API → MetricDataPoint), ChartTransformer (MetricDataPoint → Chart Config), and Visualization (Chart Config → Recharts UI)

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: The metrics pipeline follows a three-stage transformation: 1) API → DataPoints via DataIngestionTransformer, 2) DataPoints → ChartConfig via ChartTransformer, 3) ChartConfig → UI via DashboardMetricChart. Use AI-generated transformers for stage 1 and 2.

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/components/member/**/*.tsx : Use the shared `MembersList` component from `src/components/member/member-list.tsx` and `getMemberDisplayInfo()` utility for consistent member display logic (initials/name) across canvas sidebar and org page.

Applied to files:

  • src/lib/helpers/get-user-name.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • CLAUDE.md
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/components/dashboard-metric-card.tsx,src/app/dashboard/[teamId]/_components/public-dashboard-metric-card.tsx : Dashboard metric cards are duplicated with public variant. Consolidate into single component with `readOnly` mode prop instead of maintaining separate components.

Applied to files:

  • src/server/api/routers/manual-metric.ts
  • CLAUDE.md
  • src/server/api/routers/metric.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/components/metric/**/*.tsx : Extract shared dashboard card patterns by consolidating `dashboard-metric-card.tsx` and `public-dashboard-metric-card.tsx` into a single component with a `readOnly` mode instead of maintaining separate components.

Applied to files:

  • src/server/api/routers/manual-metric.ts
  • CLAUDE.md
  • src/server/api/routers/metric.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/server/api/routers/**/*.ts : When adding new tRPC routes, use `protectedProcedure` or `workspaceProcedure` and always verify resource belongs to user's organization using authorization helpers (getMetricAndVerifyAccess, getRoleAndVerifyAccess, getTeamAndVerifyAccess) from '@/server/api/utils/authorization'.

Applied to files:

  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/server/api/routers/**/*.ts : Always use `protectedProcedure` or `workspaceProcedure` for tRPC routes, and include authorization checks using helpers from `src/server/api/utils/authorization.ts` (getMetricAndVerifyAccess, getRoleAndVerifyAccess, getTeamAndVerifyAccess) to verify resources belong to the user's organization.

Applied to files:

  • src/server/api/routers/manual-metric.ts
  • CLAUDE.md
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : Avoid modifying `enrichNodesWithRoleData` flow without understanding the complete canvas serialization logic for saving/loading React Flow nodes to the database

Applied to files:

  • src/server/api/utils/organization-members.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/app/metric/_components/**/*.tsx : Consolidate nearly identical metric dialog wrappers (5 files) by using a factory pattern to reduce duplication across different provider implementations.

Applied to files:

  • src/components/metric/role-assignment.tsx
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : React Flow nodes must store minimal data (e.g., just `roleId`); fetch full Role data from TanStack Query cache in the Node component to keep canvas and sidebars in sync

Applied to files:

  • src/components/metric/role-assignment.tsx
  • CLAUDE.md
🧬 Code graph analysis (9)
src/server/api/utils/cache-strategy.ts (1)
src/server/db.ts (1)
  • db (26-26)
src/server/api/routers/role.ts (1)
src/server/api/utils/get-user-display-name.ts (1)
  • fetchUserDisplayName (14-26)
src/server/api/services/transformation/chart-generator.ts (2)
src/server/api/utils/cache-strategy.ts (1)
  • invalidateDashboardCache (197-206)
src/server/db.ts (1)
  • db (26-26)
src/hooks/use-optimistic-role-update.ts (1)
src/lib/helpers/get-user-name.ts (1)
  • getUserDisplayName (7-17)
src/server/api/routers/manual-metric.ts (1)
src/server/api/utils/cache-strategy.ts (1)
  • invalidateDashboardCache (197-206)
src/components/metric/role-assignment.tsx (1)
src/lib/helpers/get-user-name.ts (1)
  • getUserDisplayName (7-17)
src/server/api/routers/metric.ts (1)
src/server/api/utils/cache-strategy.ts (1)
  • invalidateDashboardCache (197-206)
src/server/api/routers/pipeline.ts (2)
src/server/api/utils/cache-strategy.ts (1)
  • invalidateDashboardCache (197-206)
src/server/db.ts (1)
  • db (26-26)
src/server/api/routers/dashboard.ts (1)
src/server/api/utils/cache-strategy.ts (1)
  • invalidateDashboardCache (197-206)
🔇 Additional comments (14)
src/server/api/utils/organization-members.ts (2)

136-153: LGTM: Clean helper extraction.

The enrichRoleWithName helper consolidates the role enrichment logic nicely. The fallback pattern using User ${role.assignedUserId.substring(0, 8)} provides a reasonable default when a user ID isn't found in the member map.


155-171: LGTM: Efficient conditional fetching.

The getMemberNameMapIfNeeded helper avoids unnecessary API calls by checking if any roles need enrichment first. This is a good performance optimization.

src/server/api/routers/role.ts (1)

15-15: LGTM: Consistent rename to fetchUserDisplayName.

The function rename aligns with the server-side naming convention established in this PR.

Also applies to: 99-99, 172-174

src/server/api/routers/manual-metric.ts (1)

17-17: LGTM: Clean adoption of centralized cache invalidation.

The migration to invalidateDashboardCache consolidates the cache invalidation pattern and improves maintainability.

Also applies to: 92-96

src/hooks/use-optimistic-role-update.ts (1)

5-5: LGTM: Standardized user name resolution.

The migration to the shared getUserDisplayName helper eliminates code duplication and ensures consistent user name resolution across client components.

Also applies to: 51-51

src/server/api/utils/cache-strategy.ts (1)

185-206: LGTM: Well-designed cache invalidation helper.

The invalidateDashboardCache function successfully consolidates the repeated pattern of building dashboard cache tags. The implementation correctly constructs organization-level and optional team-level tags before delegating to invalidateCacheByTags.

src/lib/helpers/get-user-name.ts (1)

1-17: LGTM: Consistent naming convention.

The rename from getUserName to getUserDisplayName establishes clear naming consistency between client-side (synchronous lookup) and server-side (async fetchUserDisplayName) user name resolution.

src/server/api/routers/pipeline.ts (1)

10-10: LGTM: Comprehensive cache invalidation migration.

All pipeline mutation endpoints have been consistently updated to use invalidateDashboardCache, eliminating manual tag construction and improving maintainability across the router.

Also applies to: 53-53, 160-164, 190-194, 236-240, 297-301

src/server/api/utils/get-user-display-name.ts (1)

14-26: LGTM: Clear server-side naming.

The rename to fetchUserDisplayName clearly distinguishes the async server-side WorkOS lookup from the client-side synchronous helper (getUserDisplayName), making the API intent more explicit.

src/server/api/services/transformation/chart-generator.ts (1)

6-6: LGTM! Cache invalidation successfully consolidated.

The replacement of invalidateCacheByTags with invalidateDashboardCache cleanly centralizes the dashboard cache invalidation pattern. Both call sites correctly pass db, organizationId, and teamId (nullable), matching the utility's signature. This eliminates manual tag construction (dashboard_org_${organizationId}, dashboard_team_${teamId}) and reduces duplication across the codebase.

Also applies to: 268-272, 472-476

src/components/metric/role-assignment.tsx (1)

27-27: LGTM! User display name function successfully standardized.

The rename from getUserName to getUserDisplayName improves clarity and aligns with the standardized naming convention across the codebase (client-side: getUserDisplayName, server-side: fetchUserDisplayName). The function signature and call site remain correct, with no behavioral changes.

Also applies to: 140-143

src/server/api/routers/dashboard.ts (1)

9-9: LGTM! Dashboard cache invalidation successfully consolidated.

The migration to invalidateDashboardCache simplifies the mutation by replacing manual cache tag construction with a centralized utility. The call correctly passes ctx.db, ctx.workspace.organizationId, and existing.metric?.teamId (which properly handles optional teamId using optional chaining).

Also applies to: 166-170

src/server/api/routers/metric.ts (1)

12-12: LGTM! All metric mutations correctly use consolidated cache invalidation.

The three mutation endpoints (create, update, delete) have been successfully migrated to use invalidateDashboardCache. Each call site correctly handles optional/nullable teamId values and ensures cache consistency after mutations. This consolidation aligns with the established cache invalidation pattern for Prisma Accelerate.

Based on learnings: cache invalidation after mutations is critical for Prisma Accelerate cache consistency.

Also applies to: 201-205, 240-244, 271-275

CLAUDE.md (1)

373-397: LGTM! Documentation accurately reflects the refactoring.

The updates correctly document:

  1. The new invalidateDashboardCache pattern for tRPC mutations (lines 373-378)
  2. Consolidated component patterns including MembersList (lines 380-386)
  3. Role enrichment utilities in organization-members.ts (lines 387-392)
  4. Standardized user display name functions: client-side getUserDisplayName and server-side fetchUserDisplayName (lines 393-397)

This provides clear guidance for future development and ensures consistency across the codebase.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/server/api/routers/role.ts (1)

118-121: Add organization-level dashboard cache invalidation to all role mutations.

Role mutations currently invalidate team_${teamId} and dashboard_team_${teamId}, but miss the organization-level dashboard cache tag dashboard_org_${organizationId}. Since dashboard queries use both org-level and team-level cache tags, and roles affect dashboard visibility, the org-level tag must also be invalidated.

Current pattern at lines 118-121, 209-212, and 230-233:

await invalidateCacheByTags(ctx.db, [
  `team_${input.teamId}`,
  `dashboard_team_${input.teamId}`,
]);

Required pattern:

await invalidateCacheByTags(ctx.db, [
  `team_${input.teamId}`,
  `dashboard_org_${ctx.workspace.organizationId}`,
  `dashboard_team_${input.teamId}`,
]);

The team_ tag cannot be removed—it's required for role.getByTeamId cache consistency, which invalidateDashboardCache does not handle.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 607d95f and 7b37a5b.

📒 Files selected for processing (13)
  • CLAUDE.md
  • src/components/metric/role-assignment.tsx
  • src/hooks/use-optimistic-role-update.ts
  • src/lib/helpers/get-user-name.ts
  • src/server/api/routers/dashboard.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/utils/cache-strategy.ts
  • src/server/api/utils/get-user-display-name.ts
  • src/server/api/utils/organization-members.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Use TypeScript 5.9 with strict type checking for all frontend and backend code

Use tRPC dual API pattern: in Server Components, make direct calls using import { api } from '@/trpc/server'; in Client Components, use React hooks with TanStack Query using import { api } from '@/trpc/react'. Server calls are 10x faster than client-side queries.

Files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/utils/get-user-display-name.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/lib/helpers/get-user-name.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
src/server/api/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

For tRPC cache invalidation after mutations, use the invalidateCacheByTags() utility with appropriate cache tags (e.g., team_${teamId}) to ensure cache consistency.

Files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/utils/get-user-display-name.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use pre-commit hooks (Husky + lint-staged) which automatically run ESLint auto-fix and Prettier formatting on staged files. Configure import sorting with @trivago/prettier-plugin-sort-imports using inline type imports.

Files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/utils/get-user-display-name.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/lib/helpers/get-user-name.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
src/server/api/routers/**/*.ts

📄 CodeRabbit inference engine (GEMINI.md)

src/server/api/routers/**/*.ts: In tRPC procedures, never assume authentication; always use helpers like getTeamAndVerifyAccess to verify access before operations
Be careful when modifying team save logic related to EditSession model, which handles locking for concurrent team editing

Always use protectedProcedure or workspaceProcedure for tRPC routes, and include authorization checks using helpers from src/server/api/utils/authorization.ts (getMetricAndVerifyAccess, getRoleAndVerifyAccess, getTeamAndVerifyAccess) to verify resources belong to the user's organization.

Files:

  • src/server/api/routers/role.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
src/hooks/**/*.ts{,x}

📄 CodeRabbit inference engine (CLAUDE.md)

src/hooks/**/*.ts{,x}: For role mutations with TanStack Query, implement optimistic updates using the pattern: 1) onMutate with optimistic update, 2) setData with server response (critical - use server response before invalidate), 3) invalidate for background refresh, 4) onError with rollback to previousData. Use the shared use-optimistic-role-update.ts hook.
For dashboard role-metric assignments, update both the role cache (role.getByTeamId) and dashboard cache (dashboard.getDashboardCharts) optimistically during mutations to maintain consistency across both views.

Files:

  • src/hooks/use-optimistic-role-update.ts
src/**/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Prefer Server Components for initial data fetching; use Client Components ('use client') only for interactivity

Files:

  • src/components/metric/role-assignment.tsx
src/**/*/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Client Components must use import { api } from '@/trpc/react' for standard HTTP/Hooks wrapper

Files:

  • src/components/metric/role-assignment.tsx
src/components/**/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Place colocated components in _components/ folders next to their parent component

Files:

  • src/components/metric/role-assignment.tsx
**/*.tsx

📄 CodeRabbit inference engine (GEMINI.md)

Use Tailwind CSS 4 for styling with shadcn/ui and Radix UI primitive components

Files:

  • src/components/metric/role-assignment.tsx
src/components/metric/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Extract shared dashboard card patterns by consolidating dashboard-metric-card.tsx and public-dashboard-metric-card.tsx into a single component with a readOnly mode instead of maintaining separate components.

Files:

  • src/components/metric/role-assignment.tsx
**/*.md

📄 CodeRabbit inference engine (GEMINI.md)

Do not create random .md documentation files unless explicitly asked; use CLAUDE.md or GEMINI.md for reference documentation

Do not create random .md documentation files when implementing features. Provide explanations in chat messages, add comments in code where necessary, and only update existing documentation (CLAUDE.md, README.md) if required. Only create documentation files if explicitly requested.

Files:

  • CLAUDE.md
🧠 Learnings (28)
📓 Common learnings
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/dashboard/[teamId]/**/*.{ts,tsx} : Dashboard cache updates for role-metric assignments must update both `role.getByTeamId` and `dashboard.getDashboardCharts` caches during mutations. Use onMutate for optimistic updates on both caches, then invalidate both on success.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/hooks/**/*.ts{,x} : For dashboard role-metric assignments, update both the role cache (`role.getByTeamId`) and dashboard cache (`dashboard.getDashboardCharts`) optimistically during mutations to maintain consistency across both views.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/**/*role*mutation*.{ts,tsx} : For role mutations, use cache pipeline with two operations: (1) onMutate for optimistic update, (2) onSuccess with both setData(updatedRole) using server response AND invalidate() for background refresh. Always use server response data in setData before invalidate to ensure Prisma Accelerate cache consistency.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/server/api/routers/**/*.ts : After mutations, invalidate cache tags using `invalidateCacheByTags(ctx.db, [``tag_${id}``])` to trigger background cache updates with Prisma Accelerate.
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/server/api/**/*.ts : For tRPC cache invalidation after mutations, use the `invalidateCacheByTags()` utility with appropriate cache tags (e.g., `team_${teamId}`) to ensure cache consistency.
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/server/api/**/*.ts : For tRPC cache invalidation after mutations, use the `invalidateCacheByTags()` utility with appropriate cache tags (e.g., `team_${teamId}`) to ensure cache consistency.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/dashboard/[teamId]/**/*.{ts,tsx} : Dashboard cache updates for role-metric assignments must update both `role.getByTeamId` and `dashboard.getDashboardCharts` caches during mutations. Use onMutate for optimistic updates on both caches, then invalidate both on success.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • CLAUDE.md
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/server/api/routers/**/*.ts : After mutations, invalidate cache tags using `invalidateCacheByTags(ctx.db, [``tag_${id}``])` to trigger background cache updates with Prisma Accelerate.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/hooks/**/*.ts{,x} : For dashboard role-metric assignments, update both the role cache (`role.getByTeamId`) and dashboard cache (`dashboard.getDashboardCharts`) optimistically during mutations to maintain consistency across both views.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/role.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • CLAUDE.md
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : For canvas node types that reference other entities (e.g., role nodes), store only the ID in node data and fetch display data from TanStack Query cache using dedicated hooks to avoid data duplication and ensure cache consistency.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/utils/organization-members.ts
  • CLAUDE.md
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : Canvas auto-save system: Changes trigger markDirty() → Debounce 2s → serializeNodes/Edges → tRPC mutation. Include beforeunload sendBeacon fallback for unsaved changes.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/app/teams/[teamId]/**/*.ts{,x} : Implement auto-save for canvas changes using the pattern: Canvas changes → markDirty() → Debounce 2s → serializeNodes/Edges → tRPC mutation, with beforeunload sendBeacon as fallback.

Applied to files:

  • src/server/api/utils/cache-strategy.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/app/teams/[teamId]/_components/**/*.tsx : Extract shared role node patterns by consolidating `role-node.tsx` and `public-role-node.tsx` (75% identical) into a single `RoleNodeTemplate` component with an `isEditable` prop.

Applied to files:

  • src/server/api/routers/role.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • CLAUDE.md
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/teams/[teamId]/**/*.{ts,tsx} : Cache-first node system: Role nodes store only `roleId` in node.data. Display data must be fetched from TanStack Query cache using the `useRoleData()` hook which queries the `role.getByTeamId` procedure.

Applied to files:

  • src/server/api/routers/role.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/utils/organization-members.ts
  • CLAUDE.md
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/hooks/use-optimistic-role-update.ts : The `use-optimistic-role-update` hook provides shared logic for all role mutations with proper cache layer handling for TanStack Query and Prisma Accelerate. Use this hook in canvas-specific wrappers to add markDirty side effects.

Applied to files:

  • src/server/api/routers/role.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/components/metric/role-assignment.tsx
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/hooks/**/*.ts{,x} : For role mutations with TanStack Query, implement optimistic updates using the pattern: 1) onMutate with optimistic update, 2) setData with server response (critical - use server response before invalidate), 3) invalidate for background refresh, 4) onError with rollback to previousData. Use the shared `use-optimistic-role-update.ts` hook.

Applied to files:

  • src/server/api/routers/role.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/components/metric/role-assignment.tsx
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/**/*role*mutation*.{ts,tsx} : For role mutations, use cache pipeline with two operations: (1) onMutate for optimistic update, (2) onSuccess with both setData(updatedRole) using server response AND invalidate() for background refresh. Always use server response data in setData before invalidate to ensure Prisma Accelerate cache consistency.

Applied to files:

  • src/server/api/routers/role.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/app/teams/[teamId]/_components/role-node.tsx,src/app/teams/[teamId]/_components/public-role-node.tsx : These role node components are 75% identical and should be consolidated. Extract shared `RoleNodeTemplate` component with `isEditable` prop to DRY up the code.

Applied to files:

  • src/server/api/routers/role.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/lib/metrics/**/*.ts : Metric transformation logic should be organized in `src/lib/metrics/` to support the 3-stage pipeline: Ingestion → Aggregation → Visualization

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to **/*.{ts,tsx} : Use tRPC dual API pattern: in Server Components, make direct calls using `import { api } from '@/trpc/server'`; in Client Components, use React hooks with TanStack Query using `import { api } from '@/trpc/react'`. Server calls are 10x faster than client-side queries.

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/**/*.ts : Server Components must use `import { api } from '@/trpc/server'` for direct DB calls without HTTP overhead

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to **/*.{ts,tsx} : For client components using tRPC, use the React Query pattern with `import { api } from '@/trpc/react'` and access data via `api.[router].[procedure].useQuery()`. For server components, use direct calls with `import { api } from '@/trpc/server'` and await the result.

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: The Metrics Pipeline processes data through 3 stages: DataIngestionTransformer (Raw API → MetricDataPoint), ChartTransformer (MetricDataPoint → Chart Config), and Visualization (Chart Config → Recharts UI)

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: The metrics pipeline follows a three-stage transformation: 1) API → DataPoints via DataIngestionTransformer, 2) DataPoints → ChartConfig via ChartTransformer, 3) ChartConfig → UI via DashboardMetricChart. Use AI-generated transformers for stage 1 and 2.

Applied to files:

  • src/server/api/services/transformation/chart-generator.ts
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/components/member/**/*.tsx : Use the shared `MembersList` component from `src/components/member/member-list.tsx` and `getMemberDisplayInfo()` utility for consistent member display logic (initials/name) across canvas sidebar and org page.

Applied to files:

  • src/lib/helpers/get-user-name.ts
  • src/hooks/use-optimistic-role-update.ts
  • src/server/api/utils/organization-members.ts
  • src/components/metric/role-assignment.tsx
  • CLAUDE.md
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/components/dashboard-metric-card.tsx,src/app/dashboard/[teamId]/_components/public-dashboard-metric-card.tsx : Dashboard metric cards are duplicated with public variant. Consolidate into single component with `readOnly` mode prop instead of maintaining separate components.

Applied to files:

  • src/server/api/routers/manual-metric.ts
  • CLAUDE.md
  • src/server/api/routers/metric.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/components/metric/**/*.tsx : Extract shared dashboard card patterns by consolidating `dashboard-metric-card.tsx` and `public-dashboard-metric-card.tsx` into a single component with a `readOnly` mode instead of maintaining separate components.

Applied to files:

  • src/server/api/routers/manual-metric.ts
  • CLAUDE.md
  • src/server/api/routers/metric.ts
  • src/server/api/routers/dashboard.ts
📚 Learning: 2025-12-29T12:52:42.935Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:42.935Z
Learning: Applies to src/server/api/routers/**/*.ts : When adding new tRPC routes, use `protectedProcedure` or `workspaceProcedure` and always verify resource belongs to user's organization using authorization helpers (getMetricAndVerifyAccess, getRoleAndVerifyAccess, getTeamAndVerifyAccess) from '@/server/api/utils/authorization'.

Applied to files:

  • src/server/api/routers/manual-metric.ts
  • src/server/api/routers/metric.ts
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/server/api/routers/**/*.ts : Always use `protectedProcedure` or `workspaceProcedure` for tRPC routes, and include authorization checks using helpers from `src/server/api/utils/authorization.ts` (getMetricAndVerifyAccess, getRoleAndVerifyAccess, getTeamAndVerifyAccess) to verify resources belong to the user's organization.

Applied to files:

  • src/server/api/routers/manual-metric.ts
  • CLAUDE.md
  • src/server/api/routers/pipeline.ts
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : Avoid modifying `enrichNodesWithRoleData` flow without understanding the complete canvas serialization logic for saving/loading React Flow nodes to the database

Applied to files:

  • src/server/api/utils/organization-members.ts
📚 Learning: 2025-12-29T12:52:43.772Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-29T12:52:43.772Z
Learning: Applies to src/app/metric/_components/**/*.tsx : Consolidate nearly identical metric dialog wrappers (5 files) by using a factory pattern to reduce duplication across different provider implementations.

Applied to files:

  • src/components/metric/role-assignment.tsx
📚 Learning: 2025-12-20T22:12:00.576Z
Learnt from: CR
Repo: drifter089/orgOS PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-20T22:12:00.576Z
Learning: Applies to src/app/teams/[teamId]/**/*.tsx : React Flow nodes must store minimal data (e.g., just `roleId`); fetch full Role data from TanStack Query cache in the Node component to keep canvas and sidebars in sync

Applied to files:

  • src/components/metric/role-assignment.tsx
  • CLAUDE.md
🧬 Code graph analysis (9)
src/server/api/utils/cache-strategy.ts (1)
src/server/db.ts (1)
  • db (26-26)
src/server/api/routers/role.ts (1)
src/server/api/utils/get-user-display-name.ts (1)
  • fetchUserDisplayName (14-26)
src/server/api/services/transformation/chart-generator.ts (2)
src/server/api/utils/cache-strategy.ts (1)
  • invalidateDashboardCache (197-206)
src/server/db.ts (1)
  • db (26-26)
src/hooks/use-optimistic-role-update.ts (1)
src/lib/helpers/get-user-name.ts (1)
  • getUserDisplayName (7-17)
src/server/api/routers/manual-metric.ts (1)
src/server/api/utils/cache-strategy.ts (1)
  • invalidateDashboardCache (197-206)
src/components/metric/role-assignment.tsx (1)
src/lib/helpers/get-user-name.ts (1)
  • getUserDisplayName (7-17)
src/server/api/routers/metric.ts (1)
src/server/api/utils/cache-strategy.ts (1)
  • invalidateDashboardCache (197-206)
src/server/api/routers/pipeline.ts (2)
src/server/api/utils/cache-strategy.ts (1)
  • invalidateDashboardCache (197-206)
src/server/db.ts (1)
  • db (26-26)
src/server/api/routers/dashboard.ts (1)
src/server/api/utils/cache-strategy.ts (1)
  • invalidateDashboardCache (197-206)
🔇 Additional comments (14)
src/server/api/utils/organization-members.ts (2)

136-153: LGTM: Clean helper extraction.

The enrichRoleWithName helper consolidates the role enrichment logic nicely. The fallback pattern using User ${role.assignedUserId.substring(0, 8)} provides a reasonable default when a user ID isn't found in the member map.


155-171: LGTM: Efficient conditional fetching.

The getMemberNameMapIfNeeded helper avoids unnecessary API calls by checking if any roles need enrichment first. This is a good performance optimization.

src/server/api/routers/role.ts (1)

15-15: LGTM: Consistent rename to fetchUserDisplayName.

The function rename aligns with the server-side naming convention established in this PR.

Also applies to: 99-99, 172-174

src/server/api/routers/manual-metric.ts (1)

17-17: LGTM: Clean adoption of centralized cache invalidation.

The migration to invalidateDashboardCache consolidates the cache invalidation pattern and improves maintainability.

Also applies to: 92-96

src/hooks/use-optimistic-role-update.ts (1)

5-5: LGTM: Standardized user name resolution.

The migration to the shared getUserDisplayName helper eliminates code duplication and ensures consistent user name resolution across client components.

Also applies to: 51-51

src/server/api/utils/cache-strategy.ts (1)

185-206: LGTM: Well-designed cache invalidation helper.

The invalidateDashboardCache function successfully consolidates the repeated pattern of building dashboard cache tags. The implementation correctly constructs organization-level and optional team-level tags before delegating to invalidateCacheByTags.

src/lib/helpers/get-user-name.ts (1)

1-17: LGTM: Consistent naming convention.

The rename from getUserName to getUserDisplayName establishes clear naming consistency between client-side (synchronous lookup) and server-side (async fetchUserDisplayName) user name resolution.

src/server/api/routers/pipeline.ts (1)

10-10: LGTM: Comprehensive cache invalidation migration.

All pipeline mutation endpoints have been consistently updated to use invalidateDashboardCache, eliminating manual tag construction and improving maintainability across the router.

Also applies to: 53-53, 160-164, 190-194, 236-240, 297-301

src/server/api/utils/get-user-display-name.ts (1)

14-26: LGTM: Clear server-side naming.

The rename to fetchUserDisplayName clearly distinguishes the async server-side WorkOS lookup from the client-side synchronous helper (getUserDisplayName), making the API intent more explicit.

src/server/api/services/transformation/chart-generator.ts (1)

6-6: LGTM! Cache invalidation successfully consolidated.

The replacement of invalidateCacheByTags with invalidateDashboardCache cleanly centralizes the dashboard cache invalidation pattern. Both call sites correctly pass db, organizationId, and teamId (nullable), matching the utility's signature. This eliminates manual tag construction (dashboard_org_${organizationId}, dashboard_team_${teamId}) and reduces duplication across the codebase.

Also applies to: 268-272, 472-476

src/components/metric/role-assignment.tsx (1)

27-27: LGTM! User display name function successfully standardized.

The rename from getUserName to getUserDisplayName improves clarity and aligns with the standardized naming convention across the codebase (client-side: getUserDisplayName, server-side: fetchUserDisplayName). The function signature and call site remain correct, with no behavioral changes.

Also applies to: 140-143

src/server/api/routers/dashboard.ts (1)

9-9: LGTM! Dashboard cache invalidation successfully consolidated.

The migration to invalidateDashboardCache simplifies the mutation by replacing manual cache tag construction with a centralized utility. The call correctly passes ctx.db, ctx.workspace.organizationId, and existing.metric?.teamId (which properly handles optional teamId using optional chaining).

Also applies to: 166-170

src/server/api/routers/metric.ts (1)

12-12: LGTM! All metric mutations correctly use consolidated cache invalidation.

The three mutation endpoints (create, update, delete) have been successfully migrated to use invalidateDashboardCache. Each call site correctly handles optional/nullable teamId values and ensures cache consistency after mutations. This consolidation aligns with the established cache invalidation pattern for Prisma Accelerate.

Based on learnings: cache invalidation after mutations is critical for Prisma Accelerate cache consistency.

Also applies to: 201-205, 240-244, 271-275

CLAUDE.md (1)

373-397: LGTM! Documentation accurately reflects the refactoring.

The updates correctly document:

  1. The new invalidateDashboardCache pattern for tRPC mutations (lines 373-378)
  2. Consolidated component patterns including MembersList (lines 380-386)
  3. Role enrichment utilities in organization-members.ts (lines 387-392)
  4. Standardized user display name functions: client-side getUserDisplayName and server-side fetchUserDisplayName (lines 393-397)

This provides clear guidance for future development and ensures consistency across the codebase.

@drifter089 drifter089 merged commit 6a24460 into main Dec 29, 2025
4 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