fix(logs): split summary/detail contracts to make trace tab gate type-safe#4430
fix(logs): split summary/detail contracts to make trace tab gate type-safe#4430waleedlatif1 wants to merge 48 commits intostagingfrom
Conversation
…ership workflow edits via sockets, ui improvements
…ng improvements, posthog, secrets mutations
…ration, signup method feature flags, SSO improvements
…nts, secrets performance, polling refactors, drag resources in mothership
…y invalidation, HITL docs
…endar triggers, docs updates, integrations/models pages improvements
…ions, jira forms endpoints
…mat, logs performance improvements fix(csp): add missing analytics domains, remove unsafe-eval, fix workspace CSP gap (#4179) fix(landing): return 404 for invalid dynamic route slugs (#4182) improvement(seo): optimize sitemaps, robots.txt, and core web vitals across sim and docs (#4170) fix(gemini): support structured output with tools on Gemini 3 models (#4184) feat(brightdata): add Bright Data integration with 8 tools (#4183) fix(mothership): fix superagent credentials (#4185) fix(logs): close sidebar when selected log disappears from filtered list; cleanup (#4186)
v0.6.46: mothership streaming fixes, brightdata integration
…m integration, atlassian triggers
…rity hardening, contact page, 404 page, access control, SES, SNS
v0.6.54: migration error logs
…ze, subagent thinking, files sorting, agentphone integration
fix(db): revert statement_timeout startup options breaking pooled connections (#4284)
v0.6.57: mothership reliability, ashby refactor, tables row count, copilot id fix, bun upgrade
…rizations, mothership positional table row insertion, CI improvements, org-external users, file viewer improvements
v0.6.62: fix new copilot chat creation and selection on refresh
…ixes, db query optimizations, contract boundaries code hygiene, CORS, toast improvements, tables infinite query, executor robustness, reranker support
…tion blocks/connectors updates
…-safe The Trace tab was silently missing from the Log Details sidepanel because list and detail rows shared one WorkflowLog type with executionData: z.unknown(). The UI couldn't distinguish a summary row (no spans) from a detail row (with spans), so the tab gate read undefined and hid itself. Splits into WorkflowLogSummary (list) and WorkflowLogDetail (typed executionData with optional traceSpans). Detail and by-execution routes both write through to the same logKeys.detail(id) cache, eliminating the two-key fragmentation that caused the merge memo workaround. List route moves to cursor pagination on (sortValue, id) with proper NULLS LAST handling and SQL-side sort across workflow + job execution tables. Detail route now requires and asserts workspaceId. Deep-link path uses useLogByExecutionId instead of auto-paginating the entire workspace. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 29606901 | Triggered | Generic High Entropy Secret | a54dcbe | apps/sim/providers/utils.test.ts | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
PR SummaryMedium Risk Overview Adds Reworks Reviewed by Cursor Bugbot for commit 551513b. Configure here. |
|
Recreating with clean commit history off staging. |
Greptile SummaryThis PR fixes the missing Trace tab in the Log Details sidebar by splitting the shared
Confidence Score: 3/5Not safe to merge as-is — two P1 regressions in pagination correctness and cache invalidation Two independent P1 bugs: cursor tie-breaking causes dropped rows with status/cost/duration sorts across page boundaries, and stats invalidation removal causes visible stale data after cancel/retry with live-mode off. The core Trace tab fix and contract split are solid. apps/sim/app/api/logs/route.ts (cursor tie-breaking logic), apps/sim/hooks/queries/logs.ts (missing stats invalidation in mutation onSettled) Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as Logs Page
participant QC as React Query Cache
participant ListAPI as GET /api/logs
participant DetailAPI as GET /api/logs by id
participant ByExecAPI as GET /api/logs by executionId
UI->>ListAPI: workspaceId + filters + cursor + sortBy
ListAPI-->>UI: data WorkflowLogSummary array + nextCursor
Note over UI,QC: cache stored under logKeys.list
UI->>UI: User clicks a row
UI->>DetailAPI: logId + workspaceId
DetailAPI-->>QC: WorkflowLogDetail with traceSpans
Note over UI,QC: cache stored under logKeys.detail
UI->>UI: deep-link executionId param on mount
UI->>ByExecAPI: executionId + workspaceId
ByExecAPI-->>QC: WorkflowLogDetail
Note over UI,QC: also writes to logKeys.detail for that log
QC-->>UI: dispatch TOGGLE_LOG with resolved logId
|
| const buildCursorCondition = (sortExpr: unknown, idCol: unknown): SQL | undefined => { | ||
| if (!cursor) return undefined | ||
| const v = cursor.v | ||
| const id = cursor.id | ||
| const cmp = sortOrder === 'asc' ? sql`>` : sql`<` | ||
| if (v === null) { | ||
| return sql`(${sortExpr} IS NULL AND ${idCol} ${cmp} ${id})` | ||
| } | ||
| return sql`((${sortExpr} IS NOT NULL AND ${sortExpr} ${cmp} ${v}) OR (${sortExpr} = ${v} AND ${idCol} ${cmp} ${id}) OR ${sortExpr} IS NULL)` |
There was a problem hiding this comment.
Cross-table cursor ID tie-breaking breaks pagination
The cursor's id field is derived from the last item of the merged page and then used as a tie-breaker in both the workflow and job table queries. When two rows from different tables share the same sort value, the cursor id (a UUID from one table) is compared against IDs from the other table using lexicographic order. For sorts like status where many rows share the same value, this causes systematic row omissions or duplicates across page boundaries — the next page for job logs will skip all job rows whose UUIDs are lexicographically ≥ the cursor ID (which came from a workflow log), even though they should appear on that page.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 551513b. Configure here.
| if (cmp !== 0) return sortOrder === 'asc' ? cmp : -cmp | ||
| const idCmp = a.id.localeCompare(b.id) | ||
| return sortOrder === 'asc' ? idCmp : -idCmp | ||
| }) |
There was a problem hiding this comment.
In-memory null sort contradicts SQL NULLS LAST ordering
Medium Severity
The compareSortValues function pushes nulls to the end (returns 1 when a is null), but the merge sort negates the comparison for descending order (-cmp), which moves nulls to the beginning. The SQL queries use DESC NULLS LAST, which keeps nulls at the end. This mismatch means the merged workflow+job result has incorrect ordering when sorting descending by columns with nullable values (e.g., duration, cost). The cursor derived from this misordered page won't align with the SQL cursor condition, causing rows to be duplicated or skipped across pages.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 551513b. Configure here.


Summary
The Trace tab was silently missing from the Log Details sidepanel because list and detail rows shared one
WorkflowLogtype withexecutionData: z.unknown(). The UI couldn't distinguish a summary row (no spans) from a detail row (with spans), so the tab gate read undefined and hid itself.WorkflowLogSummary(list) andWorkflowLogDetail(typedexecutionDatawith optionaltraceSpans) — makes the bug structurally impossible.logKeys.detail(id)cache, eliminating two-key fragmentation that caused the merge memo workaround.(sortValue, id)with properNULLS LASThandling and SQL-side sort across workflow + job execution tables (replaces in-memory merge that dropped rows under filters).workspaceId. Deep-link path usesuseLogByExecutionIdinstead of auto-paginating the entire workspace.Test plan
?executionId=<id>→ resolves in one round-trip, sidebar opens with detail (even for off-page logs)lists()+detail(id), no stats refetch?executionId=<id from other workspace>→ 404🤖 Generated with Claude Code