-
Notifications
You must be signed in to change notification settings - Fork 3.3k
improvement(billing): duplicate checks for bypasses, logger billing actor consistency, run from block #3107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: staging
Are you sure you want to change the base?
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Greptile OverviewGreptile SummaryThis PR strengthens billing integrity by adding duplicate subscription checks, ensuring billing actor consistency, and extending billing enforcement to run-from-block executions. Key Changes
Architecture ImpactThe changes consolidate billing logic into reusable helpers and ensure consistent billing actor resolution across execution paths. The duplicate subscription checks create multiple defense layers at authorization, checkout, transfer, and organization creation points. Confidence Score: 5/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Client
participant ExecuteAPI as Execute-from-Block API
participant Preprocessing as preprocessExecution
participant Billing as Billing Module
participant Logger as ExecutionLogger
participant DB as Database
Client->>ExecuteAPI: POST /workflows/{id}/execute-from-block
ExecuteAPI->>Preprocessing: Check billing & limits
Preprocessing->>DB: Fetch workflow record
DB-->>Preprocessing: Workflow details
Preprocessing->>Billing: Get workspace billed account
Billing-->>Preprocessing: actorUserId
Preprocessing->>Billing: Check usage limits
Billing-->>Preprocessing: Usage check result
alt Usage exceeded or blocked
Preprocessing-->>ExecuteAPI: Error (402/403)
ExecuteAPI-->>Client: Execution blocked
else Checks passed
Preprocessing-->>ExecuteAPI: Success with actorUserId
ExecuteAPI->>ExecuteAPI: Execute workflow
ExecuteAPI->>Logger: Log execution with costs
Logger->>Billing: Get workspace billed account
Billing-->>Logger: billingUserId
Logger->>DB: Update userStats (billing actor)
DB-->>Logger: Updated
Logger-->>ExecuteAPI: Logged
ExecuteAPI-->>Client: Execution result
end
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5 files reviewed, no comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| .where(and(inArray(userStats.userId, memberIds), eq(userStats.billingBlockedReason, reason))) | ||
|
|
||
| return memberIds.length | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return value doesn't reflect actual unblocked member count
Low Severity
The unblockOrgMembers function returns memberIds.length (total org members), but the SQL update only affects members where billingBlockedReason matches the provided reason. This means the return value doesn't reflect how many users were actually unblocked. The memberCount value logged in disputes.ts and elsewhere will be misleading, potentially causing confusion during incident response or auditing.
| organizationId: orgId, | ||
| memberCount, | ||
| status: dispute.status, | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Org members may stay blocked after dispute won
Medium Severity
The handleDisputeClosed function unblocks Pro users unconditionally (line 110), but uses unblockOrgMembers(orgId, 'dispute') for org members which only unblocks those with billingBlockedReason='dispute'. If a payment failure occurs while a dispute is pending, blockOrgMembers overwrites the reason to 'payment_failed'. When the dispute is later won, org members won't be unblocked because their reason no longer matches 'dispute'. The old code unblocked the owner unconditionally, matching the Pro user behavior.


Summary
Type of Change
Testing
Tested manually
Checklist