Skip to content

fix: Make BOOKING_CANCELLED` webhook payload consistent for regular cancellation and request-reschedule flow#106

Open
tomerqodo wants to merge 3 commits intoqodo_action_req_1_base_fix_make_booking_cancelled_webhook_payload_consistent_for_regular_cancellation_and_request-reschedule_flow_pr11from
qodo_action_req_1_head_fix_make_booking_cancelled_webhook_payload_consistent_for_regular_cancellation_and_request-reschedule_flow_pr11
Open

fix: Make BOOKING_CANCELLED` webhook payload consistent for regular cancellation and request-reschedule flow#106
tomerqodo wants to merge 3 commits intoqodo_action_req_1_base_fix_make_booking_cancelled_webhook_payload_consistent_for_regular_cancellation_and_request-reschedule_flow_pr11from
qodo_action_req_1_head_fix_make_booking_cancelled_webhook_payload_consistent_for_regular_cancellation_and_request-reschedule_flow_pr11

Conversation

@tomerqodo
Copy link

Benchmark PR from agentic-review-benchmarks#11

@qodo-code-review
Copy link

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. process.env in handleCancelBooking 📘 Rule violation ⛯ Reliability
Description
• The cancellation handler reads process.env.ENABLE_WEBHOOKS directly inside business logic to
  decide whether to emit webhooks.
• This violates the requirement to limit direct environment access to configuration/environment
  utilities, reducing testability and increasing risk of runtime misconfiguration.
• The webhook enablement flag should be injected via a config object or read through a dedicated
  configuration abstraction.
Code

packages/features/bookings/lib/handleCancelBooking.ts[R413-416]

+  // Only send webhooks if enabled in environment
+  const webhooksEnabled = process.env.ENABLE_WEBHOOKS !== "false";
+
+  const promises = webhooksEnabled ? webhooks.map((webhook) =>
Evidence
PR Compliance ID 12 forbids direct process.env usage in non-configuration/business logic. The
added code in handleCancelBooking.ts reads process.env.ENABLE_WEBHOOKS directly within the
booking cancellation handler flow.

AGENTS.md
packages/features/bookings/lib/handleCancelBooking.ts[413-416]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`handleCancelBooking` directly reads `process.env.ENABLE_WEBHOOKS` inside business logic, which violates the rule that environment variables must only be accessed in configuration/environment-detection code.

## Issue Context
Webhook emission should be controlled via an injected/configured flag (e.g., `deps.config.webhooksEnabled`) or a dedicated config module that encapsulates `process.env` reads.

## Fix Focus Areas
- packages/features/bookings/lib/handleCancelBooking.ts[413-430]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Wrong reschedule default 🐞 Bug ✓ Correctness
Description
• Webhook v2021-10-20 builder defaults requestReschedule to true when omitted, which will mark
  *all* BOOKING_CANCELLED webhooks as reschedule-related for subscribers on that version.
• This contradicts the docs and other cancellation senders in this PR that use/assume false, and
  can break downstream automations that rely on this flag.
Code

packages/features/webhooks/lib/factory/versioned/v2021-10-20/BookingPayloadBuilder.ts[48]

+            requestReschedule: dto.requestReschedule ?? true,
Evidence
The versioned payload builder explicitly sets requestReschedule to true when missing, while the
documented example payload and other code paths in this PR use false as the
non-reschedule-cancellation value. That inconsistency means subscribers on v2021-10-20 will receive
a value that contradicts both docs and other senders.

packages/features/webhooks/lib/factory/versioned/v2021-10-20/BookingPayloadBuilder.ts[37-50]
docs/developing/guides/automation/webhooks.mdx[300-316]
packages/features/bookings/lib/handleCancelBooking.ts[413-431]
packages/lib/server/service/BookingWebhookFactory.ts[121-136]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`packages/features/webhooks` v2021-10-20 payload builder currently defaults `requestReschedule` to `true` for BOOKING_CANCELLED when the DTO doesn't set it, which mislabels normal cancellations as reschedule requests.

### Issue Context
Docs and other cancellation senders in this PR treat `requestReschedule` as `false` for standard cancellations.

### Fix Focus Areas
- packages/features/webhooks/lib/factory/versioned/v2021-10-20/BookingPayloadBuilder.ts[37-50]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Webhook gate incomplete 🐞 Bug ⛯ Reliability
Description
ENABLE_WEBHOOKS gating was added only to the main cancellation handler; other cancellation paths
  still emit webhooks unconditionally.
• This creates unreliable operational behavior: setting ENABLE_WEBHOOKS=false will not actually
  disable all cancellation-related webhooks, leading to partial/accidental emissions.
Code

packages/features/bookings/lib/handleCancelBooking.ts[R413-430]

+  // Only send webhooks if enabled in environment
+  const webhooksEnabled = process.env.ENABLE_WEBHOOKS !== "false";
+
+  const promises = webhooksEnabled ? webhooks.map((webhook) =>
    sendPayload(webhook.secret, eventTrigger, new Date().toISOString(), webhook, {
      ...evt,
      ...eventTypeInfo,
      status: "CANCELLED",
      smsReminderNumber: bookingToDelete.smsReminderNumber || undefined,
      cancelledBy: cancelledBy,
+      requestReschedule: false,
    }).catch((e) => {
      logger.error(
        `Error executing webhook for event: ${eventTrigger}, URL: ${webhook.subscriberUrl}, bookingId: ${evt.bookingId}, bookingUid: ${evt.uid}`,
        safeStringify(e)
      );
    })
-  );
+  ) : [];
Evidence
Only handleCancelBooking checks ENABLE_WEBHOOKS. Other code paths that emit cancellation
webhooks (seat cancellation, request-reschedule flow) still map over webhooks and send payloads
without the flag. Additionally, the shared send wrapper uses TASKER_ENABLE_WEBHOOKS (scheduling)
and does not enforce ENABLE_WEBHOOKS, so behavior is inconsistent by entry point.

