Skip to content

chore: Integrate confirmation booking audit#26523

Merged
Udit-takkar merged 30 commits intomainfrom
devin/booking-confirmation-audit-1767764589
Jan 12, 2026
Merged

chore: Integrate confirmation booking audit#26523
Udit-takkar merged 30 commits intomainfrom
devin/booking-confirmation-audit-1767764589

Conversation

@hariombalhara
Copy link
Member

@hariombalhara hariombalhara commented Jan 7, 2026

What does this PR do?

Integrates booking audit logging for booking confirmation (acceptance) and rejection events. This is part of the booking audit integration plan (PR-2).

Note: This PR is stacked on #26567 which refactors the link and verify-booking-token routes to use confirmHandler directly instead of the tRPC caller pattern.

Core Changes:

  • handleConfirmation.ts: Added audit logging for single booking acceptance (onBookingAccepted) and bulk/recurring booking acceptance (onBulkBookingsAccepted). Refactored to use SimplifiedActorIdentifier union type for flexible actor specification.
  • confirm.handler.ts: Added audit logging for booking rejection (onBookingRejected) via fireRejectionEvent helper. Passes actionSource/userUuid to handleConfirmation. Input type now requires actionSource and actor.
  • zod-utils.ts: Added required actionSource field to the booking confirm input schema (values: WEBAPP, API_V1, API_V2, WEBHOOK, MAGIC_LINK)
  • _router.tsx: Explicitly adds actionSource: "WEBAPP" and actor when calling confirmHandler from tRPC
  • API v2 bookings.service.ts: Passes actionSource: "API_V2" and actor for confirm and decline operations
  • link/route.ts & verify-booking-token/route.ts: Pass actionSource: "MAGIC_LINK" and actor for magic link confirmations

Payment Webhook Integration:

  • handlePaymentSuccess.ts: Refactored to accept object params including appSlug for actor identification. Creates app actor from credentialId or falls back to appSlug.
  • Payment webhooks (alby, btcpayserver, hitpay, paypal, stripe): Updated to pass their respective appSlug for audit actor identification
  • Stripe webhook.ts: Added actor creation for payment setup success flow

Schema Changes:

  • schema.prisma: Added MAGIC_LINK to BookingAuditSource enum
  • Migration: Added 20260107093019_add_magic_link_source migration
  • RejectedAuditActionService.ts: Changed rejectionReason from StringChangeSchema (old/new) to z.string().nullable() (single value). Changed status to use BookingStatusChangeSchema.
  • dto/types.ts: Added ActorIdentification type export

Test Infrastructure:

  • Refactored integration test utilities into reusable integration-utils.ts
  • Updated route tests to mock confirmHandler directly and include makeUserActor mock

Updates since last revision

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A - internal audit logging only.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works. N/A - audit logging is non-blocking and wrapped in try-catch.

How should this be tested?

  1. Accept a single booking → verify audit log is created with onBookingAccepted
  2. Accept recurring bookings → verify audit logs are created with onBulkBookingsAccepted and share the same operationId
  3. Reject a booking → verify audit log is created with onBookingRejected
  4. Confirm/decline via API v2 → verify actionSource is "API_V2"
  5. Complete a payment via Stripe/PayPal/etc → verify audit log has correct app actor
  6. New: Confirm via magic link → verify actionSource is "MAGIC_LINK"

Human Review Checklist

  • Verify PR refactor: Use confirmHandler directly in link and verify-booking-token routes[booking-audit-prerequisite] #26567 is merged before this PR (stacked dependency)
  • Verify the MAGIC_LINK migration runs correctly
  • Verify all callers of handleConfirmation pass required actionSource and either userUuid or actor
  • Verify the SimplifiedActorIdentifier union type correctly enforces mutual exclusivity of userUuid and actor
  • Verify payment webhook handlers correctly identify their app via appSlug
  • Verify the RejectedAuditData schema change (rejectionReason no longer has old/new) is acceptable
  • Verify the guard clause behavior (skipping audit when actor is undefined) is acceptable
  • Note: Bulk rejection (recurring events) currently only logs the primary booking, not all related bookings - confirm if this is acceptable

