CodeIssuesPull RequestsActionsSecurityInsights
✨ AI
More
Settings

Fix critical booking flow bugs across all layers #3704

Merged⚡ AI-generatedMccantynz wants to mergeclaude/vigilant-wozniak-n1knptmainopened Jun 16, 20260/7 tasks
ccantynzcommented Jun 16, 2026

Originally written by @ccantynz-alt on GitHub.
Imported from https://github.com/ccantynz-alt/Hibiscus-to-airport/pull/43


Summary

End-to-end audit of the full booking system identified and fixed 15 bugs across 12 files spanning security, payments, notifications, and the booking form.

Security (Critical)

  • cancel.js had no auth — any anonymous person on the internet could cancel any booking. Added authenticateRequest guard.
  • Stripe webhook accepted unsigned events — when STRIPE_WEBHOOK_SECRET was missing, any POST could fake a payment and confirm bookings. Now rejects with 500 if secret not configured.
  • Clients could set status=confirmed / payment_status=paid on booking creation to skip payment entirely. Now hardcoded server-side to pending/unpaid (or pay_on_day for cash).
  • Webhook DB errors were swallowed — returning 200 on failure meant Stripe never retried, leaving paid bookings stuck as pending. Now returns 500 so Stripe retries.
  • update-status.js had no whitelist — any string could be written as booking status. Now validates against known values.

Payments

  • Promo discounts were never applied to Stripe — customers saw a discount on screen but were charged the full amount. handleSubmit now sends the discounted total to both the booking record and Stripe session.

Booking Form (BookingPage.jsx)

  • Address inputs used defaultValue (uncontrolled React inputs) — Google Places Autocomplete results could silently mismatch the displayed value. Changed to value.
  • Add-ons (VIP pickup, oversized luggage, return trip) weren't included in the price recalculation useEffect dependencies — toggling them didn't update the displayed price.
  • handleSubmit didn't check agreedTerms — pressing Enter in any field bypassed the disabled Book Now button and submitted without terms acceptance.
  • Added explicit address validation in handleSubmit (previously only guarded by uncontrolled HTML required).
  • Phone placeholder showed 021 123 4567 (the exact wrong number per CLAUDE.md). Changed to a generic example.
  • Import statements appeared after executable code (ES module violation). Moved all imports to the top.

Notifications

  • Customer confirmation email showed bookings@bookaride.co.nz instead of info@bookaride.co.nz.
  • Reminder email/SMS used snake_case field names (pickup_address) — when called with a rowToBooking() object (camelCase), pickup/dropoff showed as blank.
  • resend-email.js and resend-sms.js ignored the send result — always returned 200 "sent" even when Mailgun/Twilio rejected the message.
  • Cron reminders marked reminder_sent=true even when both email and SMS failed — those customers would never be retried.
  • Cron reminder "tomorrow" was calculated in UTC — in NZ timezone it could fire on the wrong calendar date.

Frontend Routing

  • CustomerTracking extracted trackingRef from useParams() but the route was path="/tracking/:ref" — the param was always undefined, making the tracking page permanently broken.
  • MyBooking.jsx used camelCase field names (pickupAddress, dropoffAddress, totalPrice) that don't exist in the API response (snake_case). Pickup/dropoff showed blank and price showed $NaN.

Test plan

  • Create a booking via the form — verify price updates when toggling VIP/oversized/return trip add-ons
  • Apply a promo code — verify the discounted amount is charged in Stripe (not the full price)
  • Complete a Stripe payment — verify booking status updates to confirmed and confirmation email arrives at customer's address with info@bookaride.co.nz shown
  • Attempt to cancel a booking without an auth token — verify 401 response
  • Navigate to /tracking/H123 — verify the page loads and polls correctly (was always showing "tracking not found" due to undefined ref)
  • Look up a booking on /my-booking — verify pickup, dropoff, and price all display correctly
  • Check reminder email/SMS content — verify pickup address is not blank

https://claude.ai/code/session_0128AhV6qVV1cEcCu4AhRP36


Generated by Claude Code

Cross-repo impact

See what breaks downstream if this PR merges.

Analyze →
⮌ Merged

This pull request was merged into main.

c comment · e edit title · m merge · a approve · r request changes · ? shortcuts