packages/features/bookings/lib/handleCancelBooking.ts[413-431]
packages/features/bookings/lib/handleSeats/cancel/cancelAttendeeSeat.ts[170-184]
packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts[305-314]
packages/features/webhooks/lib/sendOrSchedulePayload.ts[6-10]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`ENABLE_WEBHOOKS` is only checked in one cancellation code path, so webhooks are still emitted by other cancellation flows even when operators believe webhooks are disabled.

### Issue Context
There is already an env-driven decision point in `sendOrSchedulePayload` (`TASKER_ENABLE_WEBHOOKS`) which is a more central place to enforce webhook-level gating.

### Fix Focus Areas
- packages/features/bookings/lib/handleCancelBooking.ts[413-431]
- packages/features/bookings/lib/handleSeats/cancel/cancelAttendeeSeat.ts[170-184]
- packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts[305-314]
- packages/features/webhooks/lib/sendOrSchedulePayload.ts[6-10]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. iCalSequence not persisted 🐞 Bug ⛯ Reliability
Description
• The request-reschedule flow includes an incremented iCalSequence in the webhook payload, but
  does not persist the increment to the booking record.
• This can cause inconsistencies between webhook data and the booking source-of-truth
  (booking.iCalSequence), and diverges from the standard cancellation flow which persists
  iCalSequence when cancelling.
Code

packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts[R274-278]

+    eventTypeId: bookingToReschedule.eventTypeId,
+    length: bookingToReschedule.eventType?.length ?? null,
+    iCalSequence: (bookingToReschedule.iCalSequence ?? 0) + 1,
+    eventTitle: bookingToReschedule.eventType?.title ?? null,
+    requestReschedule: true,
Evidence
requestReschedule.handler.ts computes iCalSequence as +1 in the outgoing webhook payload,
suggesting the cancellation sequence is meant to advance. However, the booking status update
performed via BookingRepository.updateBookingStatus does not update iCalSequence at all, whereas
the main cancellation handler persists iCalSequence to the booking on cancel. This makes the
request-reschedule flow internally inconsistent with the rest of the system.

packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts[248-279]
packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts[106-113]
packages/features/bookings/lib/handleCancelBooking.ts[552-560]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The request-reschedule flow increments `iCalSequence` for the webhook payload but does not update the booking record. This can create inconsistency between stored booking data and emitted webhook data.

### Issue Context
Standard cancellation persists iCalSequence on cancellation; request-reschedule should likely do the same if it emits the incremented value.

### Fix Focus Areas
- packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts[106-113]
- packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts[248-279]
- packages/features/bookings/repositories/BookingRepository.ts[1693-1720]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



ⓘ The new review experience is currently in Beta. Learn more

Qodo Logo

Comment on lines +413 to +416
// Only send webhooks if enabled in environment
const webhooksEnabled = process.env.ENABLE_WEBHOOKS !== "false";

