Commit Graph
15942 Commits
Author SHA1 Message Date
Joe Au-YeungGitHubClaude Opus 4.5joe@cal.com <j.auyeung419@gmail.com>joe@cal.com <j.auyeung419@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
7abbc8c22c feat: Routing trace presenter (#27372)
* feat: Add routing trace presenters

Add domain-specific presenters (SalesforceRoutingTracePresenter,
RoutingFormTracePresenter) that format trace steps into human-readable
strings, and a core RoutingTracePresenter that delegates to them based
on step domain. Includes unit tests for all presenters.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Add findByBookingUid to RoutingTraceRepository

Add method to look up a routing trace by booking UID, needed by the
routing trace presenter tRPC endpoint.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Add getRoutingTrace tRPC endpoint

Expose routing trace data for a booking via viewer.bookings.getRoutingTrace.
Tries the permanent RoutingTrace first (round robin bookings), then falls
back to PendingRoutingTrace via the booking's form response relation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Add routing trace side sheet to booking list item

Add a route icon button on booking list items that came from routing
forms. Clicking it opens a side sheet displaying the full routing trace
as human-readable steps. Adds RoutingTraceSheet component, store state,
and translation key.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: Move routing trace action to dropdown menu

Move the routing trace button from a standalone icon on the booking list
item into the actions dropdown menu alongside "Report wrong assignment".
The RoutingTraceSheet is now rendered from BookingActionsDropdown.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: Improve routing trace UI and handle unnamed routes

- Redesign RoutingTraceSheet with vertical timeline layout, domain badges,
  skeleton loading state, and millisecond timestamps
- Use Salesforce app-store icon for Salesforce steps
- Fall back to "Unnamed route" when route name is missing or matches route ID
- Fix dropdown menu icon to git-merge (valid icon, unique in menu)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test: Add tests for getRoutingTrace handler and findByBookingUid repository method

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* Abstract functions

* Fix build error

* Add permission check

* fix: Update getRoutingTrace tests to include ctx and mock BookingAccessService

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 15:26:44 -03:00
Eunjae LeeandGitHub e7d38755dd refactor: use DI-ed cached FeaturesRepository in flags router (#27394)
## What does this PR do?

Replaces direct instantiation of `FeaturesRepository` with the dependency-injected version using `getFeaturesRepository()` from the DI container in the feature flags router.

**Key improvement:** The DI-ed version uses Redis caching, replacing the previous in-memory 5-minute cache implementation which was not ideal. This follows the established DI pattern in the codebase for loose coupling, better testability, and more robust caching across instances.

## Type of change

- [x] Refactor (non-breaking change that improves code quality)

## Mandatory Tasks (DO NOT REMOVE)

- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - no documentation changes needed.
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works.

## How should this be tested?

1. Verify feature flags functionality works as expected:
   - Feature flag list endpoint should return all features
   - Team feature check should work correctly
2. No environment variables needed beyond standard setup

## Checklist

- [x] My code follows the style guidelines of this project
- [x] I have checked if my changes generate no new warnings

## Human Review Checklist

- [ ] Verify `getFeaturesRepository()` returns a properly configured instance from the DI container
- [ ] Confirm the DI container properly injects the Prisma client
- [ ] Verify Redis caching is working as expected for feature flag data

---

**Link to Devin run:** https://app.devin.ai/sessions/2ff6e4551c8649e4b6178b31a2195327
**Requested by:** @eunjae-lee
2026-01-29 16:47:46 +01:00
emrysal 0e8dde843d chore: release v6.1.8 2026-01-29 15:01:13 +00:00
Benny JooGitHubbenny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
c7ee3984ef refactor: move feature-flags, calendars, and schedules components from packages/features to apps/web/modules (#27222)
* refactor: move feature-flags, calendars, and schedules components from packages/features to apps/web/modules

Co-Authored-By: benny@cal.com <sldisek783@gmail.com>

* fix

* fix

* fix

* fix: move DatePicker and DateOverrideInputDialog to apps/web/modules and update imports

Co-Authored-By: benny@cal.com <sldisek783@gmail.com>

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* rename

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* wip

* wip

* wip

* fix unit tests

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 16:41:44 +02:00
Eunjae LeeGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
18049bc1d6 refactor: update i18n keys to match effectiveReason values (#27381)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 14:16:12 +00:00
MorganGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
447a0289d6 fix: parse raw body Buffer in Vercel webhook controller (#27384)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 11:54:32 +00:00
Hariom BalharaGitHubunknown <>hariom@cal.com <hariombalhara@gmail.com>hariom@cal.com <hariombalhara@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2802310268 feat: Add infrastructure for no-show audit integration (#27187)
* feat: Add infrastructure for no-show audit integration

- Add Prisma migrations for SYSTEM source and NO_SHOW_UPDATED audit action
- Add NoShowUpdatedAuditActionService with array-based attendeesNoShow schema
- Update BookingAuditActionServiceRegistry to include NO_SHOW_UPDATED
- Update BookingAuditTaskConsumer and BookingAuditViewerService
- Add AttendeeRepository methods for no-show queries
- Update IAuditActionService interface with values array support
- Update locales with no-show audit translation keys

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

* fix: Add NO_SHOW_UPDATED to BookingAuditAction and SYSTEM to ActionSource types

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

* fix: Remove HOST_NO_SHOW_UPDATED and ATTENDEE_NO_SHOW_UPDATED from BookingAuditAction type to match Prisma schema

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

* fix: Update BookingAuditActionSchema to use NO_SHOW_UPDATED instead of HOST_NO_SHOW_UPDATED and ATTENDEE_NO_SHOW_UPDATED

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

* refactor: Remove deprecated no-show audit services and unify to NoShowUpdatedAuditActionService

- Delete HostNoShowUpdatedAuditActionService and AttendeeNoShowUpdatedAuditActionService
- Update BookingAuditProducerService.interface.ts to use queueNoShowUpdatedAudit
- Update BookingAuditTaskerProducerService.ts to use queueNoShowUpdatedAudit
- Update BookingEventHandlerService.ts to use onNoShowUpdated
- Add integration tests for NoShowUpdatedAuditActionService

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

* fix: Add data migration step for deprecated no-show enum values

Addresses Cubic AI review feedback (confidence 9/10): The migration now
includes an UPDATE statement to convert existing records using the
deprecated 'host_no_show_updated' or 'attendee_no_show_updated' enum
values to the new unified 'no_show_updated' value before the type cast.
This prevents migration failures if any existing data uses the old values.

Co-Authored-By: unknown <>

* fix: Use CASE expression in USING clause for enum migration

Fixes PostgreSQL error 'unsafe use of new value of enum type' by avoiding
the ADD VALUE statement and instead using a CASE expression in the ALTER
TABLE USING clause to convert deprecated enum values (host_no_show_updated,
attendee_no_show_updated) to the new unified value (no_show_updated) during
the type conversion.

Co-Authored-By: unknown <>

* fix: Replace hardcoded color with semantic text-success class

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

* fix: Remove color class completely from display fields

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 08:47:26 -03:00
Syed Ali ShahbazGitHubali@cal.com <alishahbaz7@gmail.com>unknown <>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2ec9e903ce feat: implement webhook tasker with async/sync fallback (#27378)
* feat: implement webhook tasker with async/sync fallback

This PR implements a webhook tasker with async/sync fallback architecture
to fix failing E2E tests. The solution follows the existing proration
tasker pattern and uses Dependency Injection with @evyweb/ioctopus.

Key changes:
- Create IWebhookTasker interface for webhook delivery
- Implement WebhookSyncTasker for immediate execution (E2E tests)
- Implement WebhookAsyncTasker for queued execution (production)
- Create main WebhookTasker class extending Tasker<IWebhookTasker>
- Add DI modules and tokens for all tasker components
- Update WebhookTaskerProducerService to use new WebhookTasker
- Add unit tests for sync and async taskers

The ENABLE_ASYNC_TASKER flag automatically selects the appropriate mode:
- Production: Uses WebhookAsyncTasker to queue tasks
- E2E Tests: Uses WebhookSyncTasker for immediate execution

This ensures webhooks are delivered immediately in E2E tests without
requiring the cron job that processes queued tasks.

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>

* fix: update WebhookTaskerProducerService tests for new interface

Update tests to use the new deps-based constructor and
mockWebhookTasker.deliverWebhook instead of mockTasker.create

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>

* fix: use moduleLoader pattern for WebhookProducerService in container

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>

* refactor: replace InternalTasker with Trigger.dev for webhook delivery

This commit refactors the WebhookTasker to use Trigger.dev instead of
InternalTasker, following the pattern established in BookingEmailAndSmsTasker
and PlatformOrganizationBillingTasker (PR #26803).

Changes:
- Replace WebhookAsyncTasker with WebhookTriggerTasker that uses trigger.dev
- Create trigger.dev task files (deliver-webhook.ts, config.ts, schema.ts)
- Update DI modules to use WebhookTriggerTasker
- Remove old InternalTasker-based implementation
- Update unit tests for new implementation

The WebhookSyncTasker continues to execute webhooks immediately for E2E tests
where ENABLE_ASYNC_TASKER is automatically false.

Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>

* fix: update comments to reflect Trigger.dev usage instead of InternalTasker

Co-Authored-By: unknown <>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 15:30:07 +04:00
Volnei MunhozandGitHub db7547fd6d Remove noProcessGlobal for atoms (#27382) 2026-01-29 11:25:01 +00:00
3c91703415 feat: add invoice banner + block additions to teams/orgs (#27327)
* feat: add invoice URL to proration and test seed scripts

- Add invoiceUrl field to MonthlyProration schema
- Update billing service to return hosted_invoice_url after finalizing
- Save invoice URL when creating proration invoices
- Add seed script for testing proration with real Stripe data
- Add cleanup script for test data removal

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add due invoice banner and invitation blocking for orgs

- Add DueInvoiceBanner component showing overdue prorations
- Add DueInvoiceService for checking blocking status and banner data
- Block invitations when proration invoices are 7+ days overdue
- Allow sub-team invites for existing org members (exception)
- Show banner to users with billing management permissions
- Link directly to Stripe invoice URL when available

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: set subscriptionId in team metadata in seed script

The seed script was not setting subscriptionId on the team metadata,
causing checkIfOrgNeedsUpgrade to treat the org as needing upgrade
and showing the "trialing" banner.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* push trigger test to script

* fix mocks

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:23:27 +00:00
Joe Au-YeungGitHubhariom@cal.com <hariombalhara@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Hariom Balhara
ca5d931165 fix: preserve UI config across iframe resets for element-click embeds (#27363)
* fix: preserve UI config across iframe resets for element-click embeds

For element-click embeds, ui() is called before the iframe exists, and
iframeReset() clears the queue when the modal is opened. This causes UI
config like hideEventTypeDetails, cssVarsPerTheme, and styles to be lost.

This fix stores UI config in a persistent property that survives iframe
resets and applies it when the iframe becomes ready.

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* test: add assertion to verify hideEventTypeDetails config is applied in element-click embed

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* Add mergeUiConfig function and related tests for UI configuration merging

- Introduced mergeUiConfig function to handle merging of UI configuration, specifically for cssVarsPerTheme at theme level.
- Added comprehensive tests for mergeUiConfig covering various scenarios including merging themes, handling missing properties, and preserving existing configuration values.
- Updated utils.test.ts to include tests for the new function and ensure correct behavior in different merging situations.

* Fixes

* Remove process import as it breaks embed.js

* Simplify

* fix name

* fix name

* fix: use forEach instead of for...of for URLSearchParams iteration

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2026-01-29 08:18:53 -03:00
Lauris SkraucisGitHubunknown <>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Ryukemeister
3b2e3351c4 docs: api v2 and examples app setup (#27290)
* docs: api v2 and examples app setup

* docs: api v2 and examples app setup

* fix: address Cubic AI review feedback

- Fix env file path typo in README.md (apps/api/v2.env -> apps/api/v2/.env)
- Write generated secrets to file instead of logging to console
- Add .generated-secrets to gitignore
- Update README-PLATFORM.md to reflect new secret generation behavior

Co-Authored-By: unknown <>

* chore: update locale

* chore: update docs

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Ryukemeister <sahalrajiv6900@gmail.com>
2026-01-29 11:18:23 +00:00
08a2b0bfb5 feat: add organization.passwordReset PBAC permission (#27377)
* feat: add organization.passwordReset PBAC permission

Allow org admins/owners to reset passwords for members of their
organization via a new PBAC permission. Previously this was only
available to system-level admins.

- Add PasswordReset to CustomAction enum and PERMISSION_REGISTRY
- Create migration to grant permission to admin_role (owner has wildcard)
- Add org-scoped tRPC endpoint using createOrgPbacProcedure
- Handler validates org membership, prevents self-targeting, and blocks
  resetting owner passwords
- Wire permission through MemberPermissions, getOrgMembersPageData, and
  the org members table UI dropdown

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use targeted select in org password reset to avoid over-fetching

Replace findById with findForPasswordReset repository method that only
selects email, name, and locale instead of the full userSelect which
includes sensitive fields like twoFactorSecret and backupCodes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test: add unit tests for sendPasswordReset handler

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:18:02 +00:00
sean-brydonGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1f8f134854 feat: enable PBAC feature flag globally via migration (#27376)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 11:00:55 +00:00
Rajiv SahalandGitHub 5427d28c9e fix: bad import (#27380) 2026-01-29 09:45:06 +00:00
sean-brydonGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
0d5560e0d1 fix: use WEBAPP_URL for team payment redirect instead of req.nextUrl.origin (#27233)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 09:30:14 +00:00
Eunjae LeeandGitHub ea15474edf fix: show bookings-v3 only in the settings but not in the banner (#27330)
## What does this PR do?

Adds a `displayLocations` property to the `OptInFeatureConfig` interface to control where opt-in features are displayed (settings page, banner, or both), and applies this filtering at the callers' side.

## How to test locally

```
update "Feature" set enabled = true where slug='bookings-v3';
```

Run it to globally enable the flag, and then go to the settings page to see the "Features" menu.

---

**Changes:**
- Added `OptInFeatureDisplayLocation` type with values `"settings"` | `"banner"`
- Added optional `displayLocations` property to `OptInFeatureConfig` interface
- Added helper functions:
  - `getFeatureDisplayLocations()` - returns display locations with default of `['settings']`
  - `shouldDisplayFeatureAt()` - checks if a feature should display at a specific location
  - `getOptInFeaturesForLocation()` - filters features by location
- Updated `getOptInFeaturesForScope()` to accept an optional `displayLocation` parameter for filtering
- Simplified `HAS_*_OPT_IN_FEATURES` constants to use `getOptInFeaturesForScope(scope, "settings").length > 0`
- Updated `FeatureOptInService.listFeaturesForUser()` to filter by 'settings' location
- Updated `FeatureOptInService.listFeaturesForTeam()` to filter by 'settings' location
- Updated `useFeatureOptInBanner` hook to check for 'banner' location before showing

**Default behavior:** If `displayLocations` is omitted, features default to `['settings']` only.

## Mandatory Tasks (DO NOT REMOVE)

- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - internal config change only.
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works.

## How should this be tested?

1. Verify the helper functions work as expected:
   - `getFeatureDisplayLocations({ slug: "test", ... })` should return `["settings"]` (default)
   - `getFeatureDisplayLocations({ slug: "test", displayLocations: ["banner"] })` should return `["banner"]`
   - `shouldDisplayFeatureAt(feature, "settings")` should return `true` for features without `displayLocations`
   - `getOptInFeaturesForScope("user", "banner")` should only return user-scoped features with `"banner"` in their `displayLocations`

2. Verify caller-side filtering:
   - `listFeaturesForUser()` and `listFeaturesForTeam()` should only return features with 'settings' in displayLocations
   - Banner hook should only show features with 'banner' in displayLocations
   - `HAS_*_OPT_IN_FEATURES` constants should only be true if there are features with 'settings' location

## Checklist

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

---

### Human Review Checklist
- [ ] Verify the default behavior (defaulting to `['settings']`) matches requirements
- [ ] Confirm the filtering logic is applied correctly in all callers (service methods, banner hook, constants)
- [ ] Verify the banner hook correctly prevents showing features without 'banner' in displayLocations
- [ ] Note: The test mock returns all features regardless of `displayLocation` parameter - the filtering logic in `getOptInFeaturesForScope` isn't directly tested. Consider if this is acceptable or if tests should be added.

**Link to Devin run:** https://app.devin.ai/sessions/a064ee43a56d458caf2892b55959f1ea
**Requested by:** @eunjae-lee
2026-01-29 10:17:50 +01:00
Hariom BalharaGitHubhariom@cal.com <hariombalhara@gmail.com>hariom@cal.com <hariombalhara@gmail.com>hariom@cal.com <hariombalhara@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
6acc84661d refactor: fix 413 Request Entity too large error when big image files are uploaded (#27285)
* feat: add image resizing endpoint for organization onboarding

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

* chore: add translation keys for image upload errors

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

* refactor: rename endpoint to resizeBase64Image with imageType enum and Zod validation

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

* refactor: use ImageUploader and BannerUploader components for organization brand onboarding

Replace server-side image resizing endpoint with client-side cropping using existing ImageUploader and BannerUploader components. This approach:
- Avoids sending large base64 payloads to the server (preventing 413 errors)
- Provides better UX with cropping functionality
- Aligns with team onboarding which already uses ImageUploader
- Removes unnecessary server-side code

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

* Revert formatting change

* fix: correct max file size from 10mb to 5mb in translations

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

* Add Remove bvutton too

* fix: correct banner dimension, indentation, and import order

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 08:55:13 +00:00
+4
MorganGitHubmorgan@cal.com <morgan@cal.com>morgan@cal.com <morgan@cal.com>morgan@cal.com <morgan@cal.com>lauris@cal.com <lauris.skraucis@gmail.com>morgan@cal.com <morgan@cal.com>lauris@cal.com <lauris.skraucis@gmail.com>lauris@cal.com <lauris.skraucis@gmail.com>lauris@cal.com <lauris.skraucis@gmail.com>lauris@cal.com <lauris.skraucis@gmail.com>lauris@cal.com <lauris.skraucis@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Lauris Skraucis
5b048dd868 fix: exclude third-party video apps from areCalendarEventsEnabled setting (#27230)
* fix: exclude third-party video apps from areCalendarEventsEnabled setting

When areCalendarEventsEnabled is false, video meeting creation for third-party
video apps (like Daily.co) was being skipped, causing the meetingUrl field in
webhook payloads to contain the location identifier (integrations:daily) instead
of the actual video meeting URL.

This fix adds a skipCalendarEvent option to EventManager.create() that:
- Skips calendar event creation when true
- Skips CRM event creation when true (CRM events are tied to calendar events)
- Still creates video meetings for third-party video apps

The calling code in handleConfirmation.ts and RegularBookingService.ts now uses
this option when areCalendarEventsEnabled is false, ensuring video meetings are
still created while respecting the platform customer's preference to manage
their own calendar events.

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* test: update E2E tests to verify skipCalendarEvent option is passed when areCalendarEventsEnabled is false

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* refactor: address PR review feedback - remove comments and update E2E tests to spy on createAllCalendarEvents

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* test: add spy for createAllCRMEvents in e2e tests when areCalendarEventsEnabled is false

Co-Authored-By: lauris@cal.com <lauris.skraucis@gmail.com>

* test: add missing spy for createAllCRMEvents in beforeEach hook

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* fix: use videoCallUrl from metadata for webhook payload location

Co-Authored-By: lauris@cal.com <lauris.skraucis@gmail.com>

* fix: simplify webhook location to use metadata?.videoCallUrl || evt.location

Co-Authored-By: lauris@cal.com <lauris.skraucis@gmail.com>

* docs: add description about video call link limitations when calendar events disabled

Co-Authored-By: lauris@cal.com <lauris.skraucis@gmail.com>

* i18n: add translation key for calendar events disabled video limitation

Co-Authored-By: lauris@cal.com <lauris.skraucis@gmail.com>

* fix: update translation text to accurately reflect video app behavior

Co-Authored-By: lauris@cal.com <lauris.skraucis@gmail.com>

* Update common.json

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Lauris Skraucis <lauris.skraucis@gmail.com>
2026-01-29 10:23:52 +02:00
MorganGitHubmorgan@cal.com <morgan@cal.com>morgan@cal.com <morgan@cal.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
b02470e780 feat: add webhook endpoint for Vercel deployment promoted event to promote trigger.dev (#27340)
* feat: add webhook endpoint for Vercel deployment promoted event to promote trigger.dev

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* refactor: rename TRIGGER_API_KEY to TRIGGER_SECRET_KEY

Co-Authored-By: morgan@cal.com <morgan@cal.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 16:24:42 +09:00
Hariom BalharaandGitHub c536445eec docs: clarify bookerReopened and bookerReloaded are for prerendered modals (#27348)
## What does this PR do?

Updates the embed lifecycle documentation to clarify that `bookerReopened` and `bookerReloaded` events are only applicable for prerendered modals that are now visible.

## Mandatory Tasks (DO NOT REMOVE)

- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - this PR is itself a documentation update.
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works. N/A - documentation only change.

## How should this be tested?

This is a documentation-only change. Review the accuracy of the added "Applicability" notes for both events.

## Checklist

- [x] I have read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- [x] My code follows the style guidelines of this project
- [x] I have checked if my changes generate no new warnings

---

### Reviewer Checklist
- [ ] Verify that the documentation accurately reflects when `bookerReopened` and `bookerReloaded` events fire (only for prerendered modals)

---

> [!NOTE]
> **Link to Devin run**: https://app.devin.ai/sessions/35a0c5d4d5fc4feb9a5af2d8d340b9c5
> **Requested by**: @hariombalhara
2026-01-29 10:13:58 +05:30
MorganGitHubmorgan@cal.com <morgan@cal.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
09f33a840f chore: trigger.version.ts to set trigger tasks versions in prod (#27333)
* chore: trigger.version.ts instead of .env.production

* chore: trigger.version.ts instead of .env.production

* chore: restore dotenv/config import for local development

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* fixup! chore: trigger.version.ts instead of .env.production

* fixup! fixup! chore: trigger.version.ts instead of .env.production

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-28 19:36:36 -03:00
Volnei MunhozGitHubVolnei MunhozDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
16cb9a3126 refactor: join teams with feature enabled directly in findNextSubscriptionBatch query (#27364)
* refactor: join teams with feature enabled directly in findNextSubscriptionBatch query

- Changed findNextSubscriptionBatch to accept featureId instead of teamIds
- Join TeamFeatures table directly in the query instead of separate queries
- Updated CalendarSubscriptionService.checkForNewSubscriptions to pass featureId
- Removed separate getTeamsWithFeatureEnabled call
- Updated tests to reflect the new query structure

Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>

* refactor: change featureId to featureIds array for flexibility

- Changed findNextSubscriptionBatch to accept featureIds array instead of single featureId
- Updated Prisma query to use 'in' operator for multiple feature IDs
- Updated CalendarSubscriptionService to pass array with single feature
- Updated all tests to use featureIds array

Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-28 17:52:00 -03:00
Alex van AndelGitHubalex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
844380e265 fix: reduce forcedSlowMode rate limit from 30s to 1s (#27359)
* fix: reduce forcedSlowMode rate limit from 30s to 1s

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* revert: keep rateLimit.ts unchanged, only update API v2 controllers

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-28 17:39:28 -03:00
Joe Au-YeungGitHubClaude Opus 4.5joe@cal.com <j.auyeung419@gmail.com>joe@cal.com <j.auyeung419@gmail.com>joe@cal.com <j.auyeung419@gmail.com>joe@cal.com <j.auyeung419@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Volnei Munhoz
034fbd63f1 feat: Add CrmRoutingTraceService and SalesforceRoutingTraceService (#27318)
* Add DB schema

* Init zod schema

* Init RoutingTrace and PendingRoutingTrace repository interfaces

* Create PrismaPendingRoutingTraceRepository

* Init RoutingTraceService

* Create RoutingTraceService container

* User routing trace service in routing

* Create RoutingTraceRepository and PrismaRoutingTraceRepoistory

* Add findByFormResponseId and findByQueuedFormResponseId to PendingRoutingTraceRepository

* Update DI containers

* RoutingTraceService create process booking method

* Use pending routing trace rather than URL params

* Fix schema

* Fix writing assignment reason for routed booking

* Remove  from  service

* Refactor RoutingTraceService to not rely on async local storage

* Pass RoutingTraceService through routing call

* Add attribute-logic-evaluated to routing trace step

* Add routing trace to trpc endpoint

* Add CRM routing trace step

* Fix extracting routing trace to assignment reason

* Add back CRM params to prevent refetching

* test: Add unit tests for RoutingTraceService and repositories

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* test: Add missing mock for RoutingTraceService in getRoutedUrl tests

Also fix pre-existing lint issues in the test file:
- Add explicit types to mockForm and mockSerializableForm variables
- Add explicit type to url parameter in mockContext
- Replace 'as any' with 'as unknown as InstanceType<typeof UserRepository>'

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* Link pending form submission to routing trace

* Clean up

* Add lookup field assignment reasons

* Rename to PendingRoutingTrace

* Add migration file

* fix: Update RoutingTraceService tests to use assignmentReasonRepository mock

- Add getStepsCount() method back to RoutingTraceService
- Add queuedFormResponseId support to processForBooking method
- Update tests to use mockAssignmentReasonRepository instead of prisma mock
- Remove test for missing routingTraceRepository (all deps now required)

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: Remove PII (organizer email) from log payload in RoutingTraceService

Addresses Cubic AI review feedback with confidence 9/10.
Logging PII violates sensitive information logging rules.

Co-Authored-By: unknown <>

* Write field values at the time of routing

* Write attributes used to route

* feat: add CRM routing trace service

Add CrmRoutingTraceService as a reusable wrapper around RoutingTraceService
for CRM-specific tracing. Also adds CrmRoutingTraceServiceInterface type
to support passing trace services through the CRM call chain.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add Salesforce routing trace infrastructure

Add SalesforceRoutingTrace static class with 19 trace methods covering:
- Account resolution (SOQL path): searching by website, contact domain
- Lookup field queries
- Owner lookups (contact, lead, account)
- Validation and skip scenarios
- GraphQL three-tier resolution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: wire CRM trace service through call chain

Pass crmTrace parameter through the CRM call chain:
- routerGetCrmContactOwnerEmail creates CrmRoutingTraceService
- Passes to app booking form handlers and CRM round robin skip
- CrmManager.getContacts accepts and forwards crmTrace
- All handlers accept optional crmTrace parameter

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add trace instrumentation to Salesforce CRM service

Instrument Salesforce CRM methods with routing trace steps:
- getContacts: trace owner lookups for contact/lead/account
- getAccountIdBasedOnEmailDomainOfContacts: trace website and domain searches
- findUserEmailFromLookupField: trace lookup field queries
- GetAccountRecordsForRRSkip (GraphQL): trace three-tier resolution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: rename SalesforceRoutingTrace to SalesforceRoutingTraceService

Consistent naming with CrmRoutingTraceService.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test: add unit tests for CrmRoutingTraceService and SalesforceRoutingTraceService

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* refactor: use AsyncLocalStorage for CRM routing trace

Replace explicit crmTrace parameter passing with AsyncLocalStorage:

- Add AsyncLocalStorage to RoutingTraceService with getCurrent() and runAsync()
- Update SalesforceRoutingTraceService to auto-resolve trace from AsyncLocalStorage
- Remove CrmRoutingTraceService wrapper (no longer needed)
- Remove crmTrace parameter from all CRM method signatures
- Wrap CRM operations in routingTraceService.runAsync() context

This is cleaner than threading crmTrace through 5+ function layers.
The trace context is available within the withReporting wrapper.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Use async local storage for `CrmRoutingTraceService`

* fix: correct template literal syntax in RoutingTraceService

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: use narrowed eventTypeId variable in nested async function

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: update SalesforceRoutingTraceService tests to use AsyncLocalStorage API

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* refactor: rename crmTrace to crmRoutingTraceService for consistency

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Volnei Munhoz <volnei@cal.com>
2026-01-28 17:28:35 -03:00
Joe Au-YeungGitHubClaude Opus 4.5joe@cal.com <j.auyeung419@gmail.com>joe@cal.com <j.auyeung419@gmail.com>joe@cal.com <j.auyeung419@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
f536100224 feat: Add RoutingFormTrace (#27316)
* Add DB schema

* Init zod schema

* Init RoutingTrace and PendingRoutingTrace repository interfaces

* Create PrismaPendingRoutingTraceRepository

* Init RoutingTraceService

* Create RoutingTraceService container

* User routing trace service in routing

* Create RoutingTraceRepository and PrismaRoutingTraceRepoistory

* Add findByFormResponseId and findByQueuedFormResponseId to PendingRoutingTraceRepository

* Update DI containers

* RoutingTraceService create process booking method

* Use pending routing trace rather than URL params

* Fix schema

* Fix writing assignment reason for routed booking

* Remove  from  service

* Refactor RoutingTraceService to not rely on async local storage

* Pass RoutingTraceService through routing call

* Add attribute-logic-evaluated to routing trace step

* Add routing trace to trpc endpoint

* Add CRM routing trace step

* Fix extracting routing trace to assignment reason

* Add back CRM params to prevent refetching

* test: Add unit tests for RoutingTraceService and repositories

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* test: Add missing mock for RoutingTraceService in getRoutedUrl tests

Also fix pre-existing lint issues in the test file:
- Add explicit types to mockForm and mockSerializableForm variables
- Add explicit type to url parameter in mockContext
- Replace 'as any' with 'as unknown as InstanceType<typeof UserRepository>'

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* Link pending form submission to routing trace

* Clean up

* Add lookup field assignment reasons

* Rename to PendingRoutingTrace

* Add migration file

* fix: Update RoutingTraceService tests to use assignmentReasonRepository mock

- Add getStepsCount() method back to RoutingTraceService
- Add queuedFormResponseId support to processForBooking method
- Update tests to use mockAssignmentReasonRepository instead of prisma mock
- Remove test for missing routingTraceRepository (all deps now required)

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: Remove PII (organizer email) from log payload in RoutingTraceService

Addresses Cubic AI review feedback with confidence 9/10.
Logging PII violates sensitive information logging rules.

Co-Authored-By: unknown <>

* Write field values at the time of routing

* Write attributes used to route

* fix: Add CHECK constraint to ensure at least one response ID is set in routing trace tables

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: Address PR review comments for routing trace feature

- Add checkedFallback to routing trace step data (Comment 11)
- Extract hardcoded domain/step strings to constants (Comment 13)
- Use @default(now()) for createdAt in PendingRoutingTrace and RoutingTrace (Comment 15)
- Add DEFAULT CURRENT_TIMESTAMP to migration for createdAt fields

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: Use UTC-safe timezone expression for createdAt defaults in routing trace tables

Addresses Cubic AI review feedback (confidence 9/10) to prevent timezone
issues by using dbgenerated("timezone('UTC', now())") instead of bare now()
for the createdAt fields in PendingRoutingTrace and RoutingTrace models.

Co-Authored-By: unknown <>

* fix: Align migration SQL with Prisma's expected timezone syntax

Use 'UTC'::text cast in timezone() function to match Prisma's generated SQL.

Co-Authored-By: unknown <>

* fix: Revert migration SQL to match Prisma schema timezone syntax

Remove ::text cast from timezone() function to match what Prisma generates
from the schema definition.

Co-Authored-By: unknown <>

* fix: Use explicit ::text cast in timezone() for PostgreSQL compatibility

PostgreSQL normalizes timezone('UTC', now()) to timezone('UTC'::text, now())
internally. Update both schema and migration to use the explicit cast to
ensure they match and pass the migration check.

Co-Authored-By: unknown <>

* feat: Add RoutingFormTraceService domain class for type-safe routing traces

- Create RoutingFormTraceService class with routeMatched, fallbackRouteUsed,
  attributeLogicEvaluated, and attributeFallbackUsed methods
- Add ROUTING_FORM_STEPS constants
- Add unit tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Integrate RoutingFormTraceService for routing form tracing

- Add routingFormTraceService parameter to findMatchingRoute
- Record route_matched or fallback_route_used step when route is selected
- Use "Default Route" as name for form-level fallback routes
- Refactor findTeamMembersMatchingAttributeLogic to use RoutingFormTraceService
- Update handleResponse to accept and pass routingFormTraceService
- Create RoutingFormTraceService in getRoutedUrl and pass through the flow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test: Add test coverage for RoutingFormTraceService integration

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* feat: Integrate RoutingFormTraceService for routing form tracing

- Add routingFormTraceService parameter to findMatchingRoute
- Record route_matched or fallback_route_used step when route is selected
- Use "Default Route" as name for form-level fallback routes
- Refactor findTeamMembersMatchingAttributeLogic to use RoutingFormTraceService
- Update handleResponse to accept and pass routingFormTraceService
- Create RoutingFormTraceService in getRoutedUrl and pass through the flow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: Restore schema and migration from main branch

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: Use correct parameter name routingFormTraceService in tests

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: Use 'default_route' instead of 'Default Route' for fallback route name

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 17:15:22 -03:00
Alex van AndelGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
906ba99d3c fix: add composite index on SecondaryEmail for email verification queries (#27357)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-28 14:53:31 -03:00
Joe Au-YeungGitHubunknown <>joe@cal.com <j.auyeung419@gmail.com>joe@cal.com <j.auyeung419@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Pedro Castro
620445d85f feat: Use RoutingTraceService to write assignment reasons (#27225)
* Add DB schema

* Init zod schema

* Init RoutingTrace and PendingRoutingTrace repository interfaces

* Create PrismaPendingRoutingTraceRepository

* Init RoutingTraceService

* Create RoutingTraceService container

* User routing trace service in routing

* Create RoutingTraceRepository and PrismaRoutingTraceRepoistory

* Add findByFormResponseId and findByQueuedFormResponseId to PendingRoutingTraceRepository

* Update DI containers

* RoutingTraceService create process booking method

* Use pending routing trace rather than URL params

* Fix schema

* Fix writing assignment reason for routed booking

* Remove  from  service

* Refactor RoutingTraceService to not rely on async local storage

* Pass RoutingTraceService through routing call

* Add attribute-logic-evaluated to routing trace step

* Add routing trace to trpc endpoint

* Add CRM routing trace step

* Fix extracting routing trace to assignment reason

* Add back CRM params to prevent refetching

* test: Add unit tests for RoutingTraceService and repositories

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* test: Add missing mock for RoutingTraceService in getRoutedUrl tests

Also fix pre-existing lint issues in the test file:
- Add explicit types to mockForm and mockSerializableForm variables
- Add explicit type to url parameter in mockContext
- Replace 'as any' with 'as unknown as InstanceType<typeof UserRepository>'

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* Link pending form submission to routing trace

* Clean up

* Add lookup field assignment reasons

* Rename to PendingRoutingTrace

* Add migration file

* fix: Update RoutingTraceService tests to use assignmentReasonRepository mock

- Add getStepsCount() method back to RoutingTraceService
- Add queuedFormResponseId support to processForBooking method
- Update tests to use mockAssignmentReasonRepository instead of prisma mock
- Remove test for missing routingTraceRepository (all deps now required)

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: Remove PII (organizer email) from log payload in RoutingTraceService

Addresses Cubic AI review feedback with confidence 9/10.
Logging PII violates sensitive information logging rules.

Co-Authored-By: unknown <>

* Write field values at the time of routing

* Write attributes used to route

* fix: Add CHECK constraint to ensure at least one response ID is set in routing trace tables

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: Address PR review comments for routing trace feature

- Add checkedFallback to routing trace step data (Comment 11)
- Extract hardcoded domain/step strings to constants (Comment 13)
- Use @default(now()) for createdAt in PendingRoutingTrace and RoutingTrace (Comment 15)
- Add DEFAULT CURRENT_TIMESTAMP to migration for createdAt fields

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: Use UTC-safe timezone expression for createdAt defaults in routing trace tables

Addresses Cubic AI review feedback (confidence 9/10) to prevent timezone
issues by using dbgenerated("timezone('UTC', now())") instead of bare now()
for the createdAt fields in PendingRoutingTrace and RoutingTrace models.

Co-Authored-By: unknown <>

* fix: Align migration SQL with Prisma's expected timezone syntax

Use 'UTC'::text cast in timezone() function to match Prisma's generated SQL.

Co-Authored-By: unknown <>

* fix: Revert migration SQL to match Prisma schema timezone syntax

Remove ::text cast from timezone() function to match what Prisma generates
from the schema definition.

Co-Authored-By: unknown <>

* fix: Use explicit ::text cast in timezone() for PostgreSQL compatibility

PostgreSQL normalizes timezone('UTC', now()) to timezone('UTC'::text, now())
internally. Update both schema and migration to use the explicit cast to
ensure they match and pass the migration check.

Co-Authored-By: unknown <>

* fix: Use CURRENT_TIMESTAMP for createdAt defaults (standard Cal.com pattern)

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

* fix: Use @default(now()) for createdAt in routing trace tables to match migration

Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Pedro Castro <pedro@cal.com>
2026-01-28 12:45:15 -05:00
+3
Alex van AndelGitHubalex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
c9bd18e866 chore: Disables syncing of calendarList on overlay calendar fetch (#27020)
* chore: Disables syncing of calendarList on overlay calendar fetch

* Unwrap ToggledConnectedCalendars

* Pick the right type for connectedCalendars

* further type amends

* Type fixes, tons of em

* Some further fixups consistent with what was before

* fix: resolve type incompatibility in getConnectedDestinationCalendars return type

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* fix: update DestinationCalendarProps to accept tRPC handler return type

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* fix: use generic type for DestinationCalendarProps to accept tRPC enriched types

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* fix: simplify DestinationCalendarProps type for better compatibility

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* fix: export ConnectedCalendar type for consistent type inference

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* fix: use permissive type for connectedCalendars to accept tRPC enriched types

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* fix: export ConnectedCalendar and ConnectedDestinationCalendars types from platform-libraries

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* fix: update ConnectedCalendar type to use boolean | null for primary field

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* Update ConnectedCalendarItem

* Undo some of Devins fixes, more fixes

* Fixup the destination calendar return type, historically not null

* Change init to undefined to deal with null

* Approach to connect selected calendars with the right credential

* This return type is used way too much everywhere, not refactoring

* Add the selectedCalendars to the type

* Actually fix overlay calendar

* set calendarsToLoad param as required

* Apply suggestion from @cubic-dev-ai[bot]

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

* Add new translation for 'Calendar Settings'

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-28 14:20:19 -03:00
emrysal c62f333337 chore: release v6.1.7 2026-01-28 16:20:47 +00:00
Eunjae LeeandGitHub 91a62a14ee fix: disable prefetch in /bookings (#27351) 2026-01-28 13:05:20 -03:00
Alex van AndelGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
718aef579c fix: optimize bookings/get query to use subqueries instead of materializing 400+ parameters (#27319)
PERFORMANCE: The bookings/get endpoint was taking 24s due to materializing 400+ email
addresses as individual parameters in WHERE IN clauses. This caused massive UNION
queries that overwhelmed the database.

Changes:
- Replace IN clauses with Kysely subqueries for queries 4, 5, 6, and 7
- Query 4 & 5: Use subquery to get emails from users via Membership table
- Query 6: Use subquery to get event type IDs from EventType table
- Query 7: Use subquery to get user IDs from Membership table
- Only fetch user IDs when needed for userIds filter validation
- Add new getUserIdsFromTeamIds function (lighter version without emails)

Before: WHERE email IN ($1, $2, ..., $400+) - passes 400+ parameters
After: WHERE email IN (SELECT email FROM users JOIN Membership...) - passes only team IDs

This reduces parameter count from 400+ to typically 1-10 team IDs, letting the
database optimize the query execution plan.

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-28 12:21:49 -03:00
cba329d6d2 feat: removes account dropdown from oauth consent screen (#27191)
* remove acount dropdown on consent screen

* change button back to go back

* add missing translations

* fix avatar

* code clean up

* add translation

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2026-01-28 15:34:59 +01:00
sean-brydonandGitHub ade823f135 sort team Ids (#27349) 2026-01-28 14:33:58 +00:00
Eunjae LeeGitHubeunjae@cal.com <hey@eunjae.dev>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ddceabe5d4 fix: use FeatureOptInService for bookings-v3 check (#27183)
* fix: use FeatureOptInService for bookings-v3 check

* refactor: simplify FeatureOptInService API and fix bookings page

- Add resolveFeatureStates method that takes only userId and featureIds
- Update listFeaturesForUser to take only userId parameter
- Remove getUserOrgAndTeamIds from _router.ts (now internal to service)
- Fix bookings page to use new resolveFeatureStates method
- Parallelize getUserFeaturesStatus and resolveFeatureStates calls

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* check session?.user?.id first

* remove comment

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-28 14:28:36 +00:00
Lauris SkraucisandGitHub 987e727464 docs: document business rules in AGENTS.md (#27347) 2026-01-28 14:13:09 +00:00
Volnei MunhozandGitHub 61dd7eb64c chore: Upgrade Next & React (#27332)
* upgrade next and react versions

* upgrade next and react versions

* upgrade next and react versions
2026-01-28 10:47:04 -03:00
Benny JooandGitHub 1a31f9136b refactor: Move integration attribute async components to /web (#27341)
* calendar switch

* wip

* wip

* wip

* fix
2026-01-28 10:44:18 -03:00
8e5a5629a4 fix: fixes oauth flow with user sign up (#27307)
* fix oauth flow with sign up

* extract key as const variable

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2026-01-28 13:35:27 +00:00
Amit SharmaandGitHub 5bea18fd5e feat: hubspot rr skip (#27310)
* feat: hubspot show owner availability for round robin

* fix: translations

* fix: use app name variable for text
2026-01-28 16:57:02 +05:30
ff6fa64b63 fix: UI improvements for team-wide limits (#27133)
* add badge

* allow undefined

* fix ci type errors

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2026-01-28 11:13:07 +01:00
ea76df47d2 feat: add invoice URL to proration and test seed scripts (#27297)
* feat: add invoice URL to proration and test seed scripts

- Add invoiceUrl field to MonthlyProration schema
- Update billing service to return hosted_invoice_url after finalizing
- Save invoice URL when creating proration invoices
- Add seed script for testing proration with real Stripe data
- Add cleanup script for test data removal

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* add invoice url

* add invoice URL to tests

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 09:42:57 +00:00
Rajiv SahalandGitHub 8319666d76 fix: replace new Date with dayjs (#27306) 2026-01-28 10:46:17 +05:30
emrysal 843314c397 chore: release v6.1.6 2026-01-28 02:40:17 +00:00
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
3d0663f4af feat: add composite indexes for booking queries at scale (#27315)
* feat: add composite indexes for booking queries at scale

Add new composite indexes to optimize common query patterns for the Booking
and Attendee tables. These indexes are designed to support the system at scale
(14M+ bookings, 50K daily inserts) while minimizing write overhead.

New indexes on Booking table:
- (userId, endTime): Optimizes /bookings/upcoming queries
- (userId, status, startTime): Optimizes busy times and filtered queries
- (eventTypeId, status): Optimizes round-robin and team booking queries
- (userId, createdAt): Optimizes API queries with createdAt sorting

New index on Attendee table:
- (bookingId, email): Optimizes JOIN queries filtering by attendee email

These indexes target the most common query patterns identified in:
- get.handler.ts (bookings list endpoints)
- BookingRepository.ts (busy times, round-robin)
- API v1 bookings endpoint

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* feat: add migration file for booking composite indexes

Add SQL migration to create the new composite indexes:
- Attendee(bookingId, email)
- Booking(userId, endTime)
- Booking(userId, status, startTime)
- Booking(eventTypeId, status)
- Booking(userId, createdAt)

Also clean up comments in schema.prisma to be more generic.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix: swap Attendee index column order to (email, bookingId)

Per Cubic AI review feedback - place email first to match the filter
column order in queries that filter by email.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-28 02:01:29 +00:00
Alex van AndelGitHubalex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
c45be81af5 refactor: lazy load KBar data fetching hooks only when opened (#27314)
* refactor: lazy load KBar data fetching hooks only when opened

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

* refactor: move KBar data fetching into RenderResults for proper lazy loading

Co-Authored-By: alex@cal.com <me@alexvanandel.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-27 21:45:44 -03:00
Alex van Andel 4228f576b1 Revert "fix: cancel download fetch when progress toast is closed (#27151)"
This reverts commit fd476bf7f7.
2026-01-27 17:37:31 -03:00
MorganGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
23067cd8af fix: await unawaited calendar.events.patch call in updateEvent (#27313)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-27 20:29:35 +00:00
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
21500c7047 fix: remove _count children query from EventType and Workflow repositories (#27309)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-27 15:23:26 -03:00
Eunjae LeeGitHubunknown <>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
fd476bf7f7 fix: cancel download fetch when progress toast is closed (#27152)
* fix: cancel download fetch when progress toast is closed

- Create new progress-toast utility using @coss/ui toastManager
- Add ToastProvider to app providers
- Update download components to use AbortController for cancellation
- When cancel button is clicked, abort signal stops the fetch loop

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: track active toasts with Set instead of accessing toastManager.toasts

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* feat: add AnchoredToastProvider to app providers

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: extract common CSV download logic into useCsvDownload hook

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: improve progress toast with i18n support and Progress component

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: replace useCsvDownload hook with DownloadButton component

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: rename DownloadButton to CsvDownloadButton

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* clean up i18n

* fix: properly throw AbortError when download is cancelled

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* Revert "fix: properly throw AbortError when download is cancelled"

This reverts commit 3c64b848140271e4dcd2e45dba5302eef9ca562c.

* fix abort controller

* fix layout shift

* better handle error

* fix: address Cubic AI review feedback

- Fix typo 'copmlete' -> 'complete' in download_progress i18n string
- Treat null batch as failure during CSV download to prevent partial exports

Co-Authored-By: unknown <>

* remove redundant try - catch

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-27 16:46:37 +00:00