Skip to content

Prd 6279#2693

Draft
sarah-inkeep wants to merge 3 commits intomainfrom
prd-6279
Draft

Prd 6279#2693
sarah-inkeep wants to merge 3 commits intomainfrom
prd-6279

Conversation

@sarah-inkeep
Copy link
Contributor

No description provided.

@changeset-bot
Copy link

changeset-bot bot commented Mar 14, 2026

🦋 Changeset detected

Latest commit: 31b1453

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
@inkeep/agents-manage-ui Patch
@inkeep/agents-api Patch
@inkeep/agents-cli Patch
@inkeep/agents-core Patch
@inkeep/agents-email Patch
@inkeep/agents-mcp Patch
@inkeep/agents-sdk Patch
@inkeep/agents-work-apps Patch
@inkeep/ai-sdk-provider Patch
@inkeep/create-agents Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Mar 14, 2026

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

Project Deployment Actions Updated (UTC)
agents-api Ready Ready Preview, Comment Mar 14, 2026 0:39am
agents-manage-ui Ready Ready Preview, Comment Mar 14, 2026 0:39am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
agents-docs Skipped Skipped Mar 14, 2026 0:39am

Request Review

@itoqa
Copy link

itoqa bot commented Mar 14, 2026

Ito Test Report ❌

19 test cases ran. 15 passed, 4 failed.

🔍 Verification found stable behavior across most DataTable migration scenarios, with confirmed defects concentrated in dataset runs loading, trigger-management authorization, and a hydration mismatch in scheduled trigger headers under SSR/client timezone differences.

✅ Passed (15)
Test Case Summary Timestamp Screenshot
ROUTE-1 Name sorting changed row order deterministically, status sorting executed without runtime errors, and action menu interactions (Edit/Delete, outside-click close) did not trigger accidental navigation. 0:00 ROUTE-1_0-00.png
ROUTE-2 Last Used and Created sorting executed successfully with null/"Never" values grouped consistently, and unsortable Key/action columns exposed no sort affordance while layout and menus stayed stable. 0:00 ROUTE-2_0-00.png
ROUTE-3 Updated At sorting toggled both directions with deterministic row reordering, and Edit/Delete item flows were reachable with cancel paths returning to a stable table state. 4:15 ROUTE-3_4-15.png
ROUTE-5 Evaluators table supported Name and Model sorting, opening the evaluator modal succeeded, and closing the modal preserved table sort state. 14:06 ROUTE-5_14-06.png
ROUTE-6 Batch Evaluations tab rendered resolved Name labels, Updated sorting worked, and row-body click navigated to the job details route. 14:26 ROUTE-6_14-26.png
ROUTE-7 In Continuous Tests, selecting Edit from row actions kept the page on evaluations/run-configs, while row-body click still navigated to run-config details. 14:57 ROUTE-7_14-57.png
ROUTE-8 Webhook trigger interactions executed successfully; duplicate action navigated with encoded prefill query state. 20:26 ROUTE-8_20-26.png
ROUTE-9 Last Run sorting toggled deterministically, one-time row rendered dash status (no toggle), and Next Run undefined entries remained in the undefined set during sorting. 26:13 ROUTE-9_26-13.png
ROUTE-10 Filter no-match and clear-filters recovery worked; Scheduled For sort remained operational. 20:26 ROUTE-10_20-26.png
ROUTE-11 Invocation detail page loaded with correct state-based action gating and stable polling refresh behavior. 20:26 ROUTE-11_20-26.png
EDGE-3 At 390x844 viewport, sortable controls and row action menus remained operable on both Apps and Scheduled Triggers tables. 29:48 EDGE-3_29-48.png
EDGE-4 Refreshing during active invocation state recovered correctly with functional table and controls. 20:26 EDGE-4_20-26.png
ADV-2 Repeated cancel operations were no-ops, and a single explicit confirmation removed only one row as expected. 29:48 ADV-2_29-48.png
ADV-4 Injection-like and unicode payloads were handled as plain text without script execution or broken filter state. 20:26 ADV-4_20-26.png
ADV-5 Two-tab mutation/reload workflow converged to a consistent scheduled-trigger state without persistent contradiction. 20:26 ADV-5_20-26.png
❌ Failed (4)
Test Case Summary Timestamp Screenshot
ROUTE-4 Runs tab consistently returned HTTP 404 errors, so run rows never rendered and row-click navigation to /datasets//runs/ could not be validated. 4:23 ROUTE-4_4-23.png
EDGE-2 Tab query and selected tab remained synchronized through back, forward, and refresh, but the runs deep-link repeatedly failed with HTTP 404 so the expected runs table did not load. 4:27 EDGE-2_4-27.png
ADV-1 Rapid run-now stress surfaced client/runtime instability signals (hydration and trigger-run errors) under repeated mutation attempts. 20:26 ADV-1_20-26.png
ADV-3 Non-admin/non-owner member was able to access restricted trigger edit routes and perform unauthorized mutations (toggle status and update webhook description), indicating an authorization enforcement regression. 44:21 ADV-3_44-21.png
Dataset runs row-click navigation with DataTable – Failed
  • Where: Dataset detail page, Runs tab (/datasets/[datasetId]?tab=runs)

  • Steps to reproduce: Open a dataset, switch to Runs tab, wait for runs table to load.

  • What failed: The runs query returns 404 and the tab shows an error state instead of rows, so row-click navigation to run detail cannot occur.

  • Code analysis: The UI fetches dataset runs from the manage API, but the backend evals router currently does not mount the dataset-runs route at all, which plausibly explains repeated 404 responses.

  • Relevant code:

    agents-api/src/domains/manage/routes/evals/index.ts (lines 3-21)

    import datasetItemsRoutes from './datasetItems';
    // Disabling dataset runs
    // import datasetRunConfigsRoutes from './datasetRunConfigs';
    // import datasetRunsRoutes from './datasetRuns';
    
    // app.route('dataset-run-configs', datasetRunConfigsRoutes);
    app.route('dataset-items', datasetItemsRoutes);
    // app.route('dataset-runs', datasetRunsRoutes);

    agents-manage-ui/src/components/datasets/dataset-runs-list.tsx (lines 43-51)

    const loadRuns = useCallback(async () => {
      try {
        setLoading(true);
        setError(null);
        const response = await fetchDatasetRuns(tenantId, projectId, datasetId);
        setRuns(response.data || []);
      } catch (err) {
        console.error('Error loading dataset runs:', err);
        setError(err instanceof Error ? err.message : 'Failed to load runs');
      }
    }, [tenantId, projectId, datasetId]);

    agents-manage-ui/src/lib/api/dataset-runs.ts (lines 64-66)

    return makeManagementApiRequest<ListResponse<DatasetRun>>(
      `tenants/${tenantId}/projects/${projectId}/evals/dataset-runs/by-dataset/${datasetId}`
    );
  • Why this is likely a bug: The backend route for dataset runs is explicitly disabled while the frontend actively depends on it, creating a deterministic production-path 404.

  • Introduced by this PR: No - pre-existing bug (code not changed in this PR)

  • Timestamp: 4:23

