Skip to content

v0.7.2: logs export security, code hygiene, mship cost attribution#4956

Merged
icecrasher321 merged 3 commits into
mainfrom
staging
Jun 10, 2026
Merged

v0.7.2: logs export security, code hygiene, mship cost attribution#4956
icecrasher321 merged 3 commits into
mainfrom
staging

Conversation

@icecrasher321

@icecrasher321 icecrasher321 commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

waleedlatif1 and others added 3 commits June 10, 2026 14:01
* fix(security): neutralize CSV formula injection in logs export

* refactor(csv): extract neutralizeCsvFormula to shared util

* fix(csv): only neutralize string cells in logs export
…ogs dashboard (#4950)

* refactor(ui): eliminate prop drilling in editor, home, sidebar, and logs dashboard

- panel editor: activeSearchTarget was relayed untouched through SubBlock and
  30+ input components (depth up to 6); now provided once via
  ActiveSearchTargetProvider and re-provided at tool-input's synthetic
  sub-block transformation points; removed the vestigial workspaceId
  option from SubBlockInputController/useSubBlockInput
- home: ChatSurfaceProvider carries chatId/userId and stable interaction
  callbacks to UserInput/MessageContent/MessageActions;
  MothershipResourcesProvider carries the five resource operations to
  ResourceTabs, removing MothershipView's pure-relay props
- sidebar: extended SidebarDragContext into SidebarListContext so
  WorkflowItem/FolderItem read selection/drag callbacks directly; moved the
  hidden import input up to sidebar.tsx (also fixes import no-op while the
  list shows a skeleton)
- logs dashboard: DashboardSegmentsContext feeds StatusBar directly;
  WorkflowsList no longer relays segment selection state

* refactor(home): sync ChatSurfaceProvider callback refs in a layout effect

Mutating refs during render is unsound under concurrent rendering (render
may run multiple times before commit); useLayoutEffect commits the latest
callbacks before any user event can fire.
@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 10, 2026 10:01pm

Request Review

@cursor

cursor Bot commented Jun 10, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Billing behavior changes how workspace IDs are stamped (more permissive, FK-safe) which affects usage ledger attribution; the large editor/home context refactor touches many sub-block components but is mostly wiring.

Overview
Billing on POST /api/billing/update-cost no longer requires a valid workspaceId. The route resolves the ID against the local workspace table and records usage unattributed when it is missing or unknown (self-hosted/headless clients), avoiding FK failures that could strand cost in the caller’s dead-letter queue. Error logs now include Postgres pgCode and constraint names.

CSV exports for logs and tables route string cells through shared neutralizeCsvFormula to mitigate spreadsheet formula injection.

UI refactors replace deep prop drilling with React context: ChatSurface (chatId, user/context callbacks) for Mothership chat leaves; MothershipResources for the resource panel; DashboardSegments for logs dashboard status-bar selection; ActiveSearchTarget for workflow editor sub-blocks (including nested tool-param scopes). useSubBlockInput drops an optional workspaceId prop in favor of route params.

Reviewed by Cursor Bugbot for commit 1a5cf49. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR bundles three fixes: CSV formula injection neutralization for the logs export endpoint, removal of prop drilling across editor/home/sidebar/logs-dashboard via new context providers, and best-effort workspace-ID attribution for self-hosted and headless billing clients.

  • Security (csv): neutralizeCsvFormula is extracted to lib/core/utils/csv.ts and applied to string-typed cells in both the logs and table export routes, preventing formula injection when log values are opened in Excel/Sheets.
  • Attribution: The billing contract makes workspaceId optional; the route now validates the ID against its own workspace table before stamping it on the ledger, falling back to unattributed for unknown IDs. The workspace DB lookup is not wrapped in a try-catch, so a transient database error will propagate and fail the entire cost update despite the function being documented as best-effort.
  • UI refactor: SidebarDragContext is replaced by SidebarListContext (drag + selection callbacks); ChatSurfaceProvider and MothershipResourcesProvider eliminate identity/callback prop drilling in the home view; ActiveSearchTargetProvider and DashboardSegmentsContext do the same for the editor and logs dashboard respectively.

Confidence Score: 3/5

Safe to merge on the UI refactor and CSV fix; the billing attribution route has a gap where a transient workspace lookup failure propagates and fails the whole cost update.

The billing route comment promises that costs will never be dropped over attribution metadata, but the workspace DB lookup is not guarded by try-catch. A transient Postgres error during that lookup causes the entire updateCostInner to throw, the caller gets a 500, and the cost ends up in a retry/dead-letter queue rather than being recorded unattributed as intended. The UI prop-drilling refactor and CSV injection fix are mechanically correct and low-risk.

apps/sim/app/api/billing/update-cost/route.ts — the resolveAttributableWorkspaceId function needs exception handling to honour its best-effort contract.

Important Files Changed

Filename Overview
apps/sim/app/api/billing/update-cost/route.ts Adds best-effort workspace attribution by looking up the workspace in the DB before recording usage; the lookup is not exception-guarded, contradicting the best-effort contract.
apps/sim/lib/core/utils/csv.ts Extracts neutralizeCsvFormula to a shared utility; correct implementation for string formula-injection prevention.
apps/sim/app/api/logs/export/route.ts Applies neutralizeCsvFormula to string-typed cells only; non-string array values that stringify to formula triggers are not covered.
apps/sim/app/api/table/[tableId]/export/route.ts Removes local neutralizeCsvFormula copy in favour of the new shared utility; no logic change.
apps/sim/lib/api/contracts/subscription.ts Makes workspaceId optional in the billing contract schema to support self-hosted/headless callers.
apps/sim/app/workspace/[workspaceId]/home/components/chat-surface-context/chat-surface-context.tsx New context provider using ref-latching pattern for stable callbacks; correctly uses useLayoutEffect to sync refs on every render.
apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/dashboard-segments-context.tsx New context for segment selection state in the logs dashboard; throws explicitly if used outside provider.
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/hooks/use-sidebar-list-context.ts Replaces use-sidebar-drag-context with a richer SidebarListContext including selection/drag callbacks; well-structured with noop defaults.

Sequence Diagram

sequenceDiagram
    participant Go as Go Mothership
    participant Route as POST /api/billing/update-cost
    participant Resolver as resolveAttributableWorkspaceId
    participant DB as Postgres (workspace table)
    participant Ledger as recordUsage / recordCumulativeUsage

    Go->>Route: "{userId, cost, workspaceId?, idempotencyKey?}"
    Route->>Resolver: workspaceId (may be undefined)
    alt workspaceId is undefined (headless client)
        Resolver-->>Route: undefined
    else workspaceId provided
        Resolver->>DB: "SELECT id FROM workspace WHERE id = workspaceId LIMIT 1"
        alt row found
            DB-->>Resolver: "{id}"
            Resolver-->>Route: workspaceId
        else not found (self-hosted foreign ID)
            DB-->>Resolver: []
            Resolver-->>Route: undefined (logs warning)
        else DB error (not handled)
            DB-->>Resolver: throws
            Resolver-->>Route: throws — gap
        end
    end
    Route->>Ledger: record cost with attributedWorkspaceId
    Ledger-->>Route: ok
    Route-->>Go: 200
Loading

Comments Outside Diff (1)

  1. apps/sim/app/api/logs/export/route.ts, line 17-24 (link)

    P2 Non-string values are not formula-neutralized

    neutralizeCsvFormula is only applied when typeof value === 'string', but String(value) for an array like ['=HYPERLINK(...)'] produces =HYPERLINK(...) — starting with a formula trigger — which passes through unguarded. This matches the design decision documented in the table export (numbers, booleans, dates, and JSON objects can never form a trigger) but arrays are not covered by that reasoning. Adding a comment to escapeCsv clarifying this limitation (mirroring the table-export comment) would prevent silent regressions if log values later include array-typed columns.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (1): Last reviewed commit: "fix(attribution): workspace id attr shou..." | Re-trigger Greptile

Comment thread apps/sim/app/api/billing/update-cost/route.ts
@waleedlatif1 waleedlatif1 changed the title v0.7.2: logs export security, platform ui, mship cost attribution v0.7.2: logs export security, code hygiene, mship cost attribution Jun 10, 2026
@icecrasher321 icecrasher321 merged commit d4722f9 into main Jun 10, 2026
28 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