fix(attribution): workspace id attr should be best-effort for self hosted users#4953
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Before stamping On failure, error logs now include Postgres SQLSTATE and constraint ( Reviewed by Cursor Bugbot for commit 673f036. Configure here. |
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 673f036. Configure here.
Greptile SummaryThis PR makes workspace attribution on
Confidence Score: 4/5Safe to merge; the change narrows the blast radius of a known production failure and billing correctness (keyed on userId) is unaffected by workspace attribution. The core billing path is well-tested and the fallback to unattributed is safe by design. Two minor observations remain: every hosted billing flush now incurs an extra DB round-trip for workspace validation, and the silent attribution downgrade leaves no signal in the trace span, which could make future regressions hard to detect. Neither blocks merging. apps/sim/app/api/billing/update-cost/route.ts — the new workspace lookup is on the hot billing path and lacks a span attribute to track attribution outcomes. Important Files Changed
Sequence DiagramsequenceDiagram
participant Go as Go Mothership / Self-hosted Client
participant Route as POST /api/billing/update-cost
participant WS as workspace table (DB)
participant UL as usage_log (DB)
Go->>Route: "POST { userId, cost, workspaceId? }"
Route->>Route: checkInternalApiKey()
Route->>Route: parseRequest (Zod — workspaceId now optional)
alt workspaceId provided
Route->>WS: "SELECT id WHERE id = workspaceId LIMIT 1"
alt workspace exists in this deployment
WS-->>Route: "[{ id: workspaceId }]"
Note over Route: attributedWorkspaceId = workspaceId
else workspace NOT found (self-hosted / foreign)
WS-->>Route: []
Note over Route: WARN + attributedWorkspaceId = undefined
end
else workspaceId omitted (headless)
Note over Route: attributedWorkspaceId = undefined (no DB query)
end
alt idempotencyKey present
Route->>UL: "recordCumulativeUsage({ ..., workspaceId: attributedWorkspaceId })"
else no idempotencyKey
Route->>UL: "recordUsage({ ..., workspaceId: attributedWorkspaceId })"
end
UL-->>Route: success (no FK violation possible)
Route->>Route: checkAndBillOverageThreshold(userId)
Route-->>Go: 200 OK
Reviews (1): Last reviewed commit: "fix(attribution): workspace id attr shou..." | Re-trigger Greptile |

Summary
Make workspace attribution best-effort on /api/billing/update-cost — workspaceId is now optional and resolved against this deployment before stamping (recording unattributed when foreign/missing), so self-hosted and headless flushes no longer die on usage_log FK violations and strand real cost in the dead-letter queue; failure logs now carry the Postgres SQLSTATE/constraint.
Type of Change
Testing
Tested manually
Checklist