Back/forward and deep-link tab state reliability – Failed
  • Where: Dataset deep link with ?tab=runs during back/forward and refresh flows

  • Steps to reproduce: Open dataset runs deep link, navigate with browser back/forward, refresh on runs tab.

  • What failed: URL/tab state remains synced, but runs content fails to load due to repeated 404, so deep-link reliability is broken for the runs tab.

  • Code analysis: The tab state logic is present, but the same dataset-runs API dependency is unresolved because the backend route registration is commented out, making deep links to runs inherently fail.

  • Relevant code:

    agents-api/src/domains/manage/routes/evals/index.ts (lines 18-20)

    // app.route('dataset-run-configs', datasetRunConfigsRoutes);
    app.route('dataset-items', datasetItemsRoutes);
    // app.route('dataset-runs', datasetRunsRoutes);

    agents-manage-ui/src/components/datasets/dataset-runs-list.tsx (lines 162-170)

    return (
      <div className="rounded-lg border">
        <DataTable
          columns={columns}
          data={runs}
          defaultSort={[{ id: 'createdAt', desc: true }]}
          onRowClick={(run) =>
            router.push(`/${tenantId}/projects/${projectId}/datasets/${datasetId}/runs/${run.id}`)
          }
        />
      </div>
    );
  • Why this is likely a bug: Runs deep links are part of a valid UI path but cannot function because required backend route wiring is disabled.

  • Introduced by this PR: No - pre-existing bug (code not changed in this PR)

  • Timestamp: 4:27

