Skip to content

Conversation

@github-actions
Copy link
Contributor

This is an automated pull request to merge feat/implement-new-design-system into dev.
It was created by the [Auto Pull Request] action.

@vercel
Copy link

vercel bot commented Jan 12, 2026

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

Project Deployment Review Updated (UTC)
app Ready Ready Preview, Comment Jan 14, 2026 8:47pm
portal Ready Ready Preview, Comment Jan 14, 2026 8:47pm

@cursor
Copy link

cursor bot commented Jan 12, 2026

PR Summary

Implements the new design system across the app and adds a scoped assistant chat history API.

  • UI/Navigation overhaul: Replaces legacy layouts with AppShell (navbar, sidebar, rail), adds AppShellWrapper, AppShellRailNav, and AppSidebar; converts pages (e.g., Frameworks, Integrations, People, Cloud Tests) to PageLayout/PageHeader; swaps inputs/tabs/components to @trycompai/design-system.
  • Policies: New overview with lightweight client charts (PolicyStatusChart, PolicyAssigneeChart) and PolicyChartsClient; server/client aggregation via computePoliciesOverview; filters/actions wired to non-archived policies; DB query now selects assignee data; removed /policies/all route in favor of /policies and updated revalidation/redirects.
  • People: Consolidates People, Employee Tasks, and Devices into tabbed PeoplePageTabs; redirects legacy /people/all, /people/dashboard, /people/devices to /people.
  • Assistant Chat API (API v1): Adds GET/PUT/DELETE /assistant-chat/history with user/org scoping, TTL-based storage via Upstash Redis, DTO validation, and module wiring.
  • Build/config: Adds ESLint flat config for app; updates Next config to transpile design system and icons; adds design system dependency; switches lint script to eslint; introduces agents.md authoring guidelines; MCP config adds design-system MCP.
  • Misc: Minor API/service tweaks (e.g., ordering/selects, small refactors); policy archive/delete flows redirect to /policies.

Written by Cursor Bugbot for commit 9969695. This will update automatically on new commits. Configure here.

)}
<AppShellNavItem icon={<SidebarClose className="size-4" />} onClick={toggleSidebar}>
Collapse sidebar
</AppShellNavItem>
Copy link

Choose a reason for hiding this comment

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

Sidebar collapse state doesn't persist to server cookie

High Severity

The "Collapse sidebar" button calls toggleSidebar() from useAppShell() which only toggles the design system's internal state. Unlike the old SidebarCollapseButton which called both setIsCollapsed() to update the SidebarProvider context and updateSidebarState() to persist to the server cookie, this new implementation does neither. As a result, the sidebar collapsed state won't persist across page refreshes, and components using useSidebar().isCollapsed (like SidebarLogo on line 184) will have stale state that doesn't reflect the visual state after toggling.

Fix in Cursor Fix in Web

hasAuditorRole,
isOnlyAuditor,
}: AppSidebarProps) {
const pathname = usePathname();
Copy link

Choose a reason for hiding this comment

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

Missing null check for pathname could cause runtime crash

Medium Severity

The usePathname() hook returns string | null, but pathname is used without a null check at line 138 where pathname.split('/') is called. If pathname is null, this will throw a TypeError. The code inconsistently uses optional chaining later at line 144 (pathname?.startsWith()), indicating awareness of nullability but incomplete handling. The sibling component AppShellRailNav.tsx correctly handles this with usePathname() ?? ''.

Additional Locations (1)

Fix in Cursor Fix in Web

);
})}
</TableBody>
</Table>
Copy link

Choose a reason for hiding this comment

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

Pagination controls removed from risks table

High Severity

The refactored RisksTable removes all pagination UI controls. The old implementation used DataTable with DataTablePagination, which provided page navigation buttons, page size selector, and current page display. The new implementation renders a basic Table that maps over all mergedRisks without any pagination controls. While the pageCount prop is still received and data fetching respects pagination query params (page, perPage), users have no way to navigate between pages - they would need to manually edit URL parameters. For organizations with many risks, this makes the table unusable beyond the first page of results.

Fix in Cursor Fix in Web

}
}),
);
}
Copy link

Choose a reason for hiding this comment

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

S3 presigned URLs computed but never used

Medium Severity

The layout generates S3 presigned URLs for all organization logos via getSignedUrl calls, but these URLs are never displayed. The logoUrls object is passed to AppShellWrapper, which destructures it but never uses it. The refactored OrganizationSwitcher now displays colored dots instead of logos and doesn't receive the logoUrls prop. This results in unnecessary S3 API calls on every page load within the app, adding latency and API costs for work that produces no user-visible result.

Additional Locations (1)