Checklist

  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • I have checked if my changes generate no new warnings

Link to Devin run: https://app.devin.ai/sessions/5914b63665314f9480f0cf5fd2d6fd13
Requested by: @hariombalhara

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
@vercel
Copy link

vercel bot commented Jan 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
cal-com-v2 Building Building Preview, Comment Jan 8, 2026 9:31am
cal-com-v2-1767797589266-uOAD Canceled Canceled Jan 8, 2026 9:31am
cal-com-v2-5dan Canceled Canceled Jan 8, 2026 9:31am
4 Skipped Deployments
Project Deployment Review Updated (UTC)
api-v2 Ignored Ignored Preview Jan 8, 2026 9:31am
cal Ignored Ignored Jan 8, 2026 9:31am
cal-companion Ignored Ignored Preview Jan 8, 2026 9:31am
cal-eu Ignored Ignored Jan 8, 2026 9:31am

…sable' into devin/booking-confirmation-audit-1767764589
…entification

- Updated handlePaymentSuccess function to accept an object with paymentId, bookingId, appSlug, and traceContext.
- Introduced getActor function to determine the actor based on appSlug and credentialId.
- Modified webhook handlers for Alby, BTCPayServer, HitPay, PayPal, and Stripe to pass the new parameters.
- Improved logging for missing credentialId in payment processing.
- Adjusted related schemas to ensure proper type handling for booking status and actor identification.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
…ross booking services

- Added `makeUserActor` to various booking service files to enhance actor identification.
- Updated action source handling in booking confirmation and related functions to include "MAGIC_LINK".
- Refactored schemas to accommodate new actor and action source requirements, ensuring consistent type handling.
- Improved error handling and logging for booking actions to enhance traceability.
….slug

This commit modifies the appSlug parameter in the handlePaymentSuccess function across multiple payment webhook handlers to utilize the appConfig.slug value instead of hardcoded strings. This change enhances consistency and maintainability of the code.

Changes:
- Updated appSlug in handlePaymentSuccess for btcpayserver, hitpay, and paypal webhooks.
- Adjusted a test case to reflect the new appSlug value for consistency.
@hariombalhara hariombalhara marked this pull request as ready for review January 8, 2026 08:43
@hariombalhara hariombalhara requested review from a team as code owners January 8, 2026 08:43
@graphite-app graphite-app bot added enterprise area: enterprise, audit log, organisation, SAML, SSO core area: core, team members only labels Jan 8, 2026
@graphite-app graphite-app bot requested a review from a team January 8, 2026 08:43
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

7 issues found across 26 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/app/api/verify-booking-token/__tests__/route.test.ts">

<violation number="1" location="apps/web/app/api/verify-booking-token/__tests__/route.test.ts:349">
P2: Test does not verify that `actor` is passed to `confirmHandler` for the reject action. Add `actor: { type: "user", id: "test-uuid" }` to the assertion to verify audit actor is passed correctly.</violation>

<violation number="2" location="apps/web/app/api/verify-booking-token/__tests__/route.test.ts:371">
P2: Test 'should redirect with error when user not found' is missing the assertion `expect(mockConfirmHandler).not.toHaveBeenCalled()`. The parallel test for 'booking not found' includes this check - add it here for consistency and to verify the handler isn't called when user lookup fails.</violation>
</file>

<file name="packages/features/booking-audit/lib/service/__tests__/accepted-action.integration-test.ts">

<violation number="1" location="packages/features/booking-audit/lib/service/__tests__/accepted-action.integration-test.ts:69">
P2: Test cleanup for `booking2` and `booking3` is unreliable. If any assertion fails before reaching the cleanup code, these bookings won't be deleted, causing test pollution. Consider tracking dynamically created bookings in an array and cleaning them up in `afterEach`, or wrap the test body in a try/finally block to ensure cleanup runs regardless of test outcome.</violation>
</file>

<file name="packages/features/booking-audit/lib/types/actionSource.ts">

<violation number="1" location="packages/features/booking-audit/lib/types/actionSource.ts:3">
P3: Typo in comment: "explcit" should be "explicit".</violation>
</file>