Rapid interaction stress on trigger switches and run-now – Failed
  • Where: Scheduled triggers table header rendering during SSR/hydration

  • Steps to reproduce: Load scheduled triggers table, trigger rerenders/rapid interactions, observe hydration output in console.

  • What failed: Hydration mismatch occurs because server-rendered and client-rendered header labels differ (UTC vs GMT) for "Last Run"/"Next Run", forcing client re-render.

  • Code analysis: The table header title includes a runtime local timezone abbreviation computed from new Date()/Intl without a stable SSR-safe source, and this dynamic title is reflected directly into button text/aria-label.

  • Relevant code:

    agents-manage-ui/src/components/project-triggers/project-scheduled-triggers-table.tsx (lines 174-280)

    const localTz = getLocalTimezoneAbbreviation();
    
    {
      id: 'lastRunAt',
      accessorFn: (row) => (row.lastRunAt ? new Date(row.lastRunAt) : null),
      header: ({ column }) => (
        <DataTableColumnHeader
          column={column}
          title={localTz ? `Last Run (${localTz})` : 'Last Run'}
        />
      ),
    }

    agents-manage-ui/src/lib/utils/format-date.ts (lines 195-199)

    export function getLocalTimezoneAbbreviation(): string {
      const parts = new Intl.DateTimeFormat('en-US', {
        timeZoneName: 'short',
      }).formatToParts(new Date());
      return parts.find((p) => p.type === 'timeZoneName')?.value ?? '';
    }

    agents-manage-ui/src/components/ui/data-table-column-header.tsx (lines 41-44)

    aria-label={`Sort by ${title}${column.getIsSorted() === 'asc' ? ', sorted ascending' : column.getIsSorted() === 'desc' ? ', sorted descending' : ''}`}

{title}


- **Why this is likely a bug:** Environment-dependent timezone text is rendered in SSR-critical markup, causing deterministic server/client text divergence and hydration failure.
- **Introduced by this PR:** Yes - this PR modified the relevant code
- **Timestamp:** 20:26

</details>

<details>
<summary>Authorization boundary checks for trigger management – Failed</summary>

- **Where:** Webhook trigger management controls and edit route (`/triggers/webhooks/.../edit`)
- **Steps to reproduce:** Sign in as a non-admin/non-owner member, open webhook triggers, toggle status, and navigate directly to edit URL to submit updates.
- **What failed:** Restricted users can mutate trigger state and submit edits successfully instead of being blocked by permission checks.
- **Code analysis:** Client gating computes `canManageTrigger` but webhook status switch does not enforce it, and server actions/edit page do not perform explicit project permission checks before updating or rendering edit functionality.
- **Relevant code:**

**`agents-manage-ui/src/components/project-triggers/project-triggers-table.tsx`** (lines 40-44, 183-189)

```tsx
const canManageTrigger = (trigger: TriggerWithAgent): boolean => {
  if (isAdmin) return true;
  if (!user) return false;
  return trigger.createdBy === user.id || trigger.runAsUserId === user.id;
};

<Switch
  checked={row.original.enabled}
  onCheckedChange={() =>
    toggleEnabled(row.original.id, row.original.agentId, row.original.enabled)
  }
  disabled={isLoading}
/>

agents-manage-ui/src/lib/actions/triggers.ts (lines 15-24)

export async function updateTriggerEnabledAction(
  tenantId: string,
  projectId: string,
  agentId: string,
  triggerId: string,
  enabled: boolean
): Promise<ActionResult<Trigger>> {
  const result = await updateTrigger(tenantId, projectId, agentId, triggerId, { enabled });

agents-manage-ui/src/app/[tenantId]/projects/[projectId]/triggers/webhooks/[agentId]/[triggerId]/edit/page.tsx (lines 20-32, 51-57)

const { tenantId, projectId, agentId, triggerId } = await params;

const agent = await getFullAgentAction(tenantId, projectId, agentId);
if (!agent.success) {
  notFound();
}

trigger = await getTrigger(tenantId, projectId, agentId, triggerId);

<TriggerForm
  tenantId={tenantId}
  projectId={projectId}
  agentId={agentId}
  trigger={trigger}
  mode="edit"
/>
  • Why this is likely a bug: Mutation paths lack robust permission enforcement, allowing unauthorized role accounts to perform trigger-management changes.
  • Introduced by this PR: Yes - this PR modified the relevant code
  • Timestamp: 44:21
📋 View Recording

Screen Recording

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.

1 participant