Fix in Cursor Fix in Web

published: 'oklch(0.6 0.16 145)', // --success (green)
draft: 'oklch(0.75 0.15 85)', // --warning (yellow)
archived: 'oklch(0.556 0 0)', // --muted-foreground (gray)
needs_review: 'oklch(0.58 0.22 27)', // --destructive (red)
Copy link

Choose a reason for hiding this comment

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

Hardcoded chart colors break dark mode support

Medium Severity

The chart colors were changed from CSS variables (e.g., hsl(var(--chart-positive))) to hardcoded oklch values. These static color values won't respond to theme changes, meaning the charts will display with the same colors in both light and dark modes. Other charts in the codebase (like ComplianceProgressChart, PeopleChart, TasksChart) still use CSS variables for theme-adaptive colors, creating an inconsistent user experience.

Additional Locations (1)

Fix in Cursor Fix in Web

updatedAt: true,
},
orderBy: [{ lastPublishedAt: 'desc' }, { updatedAt: 'desc' }],
orderBy: { name: 'desc' },
Copy link

Choose a reason for hiding this comment

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

Trust portal policies sorted in reverse alphabetical order

High Severity

The orderBy clause was changed from date-based sorting ([{ lastPublishedAt: 'desc' }, { updatedAt: 'desc' }]) to { name: 'desc' }. This causes policies in the trust portal to be sorted in reverse alphabetical order (Z to A) instead of by most recently published. For external trust portal users reviewing an organization's compliance policies, this is counterintuitive and likely unintended. If alphabetical sorting was desired, it would typically be 'asc' (A to Z).

Fix in Cursor Fix in Web

});
setIsStatusChangeDialogOpen(true);
setIsSubmitting(false);
};
Copy link

Choose a reason for hiding this comment

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

Published policy changes no longer require approval workflow

Medium Severity

The approval workflow for changes to already-published policies has been removed. Previously, modifying a published policy would trigger the approval dialog requiring an approver to be selected. Now, changes to published policies only show a simple confirmation dialog and bypass the approval process entirely. This is a significant behavioral change that may allow unauthorized modifications to published policies without proper review.

Fix in Cursor Fix in Web

@vercel vercel bot temporarily deployed to Preview – portal January 13, 2026 20:30 Inactive
</span>{' '}
<span className="text-foreground">{current?.toString() || '(empty)'}</span>
</li>
{String(current) || '(empty)'}
Copy link

Choose a reason for hiding this comment

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

Audit log shows literal "null" instead of "(empty)"

Low Severity

The code changed from previous?.toString() || '(empty)' to String(previous) || '(empty)'. When previous or current is null/undefined, String(null) returns the literal string "null" which is truthy, so the || '(empty)' fallback never triggers. Users will see "null" or "undefined" as text in audit logs instead of the intended "(empty)" placeholder.

Fix in Cursor Fix in Web

</Suspense>
<PolicyTailoringProvider statuses={{}}>
<PolicyFilters policies={nonArchivedPolicies} />
</PolicyTailoringProvider>
Copy link

Choose a reason for hiding this comment

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

Policy tailoring status indicators completely broken

High Severity

The PolicyTailoringProvider is passed hardcoded empty statuses={{}}, which breaks the real-time policy tailoring status feature. The old implementation fetched onboarding data and used useRealtimeRun to subscribe to trigger.dev runs, populating the provider with live status updates. This allowed showing "Tailoring", "Queued", "Processing" indicators on policies and a progress bar during onboarding. The new page completely omits the onboarding query and real-time subscription, so tailoring status will never display and policies won't be blocked during active tailoring.

Fix in Cursor Fix in Web

return null;
}

const approverName = `${policy?.approver?.user?.name} (${policy?.approver?.user?.email})`;
Copy link

Choose a reason for hiding this comment

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

Approver name displays "undefined" when approver is null

Low Severity

The approverName template literal doesn't handle the case where policy.approver is null. Since the type explicitly allows approver to be null, when isPendingApproval is true but approver data isn't loaded or doesn't exist, users will see "Waiting for undefined (undefined) to review and approve this policy." instead of a meaningful message.

Fix in Cursor Fix in Web

},
{
id: 'people',
path: `/${organization.id}/people/all`,
Copy link

Choose a reason for hiding this comment

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

Navigation links to deprecated route causing unnecessary redirect

Low Severity

The new navigation components link to /people/all, but this PR also adds a redirect from /people/all to /people. This creates unnecessary server-side redirects on every People navigation click. The links in AppSidebar, AppShellWrapper, and AppShellRailNav should point directly to /people instead of the deprecated /people/all route.

Additional Locations (2)

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants