Skip to content

[VW-128] Api Key Connector Table Views#97

Open
trummelhadron wants to merge 6 commits intomainfrom
connector-tables
Open

[VW-128] Api Key Connector Table Views#97
trummelhadron wants to merge 6 commits intomainfrom
connector-tables

Conversation

@trummelhadron
Copy link
Contributor

@trummelhadron trummelhadron commented Mar 20, 2026

New table views for each of the 4 connector types (asset, device artifact, remediation, vulnerability)

image

Summary by CodeRabbit

  • New Features

    • Unified "API key connectors" UI: dedicated connectors layout, resource-type routing, searchable/paginated tables, status/type badges, and server-side prefetch for faster loads.
    • New table views for Assets, Remediations, Vulnerabilities, and Device Artifacts with drawer/list variants and improved columns.
  • Removed

    • Legacy connectors list pages for several connector resource routes.
  • Bug Fixes

    • Stricter resource-type validation to correctly return 404 for invalid routes.
  • Chores

    • Improved server error logging and TypeScript diagnostics.

@trummelhadron trummelhadron requested review from 0xcad and timrcm March 20, 2026 18:44
@vercel
Copy link

vercel bot commented Mar 20, 2026

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

Project Deployment Actions Updated (UTC)
viper Ready Ready Preview, Comment Mar 26, 2026 10:58pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
viper-demo Ignored Ignored Mar 26, 2026 10:58pm

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Removes four legacy connector list page modules and adds a new api-key-connectors feature (types, params, hooks, server prefetch/router, UI components/layout) plus new connectors route pages that wire into the new feature; several list UIs were migrated to a DataTable + drawer pattern and minor routing/validation fixes applied.

Changes

Cohort / File(s) Summary
Removed legacy connector pages
src/app/(dashboard)/(rest)/connectors/assets/page.tsx, src/app/(dashboard)/(rest)/connectors/deviceArtifacts/page.tsx, src/app/(dashboard)/(rest)/connectors/remediations/page.tsx, src/app/(dashboard)/(rest)/connectors/vulnerabilities/page.tsx
Deleted default-exported createListPage(...) modules — legacy routing/UI and their paramsLoader/prefetch wiring removed.
New connectors route pages & layout
src/app/(dashboard)/(rest)/connectors/[resourceTypeUrl]/page.tsx, src/app/(dashboard)/(rest)/connectors/[resourceTypeUrl]/items/page.tsx, src/app/(dashboard)/(rest)/connectors/[resourceTypeUrl]/layout.tsx
Adds client and server pages and a client layout that validate resourceTypeUrl, prefetch paginated connector data, and render ConnectorsLayout / ConnectorsList with Suspense/Error boundaries.
API Key Connectors — types & server
src/features/api-key-connectors/types.ts, src/features/api-key-connectors/server/routers.ts, src/features/api-key-connectors/server/params-loader.ts, src/features/api-key-connectors/server/prefetch.ts
Adds Zod schemas/types, connector include selection, TRPC procedure getManyByTypeInternal, a server params loader, and typed prefetch helpers per ResourceType.
API Key Connectors — client hooks & params
src/features/api-key-connectors/params.ts, src/features/api-key-connectors/hooks/use-connectors.ts
Adds shared pagination params and hooks: useConnectorParams() and useSuspenseConnectorsByResourceType() for suspense TRPC queries.
API Key Connectors — UI components
src/features/api-key-connectors/components/columns.tsx, src/features/api-key-connectors/components/connectors.tsx, src/features/api-key-connectors/components/connectors-layout.tsx
New column defs, ConnectorsList, container/header/search/loading/error/empty components, per-resource container/list wrappers, and ConnectorsLayout tabbed navigation.
List UI migrations (DataTable + drawers)
src/features/assets/components/*, src/features/vulnerabilities/components/*, src/features/remediations/components/*, src/features/device-artifacts/components/*
Several lists converted to DataTable-based rendering; new DataList components and "WithDrawer" variants added; columns refactored (actions column separated; new columns for device-artifacts/remediations).
Integrations/resource-type validation rename
src/features/integrations/types.ts, src/features/integrations/components/integrations-layout.tsx, src/app/(dashboard)/(rest)/settings/integrations/[resourceTypeUrl]/page.tsx
Renamed isValidIntegrationKeyisValidResourceTypeKey and switched validation usage to resource-type keys in layouts/pages.
TRPC route & misc
src/app/api/trpc/[trpc]/route.ts, src/lib/schemas.ts, tsconfig.json
Adds an onError logger to tRPC handler, updates a JSDoc comment in userSchema, and enables noErrorTruncation in tsconfig.

Sequence Diagram(s)

sequenceDiagram
  participant Page as Client Page
  participant Loader as Server Loader (connectorsParamsLoader)
  participant Prefetch as Server Prefetch
  participant TRPC as TRPC Router (getManyByTypeInternal)
  participant DB as Prisma DB

  Page->>Loader: read pagination/search params
  Page->>Prefetch: request prefetch for ResourceType
  Prefetch->>TRPC: call getManyByTypeInternal(params + resourceType)
  TRPC->>DB: fetch paginated connectors (where resourceType, include user)
  DB-->>TRPC: return rows + counts
  TRPC-->>Prefetch: return data (cached)
  Prefetch-->>Page: hydrate prefetched data
  Page->>Page: render ConnectorsList (columns, search, pagination)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • 0xcad
  • timrcm
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'VW-128 Api Key Connector Table Views' directly summarizes the main change: adding table views for API key connectors across four resource types.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch connector-tables

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: 2

🧹 Nitpick comments (3)
src/features/api-key-connectors/types.ts (1)

32-34: Consider using PascalCase for the exported type name.

The type paginatedConnectorsByTypeInput uses camelCase, while other types in this file (ConnectorResponse) and TypeScript convention typically use PascalCase for type aliases.

✏️ Suggested fix
-export type paginatedConnectorsByTypeInput = z.infer<
+export type PaginatedConnectorsByTypeInput = z.infer<
   typeof paginatedConnectorInputSchema
 >;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/api-key-connectors/types.ts` around lines 32 - 34, The exported
type name paginatedConnectorsByTypeInput should use PascalCase: rename it to
PaginatedConnectorsByTypeInput and update its declaration to export type
PaginatedConnectorsByTypeInput = z.infer<typeof paginatedConnectorInputSchema>;
then search and update all usages/imports of paginatedConnectorsByTypeInput
across the codebase (tests, consumers, and index exports) to the new
PaginatedConnectorsByTypeInput identifier so imports and references remain
consistent with ConnectorResponse and TS naming conventions.
src/features/api-key-connectors/server/prefetch.ts (1)

1-3: Add 'server-only' directive to prevent client-side imports.

This is a server-side prefetch utility that should not be imported on the client. Adding the directive ensures bundler errors if accidentally imported client-side.

🛡️ Suggested fix
+import "server-only";
+
 import type { inferInput } from "@trpc/tanstack-react-query";
 import { ResourceType } from "@/generated/prisma";
 import { prefetch, trpc } from "@/trpc/server";

As per coding guidelines: "Mark server-side files with 'server-only' directive".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/api-key-connectors/server/prefetch.ts` around lines 1 - 3, Add
the top-of-file "server-only" directive (a single line containing 'server-only')
as the very first line to prevent client-side imports; update src features
referenced symbols such as inferInput, ResourceType, prefetch, and trpc remain
unchanged — just insert the directive before the existing imports so the bundler
will error if this server-side prefetch utility is imported on the client.
src/features/api-key-connectors/components/connectors.tsx (1)

107-117: Inconsistent use of hardcoded string vs enum for resourceType.

DeviceArtifactConnectorsContainer uses the string "Device Artifact" for display, while other containers use ResourceType.* enum values directly. This works because ConnectorsContainer accepts ResourceType | string, but it's inconsistent.

Consider creating a display-name mapping to keep the prop type strict while still showing user-friendly names:

💡 Suggested approach
// At top of file or in a shared utility
const resourceTypeDisplayNames: Record<ResourceType, string> = {
  [ResourceType.Asset]: "Asset",
  [ResourceType.DeviceArtifact]: "Device Artifact",
  [ResourceType.Remediation]: "Remediation",
  [ResourceType.Vulnerability]: "Vulnerability",
};

// Then in ConnectorsHeader, use:
// title={`${resourceTypeDisplayNames[resourceType as ResourceType] ?? resourceType} Connectors`}

This would allow ConnectorsContainer to always receive ResourceType while still displaying "Device Artifact" with a space.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/api-key-connectors/components/connectors.tsx` around lines 107 -
117, DeviceArtifactConnectorsContainer currently passes the literal string
"Device Artifact" into ConnectorsContainer which accepts ResourceType | string;
change this to pass the ResourceType enum (ResourceType.DeviceArtifact) and add
a display-name mapping (e.g., resourceTypeDisplayNames:
Record<ResourceType,string>) used by ConnectorsHeader (or whatever renders the
title) to convert ResourceType.DeviceArtifact into the user-friendly "Device
Artifact"; update ConnectorsContainer prop typing to require ResourceType and
ensure ConnectorsHeader uses resourceTypeDisplayNames[resourceType] ??
resourceType for its title.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/features/api-key-connectors/components/columns.tsx`:
- Around line 53-58: The status logic in the columns renderer (where text and
color are set based on row.original.apiKeyId) mislabels connectors that have a
valid integrationId as expired; update the condition in that component (the
block that sets text and color for status) to treat a row as Active when either
row.original.apiKeyId or row.original.integrationId is present, and mark Expired
only when both are missing, keeping the same color mapping (e.g., bg-green-300
for Active, bg-red-400 for Expired).

In `@src/features/api-key-connectors/server/params-loader.ts`:
- Around line 1-2: Add the "server-only" directive as the very first line of the
file and update the local import to use the project alias: keep the createLoader
import from "nuqs/server" but replace the relative connectors import
(connectorsParams from "../params") with the aliased path connectorsParams from
"@/features/api-key-connectors/params"; ensure the "server-only" string literal
appears before any imports so the file is explicitly marked server-side.

---

Nitpick comments:
In `@src/features/api-key-connectors/components/connectors.tsx`:
- Around line 107-117: DeviceArtifactConnectorsContainer currently passes the
literal string "Device Artifact" into ConnectorsContainer which accepts
ResourceType | string; change this to pass the ResourceType enum
(ResourceType.DeviceArtifact) and add a display-name mapping (e.g.,
resourceTypeDisplayNames: Record<ResourceType,string>) used by ConnectorsHeader
(or whatever renders the title) to convert ResourceType.DeviceArtifact into the
user-friendly "Device Artifact"; update ConnectorsContainer prop typing to
require ResourceType and ensure ConnectorsHeader uses
resourceTypeDisplayNames[resourceType] ?? resourceType for its title.

In `@src/features/api-key-connectors/server/prefetch.ts`:
- Around line 1-3: Add the top-of-file "server-only" directive (a single line
containing 'server-only') as the very first line to prevent client-side imports;
update src features referenced symbols such as inferInput, ResourceType,
prefetch, and trpc remain unchanged — just insert the directive before the
existing imports so the bundler will error if this server-side prefetch utility
is imported on the client.

In `@src/features/api-key-connectors/types.ts`:
- Around line 32-34: The exported type name paginatedConnectorsByTypeInput
should use PascalCase: rename it to PaginatedConnectorsByTypeInput and update
its declaration to export type PaginatedConnectorsByTypeInput = z.infer<typeof
paginatedConnectorInputSchema>; then search and update all usages/imports of
paginatedConnectorsByTypeInput across the codebase (tests, consumers, and index
exports) to the new PaginatedConnectorsByTypeInput identifier so imports and
references remain consistent with ConnectorResponse and TS naming conventions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 41069a9f-826c-4444-bf02-64fff5d01bec

📥 Commits

Reviewing files that changed from the base of the PR and between b8ac874 and 3d6278b.

📒 Files selected for processing (13)
  • src/app/(dashboard)/(rest)/connectors/assets/page.tsx
  • src/app/(dashboard)/(rest)/connectors/deviceArtifacts/page.tsx
  • src/app/(dashboard)/(rest)/connectors/remediations/page.tsx
  • src/app/(dashboard)/(rest)/connectors/vulnerabilities/page.tsx
  • src/features/api-key-connectors/components/columns.tsx
  • src/features/api-key-connectors/components/connectors.tsx
  • src/features/api-key-connectors/hooks/use-connectors.ts
  • src/features/api-key-connectors/params.ts
  • src/features/api-key-connectors/server/params-loader.ts
  • src/features/api-key-connectors/server/prefetch.ts
  • src/features/api-key-connectors/server/routers.ts
  • src/features/api-key-connectors/types.ts
  • src/features/assets/components/asset.tsx

Copy link
Contributor

@timrcm timrcm left a comment

Choose a reason for hiding this comment

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

Looks good to me!

Copy link
Contributor

@timrcm timrcm left a comment

Choose a reason for hiding this comment

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

Note Cassidy's feedback in Slack -- it looks like there might still be some issues with this after all.

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

🧹 Nitpick comments (2)
src/app/api/trpc/[trpc]/route.ts (1)

12-14: Consider structured logging and environment-aware verbosity.

The error logging is functional, but for production use:

  1. Logging the full error object may expose sensitive data or stack traces in production logs.
  2. A more structured format would improve observability and log parsing.
♻️ Optional: Structured error logging
     onError: ({ path, error }) => {
-      console.error(path, error);
+      console.error(`[tRPC Error] ${path}:`, {
+        code: error.code,
+        message: error.message,
+        ...(process.env.NODE_ENV === "development" && { stack: error.stack }),
+      });
     },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/api/trpc/`[trpc]/route.ts around lines 12 - 14, The onError handler
currently logs the raw error object (onError: ({ path, error }) => {
console.error(path, error); }) which can leak sensitive info and is
unstructured; update the handler to emit structured logs (an object with path,
error.message, error.name, optional status/code) and gate stack traces behind an
environment check (e.g., include error.stack only when NODE_ENV !==
'production'), and redact any sensitive properties before logging or use an
existing structured logger instance if available; ensure the handler still
captures the path and a concise message for observability while avoiding full
error dumps in production.
src/features/api-key-connectors/components/connectors.tsx (1)

1-1: Rename this component file to PascalCase for consistency.

This component lives in src/features/.../components/ but the filename is connectors.tsx; please rename it to Connectors.tsx to match repo conventions.

As per coding guidelines, "Use PascalCase for component file names and kebab-case for utility/helper file names".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/api-key-connectors/components/connectors.tsx` at line 1, Rename
the component file from connectors.tsx to Connectors.tsx and update all imports
referencing it to the new filename; ensure the exported React component
(Connectors) and any default export usages still match after the rename so
imports like import Connectors from "…/components/Connectors" resolve correctly,
and run project/type-check to catch any missed import paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/features/api-key-connectors/components/connectors.tsx`:
- Line 85: Remove the debug console logging of connector payloads: delete the
console.log("useSuspenseConnectorsByResourceType:", connectors) statement in the
connectors.tsx implementation (the useSuspenseConnectorsByResourceType flow that
handles the connectors variable) so fetched connector data is not printed to the
browser console; ensure no equivalent debug logs remain in the same module or
helper functions that expose connector payloads.

---

Nitpick comments:
In `@src/app/api/trpc/`[trpc]/route.ts:
- Around line 12-14: The onError handler currently logs the raw error object
(onError: ({ path, error }) => { console.error(path, error); }) which can leak
sensitive info and is unstructured; update the handler to emit structured logs
(an object with path, error.message, error.name, optional status/code) and gate
stack traces behind an environment check (e.g., include error.stack only when
NODE_ENV !== 'production'), and redact any sensitive properties before logging
or use an existing structured logger instance if available; ensure the handler
still captures the path and a concise message for observability while avoiding
full error dumps in production.

In `@src/features/api-key-connectors/components/connectors.tsx`:
- Line 1: Rename the component file from connectors.tsx to Connectors.tsx and
update all imports referencing it to the new filename; ensure the exported React
component (Connectors) and any default export usages still match after the
rename so imports like import Connectors from "…/components/Connectors" resolve
correctly, and run project/type-check to catch any missed import paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 56631c87-204d-4f97-adf6-2e0ac36f1c78

📥 Commits

Reviewing files that changed from the base of the PR and between 9d58ad7 and f1e605c.

📒 Files selected for processing (2)
  • src/app/api/trpc/[trpc]/route.ts
  • src/features/api-key-connectors/components/connectors.tsx

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

Caution

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

⚠️ Outside diff range comments (1)
src/features/assets/components/assets.tsx (1)

228-250: ⚠️ Potential issue | 🟠 Major

Fix type mismatch: AssetsListWithDrawer receives AssetResponse but expects AssetWithIssues.

The columns and columnsWithDrawer are typed as ColumnDef<AssetResponse>[], but row.original (passed to setAsset) should be typed as data that includes the issues field. Although getManyInternal explicitly includes issues in the Prisma query (include: { ...assetInclude, issues: true }), the AssetResponse type definition doesn't reflect this. Either update the columns type to match what getManyInternal actually returns, or create a separate columns definition for this component.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/assets/components/assets.tsx` around lines 228 - 250,
AssetsListWithDrawer is calling setAsset(row.original) but the table columns are
typed as ColumnDef<AssetResponse>[] while the data returned by getManyInternal
includes issues (AssetWithIssues); fix by aligning types: either change the
columns/columnsWithActions type to ColumnDef<AssetWithIssues>[] so row.original
is correctly typed for AssetDrawer, or update the AssetResponse type to include
the issues field to match getManyInternal, or create a separate columns
definition (e.g., columnsWithIssues) typed as ColumnDef<AssetWithIssues>[] and
use that in AssetsListWithDrawer; ensure references to AssetsListWithDrawer,
columnsWithActions, columns, AssetResponse, AssetWithIssues and getManyInternal
are updated consistently.
🧹 Nitpick comments (4)
src/features/device-artifacts/components/columns.tsx (1)

19-24: Clarify the accessorKey vs accessorFn mismatch.

The column uses accessorKey: "userId" but accessorFn returns row.user.name, and the header displays "Source Tool". This creates a semantic mismatch: TanStack Table will use "userId" as the column identifier for sorting/filtering state, but the actual displayed/accessed value is the user's name.

Consider using id: "sourceTool" (or id: "userName") instead of accessorKey: "userId" to better reflect the column's purpose:

♻️ Suggested improvement
  {
-   accessorKey: "userId",
+   id: "sourceTool",
    meta: { title: "Source Tool" },
    header: "Source Tool",
    accessorFn: (row) => row.user.name,
  },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/device-artifacts/components/columns.tsx` around lines 19 - 24,
The column has a semantic mismatch: it sets accessorKey: "userId" but uses
accessorFn: (row) => row.user.name and header: "Source Tool"; update the column
definition to use a clear identifier (e.g., replace accessorKey with id:
"sourceTool" or id: "userName") and keep accessorFn as the source of truth so
sorting/filtering uses the correct column id; ensure the id matches the
displayed value and update any references that relied on "userId" for state or
tests to the new id.
src/features/assets/components/columns.tsx (1)

92-97: TODO: Implement delete action or add tracking issue.

The delete action currently only logs "TODO". Consider implementing the delete functionality or creating a tracking issue.

Would you like me to help generate the delete implementation or open an issue to track this?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/assets/components/columns.tsx` around lines 92 - 97, The TODO
stub in the DropdownMenuItem onClick must be replaced with a real delete flow:
add a handleDeleteAsset function and wire it to the onClick instead of
console.log, call your existing delete mutation (e.g., deleteAssetMutation or
deleteAsset) passing the asset id from the row props, show a confirmation prompt
before calling it, handle success by refreshing the list or calling
onDeleted/invalidating queries and show an error toast on failure; ensure the
handler is referenced where DropdownMenuItem currently uses onClick and
import/use the appropriate mutation hook (deleteAssetMutation/deleteAsset) and
any toast/confirm utilities.
src/features/api-key-connectors/components/connectors.tsx (1)

111-121: Inconsistent resourceType handling for DeviceArtifact container.

DeviceArtifactConnectorsContainer uses a hardcoded string "Device Artifact" while all other containers use the ResourceType enum. This inconsistency suggests the resourceType prop is being overloaded for both data fetching (enum) and display (human-readable string).

Consider using a display name mapping (similar to integrationsMapping which has a name field) to keep the enum usage consistent.

Proposed approach
+import { integrationsMapping } from "@/features/integrations/types";
+
+const getDisplayName = (type: ResourceType): string => {
+  const entry = Object.values(integrationsMapping).find(m => m.type === type);
+  return entry?.name ?? type;
+};

 export const DeviceArtifactConnectorsContainer = ({
   children,
 }: {
   children: React.ReactNode;
 }) => {
   return (
-    <ConnectorsContainer resourceType={"Device Artifact"}>
+    <ConnectorsContainer resourceType={ResourceType.DeviceArtifact}>
       {children}
     </ConnectorsContainer>
   );
 };

Then update ConnectorsHeader to use the display name mapping:

 export const ConnectorsHeader = ({
   disabled,
   resourceType,
 }: {
   disabled?: boolean;
-  resourceType: string;
+  resourceType: ResourceType;
 }) => {
   return (
     <EntityHeader
-      title={`${resourceType} Connectors`}
+      title={`${getDisplayName(resourceType)} Connectors`}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/api-key-connectors/components/connectors.tsx` around lines 111 -
121, DeviceArtifactConnectorsContainer currently passes a hardcoded "Device
Artifact" string to ConnectorsContainer; change it to pass the ResourceType enum
value and use a display-name mapping for UI text so enum remains the single
source for data-fetching. Update DeviceArtifactConnectorsContainer to pass
ResourceType.DeviceArtifact (or the equivalent enum key), add or reuse a mapping
(similar to integrationsMapping.name) that maps ResourceType values to
human-readable names, and update ConnectorsHeader to read the display name from
that mapping instead of relying on the prop string; reference the symbols
DeviceArtifactConnectorsContainer, ConnectorsContainer, ConnectorsHeader,
ResourceType, and integrationsMapping when making these edits.
src/features/api-key-connectors/components/connectors-layout.tsx (1)

43-45: Active tab detection could be fragile.

Using pathname.includes(tabs[1].value) to detect the "items" tab may produce false positives if "items" appears elsewhere in the pathname (e.g., a future nested route). Consider a more precise check.

Proposed improvement
-  const activeTab = pathname.includes(tabs[1].value)
-    ? tabs[1].value
-    : tabs[0].value;
+  const activeTab = pathname.endsWith("/items") || pathname.includes("/items/")
+    ? tabs[1].value
+    : tabs[0].value;

Or use exact segment matching:

const activeTab = split.at(-1) === "items" ? tabs[1].value : tabs[0].value;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/api-key-connectors/components/connectors-layout.tsx` around
lines 43 - 45, The active tab detection using pathname.includes(tabs[1].value)
in the activeTab assignment is fragile and can produce false positives; update
the logic in the activeTab computation to split the pathname into segments
(e.g., by "/"), ignore empty segments, and compare the last segment exactly to
tabs[1].value (handling trailing slashes) so you only set activeTab to
tabs[1].value when the final path segment equals "items", otherwise default to
tabs[0].value; modify the activeTab expression accordingly (referencing
activeTab, pathname, and tabs).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/`(dashboard)/(rest)/connectors/[resourceTypeUrl]/items/page.tsx:
- Around line 51-58: Add an authentication guard to the top of the Page
component by calling requireAuth() before any route logic: import requireAuth
from "@/lib/auth" and invoke requireAuth() as the first statement inside the
Page function (before accessing params or calling
isValidResourceTypeKey/resourceTypeUrl); this ensures unauthenticated users are
redirected to /login and preserves existing validation with
isValidResourceTypeKey and notFound().
- Around line 63-64: The call to config.prefetch should be awaited so prefetch
completes before render: change the usage in page.tsx to await config.prefetch({
...paginationParams }) after obtaining paginationParams from
paginationParamsLoader, and update the surrounding function/type signature
(wherever config.prefetch is declared/typed) to reflect it returns a Promise
(i.e., mark the caller as async and update the prefetch type to return
Promise<void> or the appropriate Promise type) so TypeScript correctly enforces
the async behavior; reference paginationParamsLoader and config.prefetch to
locate the changes.

In `@src/app/`(dashboard)/(rest)/connectors/[resourceTypeUrl]/page.tsx:
- Around line 10-21: The Page component currently lacks authentication and a
Suspense boundary; call requireAuth() at the top of the Page (or in the
surrounding layout) to protect the dashboard route, and wrap the ConnectorsList
render in a React.Suspense with a fallback (e.g., ConnectorsLoading) because
ConnectorsList uses useSuspenseConnectorsByResourceType which will suspend;
update the Page function (the component named Page) to validate
resourceTypePlural as before, invoke requireAuth(), then return <Suspense
fallback={<ConnectorsLoading />}> around <ConnectorsList
resourceType={resourceType} /> so suspended queries are handled.

In `@src/features/api-key-connectors/components/connectors-layout.tsx`:
- Around line 1-11: This component uses the client-side hook usePathname from
next/navigation but is missing the "use client" directive; add a top-of-file
"use client" directive to connectors-layout.tsx (above the imports) so the file
is treated as a client component, then ensure components referenced here (e.g.,
ConnectorsHeader, Tabs/TabsTrigger/TabsList) are client-safe or updated
accordingly; verify that usePathname calls remain in the component scope after
adding the directive.

---

Outside diff comments:
In `@src/features/assets/components/assets.tsx`:
- Around line 228-250: AssetsListWithDrawer is calling setAsset(row.original)
but the table columns are typed as ColumnDef<AssetResponse>[] while the data
returned by getManyInternal includes issues (AssetWithIssues); fix by aligning
types: either change the columns/columnsWithActions type to
ColumnDef<AssetWithIssues>[] so row.original is correctly typed for AssetDrawer,
or update the AssetResponse type to include the issues field to match
getManyInternal, or create a separate columns definition (e.g.,
columnsWithIssues) typed as ColumnDef<AssetWithIssues>[] and use that in
AssetsListWithDrawer; ensure references to AssetsListWithDrawer,
columnsWithActions, columns, AssetResponse, AssetWithIssues and getManyInternal
are updated consistently.

---

Nitpick comments:
In `@src/features/api-key-connectors/components/connectors-layout.tsx`:
- Around line 43-45: The active tab detection using
pathname.includes(tabs[1].value) in the activeTab assignment is fragile and can
produce false positives; update the logic in the activeTab computation to split
the pathname into segments (e.g., by "/"), ignore empty segments, and compare
the last segment exactly to tabs[1].value (handling trailing slashes) so you
only set activeTab to tabs[1].value when the final path segment equals "items",
otherwise default to tabs[0].value; modify the activeTab expression accordingly
(referencing activeTab, pathname, and tabs).

In `@src/features/api-key-connectors/components/connectors.tsx`:
- Around line 111-121: DeviceArtifactConnectorsContainer currently passes a
hardcoded "Device Artifact" string to ConnectorsContainer; change it to pass the
ResourceType enum value and use a display-name mapping for UI text so enum
remains the single source for data-fetching. Update
DeviceArtifactConnectorsContainer to pass ResourceType.DeviceArtifact (or the
equivalent enum key), add or reuse a mapping (similar to
integrationsMapping.name) that maps ResourceType values to human-readable names,
and update ConnectorsHeader to read the display name from that mapping instead
of relying on the prop string; reference the symbols
DeviceArtifactConnectorsContainer, ConnectorsContainer, ConnectorsHeader,
ResourceType, and integrationsMapping when making these edits.

In `@src/features/assets/components/columns.tsx`:
- Around line 92-97: The TODO stub in the DropdownMenuItem onClick must be
replaced with a real delete flow: add a handleDeleteAsset function and wire it
to the onClick instead of console.log, call your existing delete mutation (e.g.,
deleteAssetMutation or deleteAsset) passing the asset id from the row props,
show a confirmation prompt before calling it, handle success by refreshing the
list or calling onDeleted/invalidating queries and show an error toast on
failure; ensure the handler is referenced where DropdownMenuItem currently uses
onClick and import/use the appropriate mutation hook
(deleteAssetMutation/deleteAsset) and any toast/confirm utilities.

In `@src/features/device-artifacts/components/columns.tsx`:
- Around line 19-24: The column has a semantic mismatch: it sets accessorKey:
"userId" but uses accessorFn: (row) => row.user.name and header: "Source Tool";
update the column definition to use a clear identifier (e.g., replace
accessorKey with id: "sourceTool" or id: "userName") and keep accessorFn as the
source of truth so sorting/filtering uses the correct column id; ensure the id
matches the displayed value and update any references that relied on "userId"
for state or tests to the new id.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 685b1893-5a8b-4ced-a4a5-11b1efef206b

📥 Commits

Reviewing files that changed from the base of the PR and between 015cc29 and 2a022a2.

📒 Files selected for processing (21)
  • src/app/(dashboard)/(rest)/connectors/[resourceTypeUrl]/items/page.tsx
  • src/app/(dashboard)/(rest)/connectors/[resourceTypeUrl]/layout.tsx
  • src/app/(dashboard)/(rest)/connectors/[resourceTypeUrl]/page.tsx
  • src/app/(dashboard)/(rest)/connectors/assets/page.tsx
  • src/app/(dashboard)/(rest)/connectors/deviceArtifacts/page.tsx
  • src/app/(dashboard)/(rest)/connectors/remediations/page.tsx
  • src/app/(dashboard)/(rest)/connectors/vulnerabilities/page.tsx
  • src/app/(dashboard)/(rest)/settings/integrations/[resourceTypeUrl]/page.tsx
  • src/features/api-key-connectors/components/connectors-layout.tsx
  • src/features/api-key-connectors/components/connectors.tsx
  • src/features/assets/components/assets.tsx
  • src/features/assets/components/columns.tsx
  • src/features/device-artifacts/components/columns.tsx
  • src/features/device-artifacts/components/device-artifacts.tsx
  • src/features/integrations/components/integrations-layout.tsx
  • src/features/integrations/types.ts
  • src/features/remediations/components/columns.tsx
  • src/features/remediations/components/remediations.tsx
  • src/features/vulnerabilities/components/vulnerabilities.tsx
  • src/lib/schemas.ts
  • tsconfig.json
💤 Files with no reviewable changes (4)
  • src/app/(dashboard)/(rest)/connectors/assets/page.tsx
  • src/app/(dashboard)/(rest)/connectors/deviceArtifacts/page.tsx
  • src/app/(dashboard)/(rest)/connectors/remediations/page.tsx
  • src/app/(dashboard)/(rest)/connectors/vulnerabilities/page.tsx
✅ Files skipped from review due to trivial changes (4)
  • src/features/integrations/types.ts
  • src/features/remediations/components/columns.tsx
  • src/lib/schemas.ts
  • tsconfig.json

Comment on lines +51 to +58
const Page = async ({
params,
searchParams,
}: CombinedPageProps<"resourceTypeUrl">) => {
const { resourceTypeUrl } = await params;
if (!isValidResourceTypeKey(resourceTypeUrl)) {
return notFound();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing requireAuth() for route protection.

Dashboard routes should verify authentication before processing. Add requireAuth() at the start of the page function.

As per coding guidelines: "Protect routes requiring authentication using requireAuth() utility and redirect to /login if unauthenticated".

Proposed fix
 const Page = async ({
   params,
   searchParams,
 }: CombinedPageProps<"resourceTypeUrl">) => {
+  await requireAuth();
   const { resourceTypeUrl } = await params;

Also add the import:

import { requireAuth } from "@/lib/auth";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`(dashboard)/(rest)/connectors/[resourceTypeUrl]/items/page.tsx
around lines 51 - 58, Add an authentication guard to the top of the Page
component by calling requireAuth() before any route logic: import requireAuth
from "@/lib/auth" and invoke requireAuth() as the first statement inside the
Page function (before accessing params or calling
isValidResourceTypeKey/resourceTypeUrl); this ensures unauthenticated users are
redirected to /login and preserves existing validation with
isValidResourceTypeKey and notFound().

Comment on lines +63 to +64
const paginationParams = await paginationParamsLoader(searchParams);
config.prefetch({ ...paginationParams });
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Prefetch call should be awaited.

The prefetch function returns a Promise that should be awaited to ensure data is prefetched before rendering. Without await, the prefetch may not complete before the component renders, defeating its purpose.

Proposed fix
   const paginationParams = await paginationParamsLoader(searchParams);
-  config.prefetch({ ...paginationParams });
+  await config.prefetch({ ...paginationParams });

Also update the type definition to reflect the async nature:

 interface ConnectorResourceTypeConfig {
   listElement: React.FC;
-  prefetch: (params: PaginationInput) => void;
+  prefetch: (params: PaginationInput) => Promise<void>;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`(dashboard)/(rest)/connectors/[resourceTypeUrl]/items/page.tsx
around lines 63 - 64, The call to config.prefetch should be awaited so prefetch
completes before render: change the usage in page.tsx to await config.prefetch({
...paginationParams }) after obtaining paginationParams from
paginationParamsLoader, and update the surrounding function/type signature
(wherever config.prefetch is declared/typed) to reflect it returns a Promise
(i.e., mark the caller as async and update the prefetch type to return
Promise<void> or the appropriate Promise type) so TypeScript correctly enforces
the async behavior; reference paginationParamsLoader and config.prefetch to
locate the changes.

Comment on lines +10 to +21
const Page = () => {
const pathname = usePathname();
const resourceTypePlural = pathname.split("/").pop();

if (!resourceTypePlural || !isValidResourceTypeKey(resourceTypePlural)) {
return notFound();
}

const resourceType = integrationsMapping[resourceTypePlural].type;

return <ConnectorsList resourceType={resourceType} />;
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if the layout.tsx for this route provides auth/Suspense wrappers
fd -t f "layout.tsx" src/app/ --exec cat {} \; | rg -A 10 -B 2 "requireAuth|Suspense|ErrorBoundary"

Repository: PATCH-UPGRADE/viper

Length of output: 45


🏁 Script executed:

# First, verify the actual page.tsx file content
cat -n src/app/\(dashboard\)/\(rest\)/connectors/\[resourceTypeUrl\]/page.tsx

Repository: PATCH-UPGRADE/viper

Length of output: 848


🏁 Script executed:

# Check the parent layout files
echo "=== (rest) layout ===" && cat -n src/app/\(dashboard\)/\(rest\)/layout.tsx && echo "" && echo "=== connectors layout ===" && cat -n src/app/\(dashboard\)/\(rest\)/connectors/layout.tsx && echo "" && echo "=== (dashboard) layout ===" && cat -n src/app/\(dashboard\)/layout.tsx

Repository: PATCH-UPGRADE/viper

Length of output: 542


🏁 Script executed:

# Compare with items/page.tsx mentioned in the review
cat -n src/app/\(dashboard\)/\(rest\)/items/page.tsx

Repository: PATCH-UPGRADE/viper

Length of output: 138


🏁 Script executed:

# Check the ConnectorsList component implementation
fd -t f "ConnectorsList" src/ --exec cat -n {} \;

Repository: PATCH-UPGRADE/viper

Length of output: 45


🏁 Script executed:

fd -t f -i "connectors" src/features --type f | head -20

Repository: PATCH-UPGRADE/viper

Length of output: 241


🏁 Script executed:

# Search for ConnectorsList component definition
rg -t tsx "export.*ConnectorsList|function ConnectorsList|const ConnectorsList" src/

Repository: PATCH-UPGRADE/viper

Length of output: 90


🏁 Script executed:

# Check the (dashboard) layout for authentication
cat -n src/app/\(dashboard\)/layout.tsx

Repository: PATCH-UPGRADE/viper

Length of output: 528


🏁 Script executed:

# Look for useSuspenseConnectorsByResourceType to verify if it's actually used
rg -t tsx "useSuspenseConnectorsByResourceType" src/

Repository: PATCH-UPGRADE/viper

Length of output: 90


🏁 Script executed:

# Read the ConnectorsList component
cat -n src/features/api-key-connectors/components/connectors.tsx

Repository: PATCH-UPGRADE/viper

Length of output: 4692


🏁 Script executed:

# Check the hooks file
cat -n src/features/api-key-connectors/hooks/use-connectors.ts

Repository: PATCH-UPGRADE/viper

Length of output: 1122


🏁 Script executed:

# Search for suspense hook usage with correct rg syntax
rg "useSuspenseConnectorsByResourceType|useSuspense" src/

Repository: PATCH-UPGRADE/viper

Length of output: 10732


🏁 Script executed:

# Check if there's a (dashboard) layout that provides authentication
fd -t f "layout.tsx" src/app/\(dashboard\)/ --exec cat -n {} \;

Repository: PATCH-UPGRADE/viper

Length of output: 1760


🏁 Script executed:

# Look for requireAuth anywhere in the codebase
rg "requireAuth" src/

Repository: PATCH-UPGRADE/viper

Length of output: 2176


🏁 Script executed:

cat -n src/features/api-key-connectors/components/connectors-layout.tsx

Repository: PATCH-UPGRADE/viper

Length of output: 2597


Add authentication protection and Suspense boundary for client-side data fetching.

This page is missing requireAuth() for authentication protection (required for dashboard routes) and lacks a Suspense boundary. The ConnectorsList component uses useSuspenseConnectorsByResourceType, a suspense query that will throw a promise when suspended, requiring a parent Suspense boundary to catch it. Without this, the component may fail to render properly.

Add requireAuth() at the top of this page or at the layout level, and wrap the ConnectorsList with a Suspense boundary in the layout or page:

<details>
<summary>Example: Adding Suspense wrapper</summary>

const Page = () => {
  // ...validation logic...
  return (
    <Suspense fallback={<ConnectorsLoading />}>
      <ConnectorsList resourceType={resourceType} />
    </Suspense>
  );
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`(dashboard)/(rest)/connectors/[resourceTypeUrl]/page.tsx around
lines 10 - 21, The Page component currently lacks authentication and a Suspense
boundary; call requireAuth() at the top of the Page (or in the surrounding
layout) to protect the dashboard route, and wrap the ConnectorsList render in a
React.Suspense with a fallback (e.g., ConnectorsLoading) because ConnectorsList
uses useSuspenseConnectorsByResourceType which will suspend; update the Page
function (the component named Page) to validate resourceTypePlural as before,
invoke requireAuth(), then return <Suspense fallback={<ConnectorsLoading />}>
around <ConnectorsList resourceType={resourceType} /> so suspended queries are
handled.

Comment on lines +1 to +11
import { ActivityIcon, PlugIcon } from "lucide-react";
import Link from "next/link";
import { notFound, usePathname } from "next/navigation";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { mainPadding } from "@/config/constants";
import {
integrationsMapping,
isValidResourceTypeKey,
} from "@/features/integrations/types";
import { cn } from "@/lib/utils";
import { ConnectorsHeader } from "./connectors";
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing "use client" directive.

This component uses usePathname() from next/navigation, which is a client-side hook. The file should be marked with the "use client" directive.

As per coding guidelines: "Mark server-side files with 'server-only' directive and client components with 'use client' directive".

Proposed fix
+"use client";
+
 import { ActivityIcon, PlugIcon } from "lucide-react";
 import Link from "next/link";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { ActivityIcon, PlugIcon } from "lucide-react";
import Link from "next/link";
import { notFound, usePathname } from "next/navigation";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { mainPadding } from "@/config/constants";
import {
integrationsMapping,
isValidResourceTypeKey,
} from "@/features/integrations/types";
import { cn } from "@/lib/utils";
import { ConnectorsHeader } from "./connectors";
"use client";
import { ActivityIcon, PlugIcon } from "lucide-react";
import Link from "next/link";
import { notFound, usePathname } from "next/navigation";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { mainPadding } from "@/config/constants";
import {
integrationsMapping,
isValidResourceTypeKey,
} from "@/features/integrations/types";
import { cn } from "@/lib/utils";
import { ConnectorsHeader } from "./connectors";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/api-key-connectors/components/connectors-layout.tsx` around
lines 1 - 11, This component uses the client-side hook usePathname from
next/navigation but is missing the "use client" directive; add a top-of-file
"use client" directive to connectors-layout.tsx (above the imports) so the file
is treated as a client component, then ensure components referenced here (e.g.,
ConnectorsHeader, Tabs/TabsTrigger/TabsList) are client-safe or updated
accordingly; verify that usePathname calls remain in the component scope after
adding the directive.

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.

3 participants