<file name="packages/features/bookings/lib/handleConfirmation.ts">

<violation number="1" location="packages/features/bookings/lib/handleConfirmation.ts:409">
P2: Missing error handling: `fireBookingAcceptedEvent` should be wrapped in try-catch to prevent audit failures from breaking booking confirmation. The PR description states audit logging should be non-blocking, and other similar operations in this file (workflow scheduling) follow this pattern.</violation>
</file>

<file name="packages/trpc/server/routers/viewer/bookings/confirm.handler.ts">

<violation number="1" location="packages/trpc/server/routers/viewer/bookings/confirm.handler.ts:468">
P2: Missing try-catch around `fireRejectionEvent` call. The PR description states audit logging should be non-blocking and wrapped in try-catch, but this await has no error handling. If the audit service fails, it will cause the booking rejection handler to fail even though the database updates have already been committed, leading to inconsistent state and missed webhooks.</violation>
</file>

<file name="packages/features/booking-audit/lib/actions/RejectedAuditActionService.ts">

<violation number="1" location="packages/features/booking-audit/lib/actions/RejectedAuditActionService.ts:20">
P2: Schema shape change for `rejectionReason` (from `{ old, new }` object to simple string) without incrementing VERSION or adding migration logic. If any existing data exists with the old format, `parseStored` and `migrateToLatest` will fail. Consider either:
1. Incrementing VERSION to 2 and adding migration logic in `migrateToLatest` to transform `{ old, new }` → `new`
2. Adding a comment confirming no production data exists yet with this schema</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

This commit adds additional assertions to the booking token verification tests to ensure that the confirmHandler is not called when an error occurs. It also introduces a mechanism to clean up additional booking UIDs after each test in the accepted action integration tests, improving test reliability. Furthermore, it updates the action source schema comment for clarity.

