Repository navigation
feat(demo-booking): send demo requests and booking decisions to a sales-channel webhook - #10015
waleedlatif1 wants to merge 1 commit into
Conversation
…es-channel webhook
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
[Medium impact] The PR appears safe to merge, with the earlier non-blocking duplicate-notification concern still open. Findings
SummaryAdds optional sales-channel webhook events for demo requests and booking decisions.
|
| if (decision !== 'declined') { | ||
| after(() => | ||
| notifyDemoRequest({ | ||
| type: 'demo_request.booking', | ||
| bookingUid: uid, |
There was a problem hiding this comment.
Every repeated Cal.com delivery sends demo_request.booking again for the same bookingUid. claimDemoBooker remembers the original lookup, but it does not stop another notification. An unverified booking stays pending on every delivery, so each retry sends another sales event and can create duplicate cards or manual review work.
Add a separate notification claim keyed by bookingUid to filter repeated deliveries.
There was a problem hiding this comment.
2 issues found across 6 files
Confidence score: 3/5
- Repeated Cal.com deliveries for the same
bookingUidcan schedule duplicate sales notifications inapps/sim/app/api/demo-requests/bookings/route.ts. Only schedule a notification when this request creates the claim. - In
apps/sim/lib/demo-booking/notify.ts, leaving the response body untouched can keep the connection open until garbage collection. Cancel the body before checking the status.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/sim/lib/demo-booking/notify.ts">
<violation number="1" location="apps/sim/lib/demo-booking/notify.ts:57">
P3: The response body is never consumed or cancelled, so each send can hold its connection until GC. Cancel the body before checking the status, as the connector clients already do.</violation>
</file>
<file name="apps/sim/app/api/demo-requests/bookings/route.ts">
<violation number="1" location="apps/sim/app/api/demo-requests/bookings/route.ts:102">
P2: Repeated Cal.com deliveries for the same `bookingUid` can schedule another sales notification because `reviewDemoBookingRequest` returns the stored claim but this branch does not distinguish first from repeated processing. Deduplicate booking notifications by claim/booking ID before scheduling the webhook event.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Turn on auto-fix | Re-trigger cubic
|
|
||
| // A declined booking had no form submission behind it, which is what a bot | ||
| // booking the public link looks like, so the sales channel never hears of it. | ||
| if (decision !== 'declined') { |
There was a problem hiding this comment.
P2: Repeated Cal.com deliveries for the same bookingUid can schedule another sales notification because reviewDemoBookingRequest returns the stored claim but this branch does not distinguish first from repeated processing. Deduplicate booking notifications by claim/booking ID before scheduling the webhook event.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/sim/app/api/demo-requests/bookings/route.ts, line 102:
<comment>Repeated Cal.com deliveries for the same `bookingUid` can schedule another sales notification because `reviewDemoBookingRequest` returns the stored claim but this branch does not distinguish first from repeated processing. Deduplicate booking notifications by claim/booking ID before scheduling the webhook event.</comment>
<file context>
@@ -86,10 +89,27 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
+
+ // A declined booking had no form submission behind it, which is what a bot
+ // booking the public link looks like, so the sales channel never hears of it.
+ if (decision !== 'declined') {
+ after(() =>
+ notifyDemoRequest({
</file context>
| body: JSON.stringify(event), | ||
| signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), | ||
| }) | ||
| if (!response.ok) { |
There was a problem hiding this comment.
P3: The response body is never consumed or cancelled, so each send can hold its connection until GC. Cancel the body before checking the status, as the connector clients already do.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/sim/lib/demo-booking/notify.ts, line 57:
<comment>The response body is never consumed or cancelled, so each send can hold its connection until GC. Cancel the body before checking the status, as the connector clients already do.</comment>
<file context>
@@ -0,0 +1,66 @@
+ body: JSON.stringify(event),
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
+ })
+ if (!response.ok) {
+ logger.warn('Demo request webhook rejected the event', {
+ type: event.type,
</file context>
| if (!response.ok) { | |
| await response.body?.cancel() | |
| if (!response.ok) { |
|
Closing: this is moving into Sim workflows driven by Cal.com webhooks, which already carry the form's details in the booking notes, so the app doesn't need to send anything. |
Summary
notifyDemoRequestposts/demoevents toDEMO_REQUEST_WEBHOOK_URL(bearerDEMO_REQUEST_WEBHOOK_TOKEN), so the sales channel gets one card per request instead of a forwarded emaildemo_request.submittedafter its record is saved; the Cal.com booking webhook sendsdemo_request.bookingwith the decision, start time and attendeeafter(), so they never slow the visitor or the Cal.com ack, and a failure is logged and droppedType of Change
Testing
biome on the changed files; type-check and audits in CI
Checklist
test-auditauthoring gate)