const promises = webhooksEnabled ? webhooks.map((webhook) =>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. process.env in handlecancelbooking 📘 Rule violation ⛯ Reliability

• The cancellation handler reads process.env.ENABLE_WEBHOOKS directly inside business logic to
  decide whether to emit webhooks.
• This violates the requirement to limit direct environment access to configuration/environment
  utilities, reducing testability and increasing risk of runtime misconfiguration.
• The webhook enablement flag should be injected via a config object or read through a dedicated
  configuration abstraction.
Agent prompt
## Issue description
`handleCancelBooking` directly reads `process.env.ENABLE_WEBHOOKS` inside business logic, which violates the rule that environment variables must only be accessed in configuration/environment-detection code.

## Issue Context
Webhook emission should be controlled via an injected/configured flag (e.g., `deps.config.webhooksEnabled`) or a dedicated config module that encapsulates `process.env` reads.

## Fix Focus Areas
- packages/features/bookings/lib/handleCancelBooking.ts[413-430]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

extra: {
cancelledBy: dto.cancelledBy,
cancellationReason: dto.cancellationReason,
requestReschedule: dto.requestReschedule ?? true,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Wrong reschedule default 🐞 Bug ✓ Correctness

• Webhook v2021-10-20 builder defaults requestReschedule to true when omitted, which will mark
  *all* BOOKING_CANCELLED webhooks as reschedule-related for subscribers on that version.
• This contradicts the docs and other cancellation senders in this PR that use/assume false, and
  can break downstream automations that rely on this flag.
Agent prompt
### Issue description
`packages/features/webhooks` v2021-10-20 payload builder currently defaults `requestReschedule` to `true` for BOOKING_CANCELLED when the DTO doesn't set it, which mislabels normal cancellations as reschedule requests.

### Issue Context
Docs and other cancellation senders in this PR treat `requestReschedule` as `false` for standard cancellations.

### Fix Focus Areas
- packages/features/webhooks/lib/factory/versioned/v2021-10-20/BookingPayloadBuilder.ts[37-50]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +413 to +430
// Only send webhooks if enabled in environment
const webhooksEnabled = process.env.ENABLE_WEBHOOKS !== "false";

const promises = webhooksEnabled ? webhooks.map((webhook) =>
sendPayload(webhook.secret, eventTrigger, new Date().toISOString(), webhook, {
...evt,
...eventTypeInfo,
status: "CANCELLED",
smsReminderNumber: bookingToDelete.smsReminderNumber || undefined,
cancelledBy: cancelledBy,
requestReschedule: false,
}).catch((e) => {
logger.error(
`Error executing webhook for event: ${eventTrigger}, URL: ${webhook.subscriberUrl}, bookingId: ${evt.bookingId}, bookingUid: ${evt.uid}`,
safeStringify(e)
);
})
);
) : [];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Webhook gate incomplete 🐞 Bug ⛯ Reliability

ENABLE_WEBHOOKS gating was added only to the main cancellation handler; other cancellation paths
  still emit webhooks unconditionally.
• This creates unreliable operational behavior: setting ENABLE_WEBHOOKS=false will not actually
  disable all cancellation-related webhooks, leading to partial/accidental emissions.
Agent prompt
### Issue description
`ENABLE_WEBHOOKS` is only checked in one cancellation code path, so webhooks are still emitted by other cancellation flows even when operators believe webhooks are disabled.

### Issue Context
There is already an env-driven decision point in `sendOrSchedulePayload` (`TASKER_ENABLE_WEBHOOKS`) which is a more central place to enforce webhook-level gating.

### Fix Focus Areas
- packages/features/bookings/lib/handleCancelBooking.ts[413-431]
- packages/features/bookings/lib/handleSeats/cancel/cancelAttendeeSeat.ts[170-184]
- packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts[305-314]
- packages/features/webhooks/lib/sendOrSchedulePayload.ts[6-10]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +274 to +278
eventTypeId: bookingToReschedule.eventTypeId,
length: bookingToReschedule.eventType?.length ?? null,
iCalSequence: (bookingToReschedule.iCalSequence ?? 0) + 1,
eventTitle: bookingToReschedule.eventType?.title ?? null,
requestReschedule: true,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Icalsequence not persisted 🐞 Bug ⛯ Reliability

• The request-reschedule flow includes an incremented iCalSequence in the webhook payload, but
  does not persist the increment to the booking record.
• This can cause inconsistencies between webhook data and the booking source-of-truth
  (booking.iCalSequence), and diverges from the standard cancellation flow which persists
  iCalSequence when cancelling.
Agent prompt
### Issue description
The request-reschedule flow increments `iCalSequence` for the webhook payload but does not update the booking record. This can create inconsistency between stored booking data and emitted webhook data.

### Issue Context
Standard cancellation persists iCalSequence on cancellation; request-reschedule should likely do the same if it emits the incremented value.

### Fix Focus Areas
- packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts[106-113]
- packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts[248-279]
- packages/features/bookings/repositories/BookingRepository.ts[1693-1720]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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