Changes:
- Updated tests in `verify-booking-token` to check that `mockConfirmHandler` is not called on error.
- Implemented cleanup logic for additional booking UIDs in `accepted-action.integration-test.ts`.
- Clarified comment in `actionSource.ts` regarding the schema for action sources.
- Refactored `handleConfirmation.ts` and `confirm.handler.ts` to include tracing logger for error handling in booking events.
let actor: Actor;
const appData = apps?.[appSlug as keyof typeof apps];
if (appData?.credentialId) {
actor = makeAppActor({ credentialId: appData.credentialId });
Copy link
Contributor

Choose a reason for hiding this comment

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

We have too many functions like makeUserActor, makeGuestActor. We should just create a single factory class that would handle all the different types

Copy link
Member Author

@hariombalhara hariombalhara Jan 8, 2026

Choose a reason for hiding this comment

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

I would have to think about it, though I will implement in a followup.

Do you have something specific in mind?

The way I see it a route/Service would have to specifically identify what kind of actor took the action. That decision is pretty specific to the route depdning on what data is passed to it.

Once it knows what actor it needs to use, it just needs to call appropriate fn. But I totally feel it can be improved, in some way,

@hariombalhara hariombalhara changed the title chore: Integrate booking confirmation booking audit chore: Integrate confirmation booking audit Jan 8, 2026
Copy link
Contributor

@Udit-takkar Udit-takkar left a comment

Choose a reason for hiding this comment

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

LGTM. just few small followups

Copy link
Member

@alishaz-polymath alishaz-polymath left a comment

Choose a reason for hiding this comment

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

Let's go 🚀 🚀 🚀

@Udit-takkar Udit-takkar enabled auto-merge (squash) January 12, 2026 06:13
@Udit-takkar Udit-takkar merged commit 77f59b1 into main Jan 12, 2026
44 of 45 checks passed
@Udit-takkar Udit-takkar deleted the devin/booking-confirmation-audit-1767764589 branch January 12, 2026 11:17
Anshumancanrock pushed a commit to Anshumancanrock/cal.com that referenced this pull request Jan 12, 2026
* chore: Integrate booking confirmation booking audit

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* fix: Use BookingStatus type instead of string for booking.status

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* Make booking-audit integration test utils reusable

* refactor: enhance handlePaymentSuccess to accept appSlug and actor identification

- Updated handlePaymentSuccess function to accept an object with paymentId, bookingId, appSlug, and traceContext.
- Introduced getActor function to determine the actor based on appSlug and credentialId.
- Modified webhook handlers for Alby, BTCPayServer, HitPay, PayPal, and Stripe to pass the new parameters.
- Improved logging for missing credentialId in payment processing.
- Adjusted related schemas to ensure proper type handling for booking status and actor identification.

* fix: Correct import paths and getActor function call

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* fix: Use ActorIdentification type instead of AuditActor in getActor

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* fix: Add guard clause for undefined actor in fireBookingAcceptedEvent

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* fix: Add actionSource to all confirm calls

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* refactor: Integrate actor identification and action source updates across booking services

- Added `makeUserActor` to various booking service files to enhance actor identification.
- Updated action source handling in booking confirmation and related functions to include "MAGIC_LINK".
- Refactored schemas to accommodate new actor and action source requirements, ensuring consistent type handling.
- Improved error handling and logging for booking actions to enhance traceability.

* Remvoe formatting changes

* Add test

* refactor: Enhance booking confirmation tests and event handling

- Updated `confirm.handler.test.ts` to improve test coverage for booking acceptance and rejection scenarios, including bulk bookings.
- Refactored the mock implementation of `BookingEventHandlerService` to streamline event handling for accepted and rejected bookings.
- Adjusted the `handleConfirmation` function to utilize `acceptedBookings` for better clarity and maintainability.
- Added tests to ensure correct invocation of event handler methods for both single and bulk booking confirmations and rejections.

* fix tests

* refactor: Use confirmHandler directly in link and verify-booking-token routes

Refactors the link and verify-booking-token API routes to call confirmHandler directly instead of using the tRPC caller pattern. This simplifies the code by removing the need for session getter, legacy request building, and context creation.

Changes:
- apps/web/app/api/link/route.ts: Use confirmHandler directly with ctx and input
- apps/web/app/api/verify-booking-token/route.ts: Use confirmHandler directly with ctx and input
- Updated tests to mock confirmHandler instead of tRPC caller

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* fix ts errors due to merge frommain

* feat: introduce getAppActor utility for actor creation

This commit adds a new utility function, getAppActor, to streamline the process of creating actor objects for apps based on their slug and credential ID. The function is integrated into handlePaymentSuccess and handleStripePaymentSuccess, replacing the previous inline actor creation logic. This refactor enhances code maintainability and readability by centralizing actor creation logic.

Changes:
- New file: packages/app-store/_utils/getAppActor.ts
- Updated handlePaymentSuccess and handleStripePaymentSuccess to use getAppActor
- Removed redundant actor creation code from these functions

* refactor: Update appSlug in payment success handlers to use appConfig.slug

This commit modifies the appSlug parameter in the handlePaymentSuccess function across multiple payment webhook handlers to utilize the appConfig.slug value instead of hardcoded strings. This change enhances consistency and maintainability of the code.

Changes:
- Updated appSlug in handlePaymentSuccess for btcpayserver, hitpay, and paypal webhooks.
- Adjusted a test case to reflect the new appSlug value for consistency.

* test: Enhance booking token verification and audit action tests

This commit adds additional assertions to the booking token verification tests to ensure that the confirmHandler is not called when an error occurs. It also introduces a mechanism to clean up additional booking UIDs after each test in the accepted action integration tests, improving test reliability. Furthermore, it updates the action source schema comment for clarity.

Changes:
- Updated tests in `verify-booking-token` to check that `mockConfirmHandler` is not called on error.
- Implemented cleanup logic for additional booking UIDs in `accepted-action.integration-test.ts`.
- Clarified comment in `actionSource.ts` regarding the schema for action sources.
- Refactored `handleConfirmation.ts` and `confirm.handler.ts` to include tracing logger for error handling in booking events.

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@vercel vercel bot temporarily deployed to Preview – cal-companion January 13, 2026 08:48 Inactive
@vercel vercel bot temporarily deployed to Preview – dev January 13, 2026 08:49 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO ❗️ migrations contains migration files ready-for-e2e size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants