* fix: add guest limits and rate limiting to booking-guests endpoint
- Add ArrayMaxSize(10) validation to limit guests per request to 10
- Add aggressive rate limiting (5 requests/minute) via @Throttle decorator
- Add total guest limit check (max 30 guests per booking) to prevent abuse
- Update API documentation to reflect new limits
This prevents scammers from using the endpoint to send spam emails
to hundreds of guests through our system.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* docs: update openapi.json with guest limits and rate limiting info
Co-Authored-By: morgan@cal.com <morgan@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-02-02 11:49:25 +02:00
Joe Au-YeungGitHubjoe@cal.com <j.auyeung419@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Claude Opus 4.5
* feat(salesforce): add field rules for round robin skip
- Add rrSkipFieldRules schema to appDataSchema in zod.ts
- Implement applyFieldRules method in CrmService.ts for post-query filtering
- Integrate field rules into getContacts method when forRoundRobinSkip=true
- Add UI component for configuring field rules in EventTypeAppCardInterface
- Add translations for new UI strings
- Add comprehensive tests for field rules functionality
Field rules allow users to specify conditions based on Salesforce record fields
with 'ignore' or 'must_include' actions. Rules are evaluated with AND logic
and gracefully handle missing fields by skipping those rules.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add children prop to Section.SubSectionHeader for field rules
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat(salesforce): add edit button for field rules
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat(salesforce): apply field rules to GraphQL results
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat(salesforce): add Redis caching for field validation
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix(salesforce): remove Redis caching to fix ERR_INVALID_THIS error
- Removed Redis caching for field validation that was causing ERR_INVALID_THIS errors
- Simplified field rules filtering to try query directly and skip filtering if it fails
- Restored ensureFieldsExistOnObject method for other uses (write to record)
- Field rules now gracefully handle invalid fields by skipping filtering
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* chore: reformat getAttributes.ts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(salesforce): dynamically build GraphQL query for field rules with multi-edge iteration
- Add buildDynamicAccountQuery to inject field rule fields into GraphQL query
- Add passesFieldRules to evaluate ignore/must_include rules against UIAPI nodes
- Validate field rules via getObjectFieldNames (in-memory + Redis cache) before branching
- Remove applyFieldRulesToGraphQLRecords (used jsforce conn in GraphQL path)
- Iterate all edges in Tiers 1 and 2 instead of only the first result
- Rank Tier 3 accounts by contact count and fallback to next on field rule failure
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(salesforce): add field rule routing trace steps
Add trace calls alongside field rule info logs for routing visibility:
- fieldRulesValidated: records validation result in CrmService
- fieldRuleFilteredRecord: records when account is filtered at each tier
- fieldRuleEvaluated: records individual rule evaluation details
- allRecordsFilteredByFieldRules: records when SOQL records are all filtered
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(salesforce): remove duplicate field validation and fix disabled Select options
applyFieldRules now receives pre-validated rules from the early
validation block instead of re-validating internally. Also adds
the missing options prop to the disabled Select in the field rules UI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(salesforce): include failed rule details in field rule trace steps
Rename passesFieldRules to getFailingFieldRule so the caller receives
the specific rule that caused filtering. The fieldRuleFilteredRecord
trace step now includes failedRule with field, value, and action.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test(salesforce): add GraphQL path tests for field rules
Cover field rule filtering across all three GraphQL resolution tiers
(contact, account, related contacts) with ignore and must_include
actions, multi-edge fallback, case-insensitivity, and dynamic query
selection.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Abstract new field rules settings
* Reduce extra SOQL call
* fix(salesforce): fix type errors in CrmService and GraphQL client
- Add missing import for getRedisService from @calcom/features/di/containers/Redis
- Fix ensureFieldsExistOnObject to properly return Field[] instead of incomplete function
- Use Array.from() instead of spread operator for Set and Map iterators to fix downlevelIteration errors
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-02-01 23:03:19 -05:00
Benny JooGitHubunknown <>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: move Booker hooks from packages/features to apps/web/modules
Migrate the following Booker hooks:
- useOverlayCalendar
- useSkipConfirmStep
- useInitializeWeekStart
- useIsQuickAvailabilityCheckFeatureEnabled
- useDecoyBooking
These hooks are only imported by apps/web files, making them safe to move
without creating circular dependencies.
Part of the tRPC-driven UI migration from packages/features to apps/web/modules.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: revert useIsQuickAvailabilityCheckFeatureEnabled move and fix import paths
- Reverted useIsQuickAvailabilityCheckFeatureEnabled.ts back to packages/features since it's imported by useSlots.ts in packages/features (would create circular dependency)
- Fixed import paths in useOverlayCalendar.ts to use @calcom/features paths
- Fixed import paths in useSkipConfirmStep.ts to use @calcom/features paths
- Updated Booker.tsx to import useIsQuickAvailabilityCheckFeatureEnabled from original location
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: use @calcom/web alias for hook imports to fix vitest resolution
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor
* migrate more hooks
* fix
* mv types
* fix
* fix
* fix
* fix
* revert: remove formatting-only changes to make PR easier to review
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* fix
* fix
* revert: restore original import ordering in moved hooks
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix imports
* fix
* fix
* wip
* wip
* wip
* wip
* wip
* wip
* fix: add isBrowser guard to useSlotsViewOnSmallScreen hook
Address Cubic AI review feedback (confidence 9/10) by adding the isBrowser
guard to the useSlotsViewOnSmallScreen hook to follow the file's client-only
contract and avoid executing during SSR/prerendering.
Co-Authored-By: unknown <>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-31 07:33:33 -03:00
sean-brydonGitHubunknown <>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: TOUTOC in handleSeats
* fix type check
* refactor: replace Prisma include with select in integration tests
Address Cubic AI review feedback (confidence 9/10) to use select instead
of include in Prisma queries to limit returned fields and avoid pulling
full related records.
Co-Authored-By: unknown <>
* fix seat count
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-30 13:38:31 +00:00
devin-ai-integration[bot]GitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>ali@cal.com <ali@cal.com>
The previous implementation relied on the hosts array returned from
findTeamEventTypes, which is limited to 5 hosts for display purposes.
This caused the 'Assigned' badge to not show for users who were hosts
but not in the first 5 returned by the query.
This fix queries the Host table directly with a single batch query to
get all event type IDs where the current user is a host, ensuring the
badge shows correctly regardless of how many hosts an event type has.
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ali@cal.com <ali@cal.com>
Adds encrypted credential storage using a new keyring system:
- New `encryptedKey` column with AES-256-GCM encryption
- Decryption in getCalendarsEvents with fallback to legacy `key`
- buildCredentialCreateData service for credential creation
- Phase 1: Google Calendar only, other integrations follow
2026-01-30 09:15:13 -03:00
Benny JooGitHubbenny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: allow wildcard prefix in normalizeDomain function
The normalizeDomain function now accepts domains with *. prefix
(e.g., *.cal.com) for wildcard domain matching in the watchlist.
The domain part after *. is validated using the existing regex.
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: allow wildcard domains in validation checks
Update WatchlistOperationsService and CreateBlocklistEntryModal to
accept wildcard domain prefixes (*.) in domain validation. This ensures
wildcard domains like *.cal.com can be added through both the API and UI.
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-29 21:56:55 -03:00
Alex van AndelGitHubalex@cal.com <me@alexvanandel.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add wildcard domain matching to watchlist
When a domain is blocked in the watchlist (e.g., cal.com), all subdomains
are now also blocked (e.g., app.cal.com, sub.app.cal.com).
Changes:
- Add getParentDomains() utility to extract all parent domains
- Update GlobalBlockingService.isBlocked() and areBlocked() for wildcard matching
- Update OrganizationBlockingService.isBlocked() and areBlocked() for wildcard matching
- Add comprehensive tests for wildcard domain matching
- More specific subdomain matches take precedence over parent domain matches
- Email matches still take precedence over domain matches
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* feat: make wildcard domain matching configurable
- *.cal.com blocks all subdomains (app.cal.com, sub.app.cal.com, etc.)
- cal.com only blocks exact matches (not subdomains)
- Updated getWildcardPatternsForDomain to generate wildcard patterns
- Added domainMatchesWatchlistEntry for configurable matching logic
- Updated GlobalBlockingService and OrganizationBlockingService
- Updated tests to verify new behavior
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* refactor: simplify wildcard pattern generation to strip only first part
- Only strips the first part before the first dot
- Handles multi-part TLDs correctly (e.g., .co.uk)
- Returns empty array for two-part domains (e.g., cal.com -> no pattern)
- app.cal.com -> *.cal.com
- bloody-hell.cal.co.uk -> *.cal.co.uk
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-29 23:59:51 +00:00
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Add database index on the channelId column in the SelectedCalendar
table to improve lookup performance for watched calendar channels.
2026-01-29 20:36:40 +00:00
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>
* 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>
## 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
Benny JooGitHubbenny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* 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>
* 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>
* 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
* 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>
* 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>
## 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
* 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>
## 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
* 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
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
* 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>
* 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>
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
* 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>
* 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
Alex van AndelGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
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>
* 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>
* 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
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* 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
MorganGitHubDevin 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-27 15:23:26 -03:00
Joe Au-YeungGitHubjoe@cal.com <j.auyeung419@gmail.com>joe@cal.com <j.auyeung419@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Create `getSalesforceTokenLifetime`
* When connecting salesforce, add token_lifetime
* Migrate token_lifetime and refetch if token expiry doesn't match
* Add tests for Salesforce token lifetime feature
- Add unit tests for getSalesforceTokenLifetime function
- Add integration tests for token lifecycle management in CrmService
- Fix type error in CrmService.ts by extracting refreshToken variable
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* chore: re-trigger CI
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-27 10:00:48 -03:00
Peer RichelsenGitHubpeer@cal.com <peer@cal.com>peer@cal.com <peer@cal.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add proration invoice and reminder email templates
Add email templates for monthly proration billing notifications:
- ProrationInvoiceEmail: Sent when invoice is created for additional seats
- ProrationReminderEmail: Sent 7 days later if invoice remains unpaid
Includes:
- React email templates using V2BaseEmailHtml
- BaseEmail classes for rendering
- Billing email service functions
- Translation keys for email content
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use allSettled
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 09:28:27 +00:00
MorganGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Rajiv Sahal
Add three new optional callbacks to CalProvider that enable users to react during the access token refresh lifecycle:
- onTokenRefreshStart: Called when token refresh begins
- onTokenRefreshSuccess: Called when token refresh succeeds
- onTokenRefreshError: Called when token refresh fails with error message
These callbacks are invoked in both token refresh locations:
1. Response interceptor (when API returns 498 status)
2. Initial access token validation
The callbacks are properly passed through the component hierarchy:
CalProvider -> BaseCalProvider -> useOAuthFlow hook
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Rajiv Sahal <sahalrajiv-extc@atharvacoe.ac.in>
2026-01-27 14:47:56 +05:30
Benny JooGitHubbenny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>