Commit Graph
2328 Commits
Author SHA1 Message Date
2881961859 feat: add custom calendar reminder for Google Calendar events (#26078)
* feat: add custom calendar reminder for Google Calendar events

Allows users to set default reminder notifications (10, 30, or 60 minutes)
for events created via Cal.com bookings in Google Calendar. This addresses
the issue where Google Calendar's default reminders don't apply to
API-created events.

- Add customCalendarReminder field to DestinationCalendar model
- Create reminder selector UI in destination calendar settings
- Update GoogleCalendarService to apply custom reminders (popup + email)
- Add TRPC endpoint for updating reminder settings

* fix: address code review feedback

- Use z.union with literal values (10, 30, 60) for stricter schema validation
- Add localization for toast messages using t()
- Fix test data to use null for customCalendarReminder to match test intent

* fix: add customCalendarReminder to DestinationCalendar types

Update manually-defined DestinationCalendar types to include the new
customCalendarReminder field added in the previous commit. This fixes
type mismatches when passing Prisma-persisted destination calendars to
functions using these local type definitions.

* fix: update customCalendarReminder type in test to match Prisma schema

The customCalendarReminder field is defined as a non-nullable Int with
default value of 10 in the Prisma schema. Changed test value from null
to 10 to fix TS2345 type error.

* feat: add 'just in time' reminder option for Google Calendar events

- Add 0 (just in time) as a valid reminder option alongside 10, 30, 60 minutes
- Update TRPC schema to accept 0 as valid reminder value
- Add 'Just in time' option to reminder dropdown selector UI
- Add translation for 'just_in_time' key in English locale
- Include comprehensive test case for 0-minute (just in time) reminders
- Remove unused import from test file

This addresses reviewer feedback to provide flexible 'just in time' option that allows reminders to fire at exact event start time.

🤖 Generated with Claude Code

* fix: add customCalendarReminder to calendars service mock

- Add missing customCalendarReminder field to destination calendar mock
- Matches the Prisma schema requirement
- Fixes type error in calendars controller e2e test

* fix: add customCalendarReminder to destination calendars controller test

- Add missing customCalendarReminder field to mock destination calendar
- Matches Prisma schema requirement
- Fixes type error in destination-calendars controller e2e test

* fix: cast customCalendarReminder to ReminderMinutes type

- Add type cast for reminderValue to ensure type safety
- Use nullish coalescing (??) to preserve 0 as valid reminder value
- Ensures database number type is properly cast to ReminderMinutes union

* refactor: simplify translation logic in DestinationReminderSelector

- Remove conditional check for 'just_in_time' label
- Pass count parameter to all translations uniformly
- Translation function handles unused parameters gracefully

Addresses review feedback from @Khaan25

* refactor: make custom calendar reminder opt-in and use repository pattern

- Change default from 10 to null (opt-in feature)
- Add DestinationCalendarRepository to avoid direct Prisma usage
- Add 'Use default reminders' option to UI

* refactor: remove redundant migration file

The original migration already creates customCalendarReminder as nullable,
so this second migration to make it nullable is not needed.

* fix: type error for customCalendarReminder in destination calendar settings

* refactor: validate customCalendarReminder with Zod schema instead of type casting

* refactor: use instance methods in DestinationCalendarRepository

Changed from static to instance methods with getInstance() pattern as requested in review.

* refactor: replace singleton with DI for DestinationCalendarRepository

- Remove getInstance() singleton pattern
- Add DI tokens, module, and container
- Update GoogleCalendarService and tRPC handler to use DI

---------

Co-authored-by: Volnei Munhoz <volnei@cal.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
2026-01-14 12:32:00 +01:00
MorganGitHubmorgan@cal.com <morgan@cal.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
0b37520f0d fix: translate location dropdown group labels and options in event-type settings (#26784)
* fix: translate location dropdown group labels in event-type settings

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

* fix: use requesting user's locale for team event type translations

For team event types, the current user might not be in eventType.users,
causing translations to default to English. This fix queries the user's
locale directly from the database when not found in the event type users.

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

* refactor: pass userLocale as parameter instead of database call

Per PR feedback, pass the authenticated user's locale as an optional
parameter to getEventTypeById instead of making an extra database call.
The locale is passed from ctx.user.locale in the tRPC handler.

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

* fix: provide userLocale in apiv2 getEventTypeById

* fix: remove unused ts comments

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-14 08:28:31 -03:00
Rajiv SahalandGitHub 851aa30829 fix: respect hideCalendarNotes setting during booking reschedule (#25945)
Add hideCalendarNotes support to reschedule flow

The hideCalendarNotes flag was only handled in CalendarManager.createEvent(), not in updateEvent(). This caused notes to become visible again in ICS files after rescheduling.

Changes:
- Add hideCalendarNotes handling to CalendarManager.updateEvent()
- Add hideCalendarNotes checks to reschedule email functions
- Move description reset before reschedule call (required for cloned event)
2026-01-13 20:31:38 -03:00
c13fce4483 fix: changes to error on schedule name empty save (#24044)
* fix #21709: change to error on schedule name empty save

* fix comments

* minor enahncemnts

---------

Co-authored-by: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2026-01-13 18:29:58 +00:00
Eunjae LeeGitHubeunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>sean-brydon
5c686d90f9 feat: add tri-state UI settings pages and auto opt-in preference (#25892)
* feat: add tri-state UI settings pages and auto opt-in preference

TASK 5: Tri-state UI with ToggleGroup
- Create shared TeamOrgFeaturesSettings component
- Create user features settings page (features-view.tsx)
- Create team features settings page
- Create org features settings page

TASK 6: Add auto opt-in preference
- Add autoOptInExperimentalFeatures field to User and Team models
- Add migration for new fields
- Add TRPC endpoints for auto opt-in preference (using repository pattern)
- Add auto opt-in checkboxes to settings pages

Also adds i18n keys for feature opt-in UI.

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

refactor: rename autoOptInExperimentalFeatures to autoOptInFeatures

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

refactor: apply PBAC procedure pattern to featureOptIn router

- Create createTeamPbacProcedure for team-scoped endpoints
- Create createOrgPbacProcedure for organization-scoped endpoints
- Refactor all team/org endpoints to use the new PBAC procedures
- Significantly reduces boilerplate code for permission checks

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

add features pages

implement hooks

update style

update style

rename slug to featureId

show Features page on the side bar only if OPT_IN_FEATURES.length > 0

revert unncessary renaming

revert some changes

remove some changes

* fix repository usage

* test: add unit tests for PBAC utility procedures

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

* feat: add 'disabled by organization' badge for Team Level Features page

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

* a little clean up

* feat: add effectiveReason to computeEffectiveStateAcrossTeams for better UI feedback

- Update computeEffectiveStateAcrossTeams to return both enabled state and reason
- Add EffectiveStateReason type with 6 possible values
- Update FeatureOptInService to include effectiveReason in resolved state
- Simplify useUserFeatureOptIn.getBlockedWarning to use effectiveReason directly
- Add feature_no_explicit_enablement_warning translation
- Invalidate feature list when auto-opt-in setting changes in all hooks

* test: add tests for FeatureOptInService.listFeaturesForTeam and refactor router to use TeamRepository

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

* make it clearer about auto opt in

* move hooks to apps/web/module

* fix

* fix: move types to packages/features/feature-opt-in, fix imports and test mocks

- Move types.ts from apps/web/modules/feature-opt-in/hooks to packages/features/feature-opt-in
- Update FeaturesSettings.tsx to import types from new location
- Update hooks to import types from @calcom/features/feature-opt-in/types
- Fix organization features-view import path (~/settings/organizations -> ~/ee/organizations)
- Fix PermissionCheckService mock in util.test.ts to use class syntax

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

* fix: add validation for team ID and remove isPublic from featureOptIn handler

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

* fix: resolve biome lint errors in feature-opt-in files

- Add explicit return types to functions and methods
- Replace ternary operators with if-else statements
- Replace forEach with for...of loops to avoid useIterableCallbackReturn
- Extract helper functions to reduce function complexity
- Add explicit type annotations to variables
- Move exports to end of file to satisfy useExportsLast rule

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

* fix: resolve type errors in featureOptIn router

- Replace ctx.organizationId with ctx.user.organization.id
- Add null checks for organizationId in org procedures
- Remove incorrect type annotation from featureOptInRouter

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

* refactor: address PR feedback on feature opt-in implementation

- Refactor createMutationCallbacks to useMutationCallbacks hook with useLocale internally
- Restore comment on featureOptIn prop in FeaturesSettings.tsx
- Revert getAllTeamIds helper, use ternary operator instead
- Use ctx.user.organizationId with proper guard clauses

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

* fix type error

* feat: disable toggle when feature is blocked by higher level

- Add isBlockedByHigherLevel function to UseFeatureOptInResult interface
- Implement blocking detection for user level (org/team disabled)
- Implement blocking detection for team level (org disabled)
- Organization level never blocked (top level)
- Update FeaturesSettings to disable ToggleGroup when blocked

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

* change order of toggle buttons

* feat: add policy field (permissive/strict) to feature opt-in config

- Add OptInFeaturePolicy type with 'permissive' and 'strict' modes
- Update computeEffectiveStateAcrossTeams to handle both policies:
  - Permissive: user opt-in can activate; disables only win if ALL teams disable
  - Strict: user opt-in alone not enough; ANY explicit disable blocks
- Add new EffectiveStateReason values for strict policy
- Update FeatureOptInService to read policy from config
- Add unit tests for all 9 policy scenarios from spec

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

* refactor: rewrite test file with scenario tables and make policy required

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

* fix type

* fix types

* make policy required

* disable toggle group if blocked by higher level

* refactor: move PBAC procedures to packages/trpc/server/procedures

- Move util.ts to pbacProcedures.ts in procedures folder for better reusability
- Move util.test.ts to pbacProcedures.test.ts alongside the main file
- Update imports in _router.ts to use new location

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

* fix: remove redundant null checks in featureOptIn router

The createOrgPbacProcedure middleware already validates organizationId
and throws if null. Use non-null assertion (!) instead of redundant
runtime checks since the middleware guarantees the value exists.

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

* refactor: improve middleware typing to avoid non-null assertions

Remove explicit return type from createOrgPbacProcedure to let TypeScript
infer the extended context type. This allows handlers to use ctx.organizationId
directly (typed as number) instead of ctx.user.organizationId! assertions.

The middleware validates organizationId and adds it to the context, so
downstream handlers can safely access ctx.organizationId as a number.

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

* feat(pbac): use featureOptIn permissions instead of generic team/org permissions

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

* feat(pbac): add PBAC to team features page and pass canEdit to views

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

* fix: add effectiveReason to IFeatureOptInService and update listFeaturesForTeam interface

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

* fix: add feature_any_team_disabled to isUserBlockedByHigherLevel check

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

* fix: add strict-policy reasons to warning helper function

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
2026-01-13 15:37:53 +01:00
Hariom BalharaGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
75d611c2e8 chore: Integrate creation/rescheduling booking audit for Recurring/regular booking/seated bookings (#26046)
* Integrate creation/rescheduling booking audit

* fix: add missing hostUserUuid to booking audit test data

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

* fix-ci

* feat: enhance booking audit with seat reference

- Added support for seat reference in booking audit actions.
- Updated localization for booking creation to include seat information.
- Modified relevant services to pass attendee seat ID during booking creation.

* fix: update test data to match schema requirements

- Add seatReferenceUid: null to default mock audit log data
- Add seatReferenceUid: null to multiple audit logs test case
- Convert SEAT_RESCHEDULED test data to use numeric timestamps instead of ISO strings

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

* Allow nullish seatReferenceUid

* feat: enhance booking audit to support rescheduledBy information

- Updated booking audit actions to include rescheduledBy details, allowing tracking of who rescheduled a booking.
- Refactored related services to accommodate the new rescheduledBy parameter in booking events.
- Adjusted type definitions and function signatures to reflect the changes in the booking audit context.

* Avoid possible run time issue

* Fix imoport path

* fix failing test due to merge from main\

* Pass useruuid

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-13 13:16:16 +00:00
sean-brydonandGitHub aaf5958b7d feat: adds admin billing section (#26747)
* feat: adds admin billing section

* use loading prop

* add log on resend error

* add error log in billing portal
2026-01-13 10:34:52 +00:00
Eunjae LeeGitHubeunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
829d6c4714 feat(pbac): add FeatureOptIn resource to permission registry (#26761)
* feat(pbac): add Feature resource to permission registry

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

* feat(pbac): add migration for Feature resource permissions

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

* feat(pbac): add English translations for Feature resource

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

* feat(pbac): update Feature resource for opt-in/opt-out control (read and update only)

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

* feat(pbac): rename Feature to FeatureOptIn resource

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

* feat(pbac): simplify update description text

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-13 10:17:41 +00:00
sean-brydonGitHubunknown <>sean@cal.com <Sean@brydon.io>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
383314d3e2 feat: add skip trial feature for teams/orgs billing page (#26584)
* feat: add skip trial feature for teams/orgs billing page

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* feat: add translation strings for skip trial feature and fix lint-staged config

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: use IS_TEAM_BILLING_ENABLED instead of IS_SELF_HOSTED

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* fix: use correct DialogHeader props in billing-view.tsx

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* restore lint staged config file

* invalidate trpc cache

* fix: update role filter and error message in skipTrialForTeam handler

- Changed role filter to include both OWNER and ADMIN roles to match authorization logic
- Updated error message to reflect that both owners and admins can skip the trial

Addresses Cubic AI review feedback on PR #26584

Co-Authored-By: unknown <>

* fix: optimize skipTrialForTeam to query only specific team by ID

Address Cubic AI review feedback: Replace findAllAcceptedTeamMemberships
(which fetches all teams) with TeamRepository.findById (which fetches
only the specific team needed). Authorization is already validated
earlier in the handler, so this redundant query was inefficient.

Co-Authored-By: unknown <>

* fix static methods

* feat: use pbac

* fix: remove redundant team query in getSubscriptionStatus handler

Co-Authored-By: sean@cal.com <Sean@brydon.io>

* add pbac to skip team handler

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-13 09:17:42 +00:00
Bailey PumfleetGitHubunknown <>Pedro CastroDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
7c66f33de2 chore: UX Fixes (#26643)
* Copy changes

* Move search bar inline with new button

* Get rid of no more results message

* Change hidden badge to (hidden)

* Remove Cal.ai badge from sidebar

* Add dropdown to create button when there is multiple options

* Fix delete dialog

* Saved filters updates

* More string fixes

* Switch members table to use names

* Fix member spacing

* Fix routing form identifier field

* Fix routing forms stuff

* Only show SMS hint on SMS options

* Make workflow delete button minimal

* Fix padding on workflow steps

* Remove min width on workflow title

* Fix delete workflow PR

* Fix org profile buttons

* Fix org profile screen partially scrolled down

* Improve logos & banner uploads

* Personal profile fixes

* Fix settings general view stuff

* Sentence case consistency

* Fix stuff I broke

* Fix fab

* Fix hidden translation string

* Fix text fields

* Make button small for solo users too

* fix: update E2E tests to match sentence case labels in routing forms

* fix: update tests to match sentence case label changes

- insights.e2e.ts: chart titles (14 strings)
- event-types.e2e.ts: Organizer phone number location
- EditLocationDialog.test.tsx: phone number labels

* fix: address Cubic AI review feedback (confidence 9+)

- Replace hardcoded text-gray-500 with text-muted in TextField.tsx hint section
- Replace text locator with data-testid in E2E test for location select

Co-Authored-By: unknown <>

* fix: update E2E tests for sentence case label changes

- Use data-testid selectors for location options (more reliable than text)
- Update field identifiers in routing-forms tests to match new labels
- Fix Long text selector in manage-booking-questions test

* fix: replace text locator with data-testid in manage-booking-questions E2E test

Replace fragile text="Long text" locator with resilient
page.getByTestId("select-option-textarea") selector per E2E best practices.

Addresses Cubic AI review feedback (confidence 9/10).

Co-Authored-By: unknown <>

* fix: use .last() for multiple location select items

---------

Co-authored-by: Pedro Castro <pedro@cal.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-13 00:56:08 -05:00
Bailey PumfleetGitHubunknown <>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
5f21f54bae feat: Add compliance page to settings (#26777)
* Add compliance page to settings

* fix: sanitize error logging in B2 download route

Avoid logging raw error objects which may expose sensitive B2 credentials
or internal information. Use sanitized error message instead.

Co-Authored-By: unknown <>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-12 21:50:09 -03:00
Joe Au-YeungGitHubjoe@cal.com <j.auyeung419@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Eunjae Lee
8dbe3848e7 feat: Create Integration Attribute Sync records (#26007)
* Add db schema

* Add `CredentialRepository.findByTeamIdAndSlugs`

* Add enabled app slugs for attribute syncing

* Create repository for `IntegrationAttributeSync`

* Create zod schemas

* Create `AttributeSyncUserRuleOutputMapper`

* Create `IntegrationAttributeSyncService`

* Create DI contianer

* Create trpc endpoints

* Create page

* Include team name in `CredentialRepository.findByTeamIdAndSlugs`

* Update schema and relations

* Update types and schemas

* Add more methods to IntegrationAttributeSyncRepository

* Add more services to `IntegrationAttributeSyncService`
- getById
- Init updateIncludeRulesAndMappings

* Refactor `getTeams.handler` to use repository

* Create `createAttributeSync` trpc endpoint

* Create `updateAttributeSync` trpc endpoint

* Add router to trpc

* Create attribute sync child components

* Pass custom actions to `FormCard`

* Create `IntegrationAttributeSyncCard`

* Pass inital props via server side

* Fix prop

* Only refetch on mutation

* Fixes

* Add form error when duplicate field and attribute combo

* Add `updateTransactionWithRUleAndMappings` logic

* Adjust zod schemas

* Service add `updateIncludeRulesAndMappings`

* Pass orgId from server to component

* Rename types

* Add deleteById method to repository

* Add name to integrationAttributeSync

* Add deleteById method to service

* Rename method

* Add deleteAttributeSync trpc endpoint

* Make the IntegrationAttributeSyncCard a dummy component

* test: add tests for IntegrationAttributeSync feature

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

* Move creating a attribute sync record to the service

* Add i18n strings

* Safe select credential in find by id and team

* Fix default credentialId value in form

* Update repository return types

* Add i18n string

* Make credentialId optional for form schema

* Fix label

* Add cascade deletes

* Add verification that syncs belong to org

* Create mapper for repository output

* Type fixes

* Remove old test file

* Pass `attributeOptions` from parent to children

* Infer types from zod schema

* Type fixes

* Type fix

* Clean up

* Add i18n strings

* Remove unused file

* Address feedback

* Add migration file

* Address feedback

* Add validation for new integration values

* Remove unused router

* Move away from z.infer to z.ZodType

* Clean up comments

* Type fix

* Type fixes

* Type fix

* fix: add passthrough to syncFormDataSchema to preserve extra fields

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

* fix: remove incorrect test that expected extra fields to pass through syncFormDataSchema

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

* Add indexes

* Add aria label

* Address feedback - consistent validation

* Fix import paths for attribute types

* refactor: change attributeSyncRules array to singular attributeSyncRule

The database schema enforces a one-to-one relationship between
IntegrationAttributeSync and AttributeSyncRule (via @unique constraint),
and the UI only supports a single rule. This change makes the TypeScript
type match the database schema and UI behavior.

Changes:
- Update IntegrationAttributeSync interface to use attributeSyncRule: AttributeSyncRule | null
- Update mapper to return singular rule instead of wrapping in array
- Update UI component to access sync.attributeSyncRule directly
- Update IIntegrationAttributeSyncUpdateParams Omit type
- Update tests to use attributeSyncRule: null instead of attributeSyncRules: []

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

* feat: implement FeatureOptInService (#25805)

* feat: implement FeatureOptInService WIP

* clean up

* feat: consolidate feature repositories and add updateFeatureForUser

- Implement updateFeatureForUser in FeaturesRepository (similar to updateFeatureForTeam)
- Move getUserFeatureState and getTeamFeatureState from PrismaFeatureOptInRepository to FeaturesRepository
- Update FeatureOptInService to use only FeaturesRepository
- Add setUserFeatureState and setTeamFeatureState methods to FeatureOptInService
- Update _router.ts to remove PrismaFeatureOptInRepository usage
- Remove PrismaFeatureOptInRepository.ts and FeatureOptInRepositoryInterface.ts
- Update features.repository.interface.ts and features.repository.mock.ts
- Add integration tests for updateFeatureForUser, getUserFeatureState, getTeamFeatureState
- Update service.integration-test.ts to use FeaturesRepository

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

* refactor: rename updateFeatureForUser to setUserFeatureState

Rename to match the convention used for setTeamFeatureState

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

* refactor: return FeatureState type from getUserFeatureState and getTeamFeatureState

* fix integration tests

* clean up logics

* update services and router

* refactor: change getUserFeatureState and getTeamFeatureState to accept featureIds array

- Renamed getUserFeatureState to getUserFeatureStates
- Renamed getTeamFeatureState to getTeamFeatureStates
- Changed parameter from featureId: string to featureIds: string[]
- Changed return type from FeatureState to Record<string, FeatureState>
- Updated FeatureOptInService to use the new batch methods
- Added tests for querying multiple features in a single call
- Optimized listFeaturesForTeam to fetch all feature states in one query

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

* feat: add getFeatureStateForTeams for batch querying multiple teams

- Added getFeatureStateForTeams method to query a single feature across multiple teams in one call
- Updated FeatureOptInService.resolveFeatureStateAcrossTeams to use the new batch method
- Replaces N+1 queries with a single database query for team states
- Added comprehensive integration tests for the new method

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

* refactor: combine org and team state queries into single call

- Include orgId in the teamIds array passed to getFeatureStateForTeams
- Extract org state and team states from the combined result
- Reduces database queries from 3 to 2 in resolveFeatureStateAcrossTeams

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

* refactor: use team.isOrganization and clarify computeEffectiveState comment

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

* refactor: use MembershipRepository.findAllByUserId with isOrganization

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

* feat: add featureId validation using isOptInFeature type guard

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

* less queries

* add fallback value

* fix type error

* move files

* add autoOptInFeatures column

* use autoOptInFeatures flag within FeatureOptInService

* add setUserAutoOptIn and setTeamAutoOptIn

* fix computeEffectiveState logic

* rewrite computeEffectiveState

* clean up integration tests

* clean up in afterEach

* fix type error

* refactor: use FeaturesRepository methods instead of direct Prisma calls

Replace all manual userFeatures and teamFeatures Prisma operations with
the new setUserFeatureState and setTeamFeatureState repository methods.

Changes include:
- Admin handlers (assignFeatureToTeam, unassignFeatureFromTeam)
- Test fixtures and integration tests
- Playwright fixtures
- Development scripts

This ensures consistent feature flag management through the repository
pattern and supports the new tri-state semantics (enabled/disabled/inherit).

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

* clean up

* fix the logic

* extract some logic into applyAutoOptIn()

* remove wrong code

* refactor: convert setUserFeatureState and setTeamFeatureState to object params with discriminated union

- Convert multiple positional parameters to single object parameter
- Use discriminated union types: assignedBy required for enabled/disabled, omitted for inherit
- Update all callers across repository, service, handlers, fixtures, and tests

* fix type error

* use Promise.all

* fix

---------

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

* Prevent duplicate field and attribute mappings

* Add validation that attribute belongs to the org

* fix: address Cubic AI review feedback

- Add @@index([credentialId]) to IntegrationAttributeSync model for efficient cascade deletes and credential-based queries (confidence: 9/10)
- Fix translation key from 'credential_required' to 'attribute_sync_credential_required' to match existing locale definition (confidence: 10/10)

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

* fix: address remaining cubic review feedback

- RuleBuilder.tsx: Use unique IDs for React keys instead of array index to prevent reconciliation bugs when removing conditions
- updateAttributeSync.handler.ts: Add early organization check before service calls for consistency
- createAttributeSync.handler.ts: Add CredentialNotFoundError class for type-safe error handling instead of string matching
- IntegrationAttributeSyncService.test.ts: Replace expect.fail() with proper Vitest rejects.toSatisfy() pattern

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

* Pull test file from main

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
2026-01-12 22:57:28 +00:00
2f90138757 feat: update translations via @LingoDotDev (#26773)
Co-authored-by: Lingo.dev <support@lingo.dev>
2026-01-12 21:52:37 +00:00
devin-ai-integration[bot]GitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>susan@cal.com <susan@cal.com>
41dcfe0307 chore: update company email banner copy (#26767)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: susan@cal.com <susan@cal.com>
2026-01-12 20:52:35 +00:00
cal-com-ci[bot]GitHubLingo.devDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Keith Williams
f24f5b2b35 feat: update translations via @LingoDotDev (#26700)
Co-authored-by: Lingo.dev <support@lingo.dev>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2026-01-11 09:01:28 +00:00
f86a8dc93e feat: update translations via @LingoDotDev (#26599)
Co-authored-by: Lingo.dev <support@lingo.dev>
2026-01-10 17:54:22 +00:00
+4
Dhairyashil ShindeGitHubunknown <>unknown <>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Anik Dhabal BabuKeith WilliamsAnshumancanrockMorgancal.comAnas NajamEunjae LeeAmit SharmaVolnei Munhoz
2d514a2a3e feat: companion alert system for browser extension (#26613)
* feat: companion alert system for browser extension

* feat: implement cross-platform alert system for browser extension

- Add ToastContext.tsx with global toast provider for managing toast state
- Add GlobalToast.tsx centered toast component for web/browser extension
- Modify alerts.ts to be platform-aware (native Alert on iOS/Android, toast on web)
- Add showInfoAlert function for informational alerts
- Update _layout.tsx to wrap app with ToastProvider and GlobalToast
- Export new toast context and alert functions from index files

* style: update toast to white/black design system

- Use white background with gray border
- Use black icons and text colors
- Match companion app design system

* open the toast at the center

* refactor: migrate event-types/index.tsx to unified alert system

- Remove inline toast state (showToast, toastMessage) and showToastMessage function
- Remove inline toast UI component at the end of the file
- Migrate all platform-specific Alert.alert calls to showSuccessAlert/showErrorAlert
- Simplifies code by using cross-platform alert utilities

* refactor: migrate useBookingActions.ts to unified alert system

- Add showSuccessAlert import alongside showErrorAlert
- Migrate all Alert.alert('Success', ...) calls to showSuccessAlert
- Affected handlers: handleSubmitReschedule, handleRescheduleWithValues,
  handleSubmitCancel, handleCancelBooking, handleConfirmBooking,
  handleRejectBooking, handleSubmitReject, handleInlineConfirm

* refactor: migrate useBookingActionModals.ts to unified alert system

- Add showSuccessAlert import alongside showErrorAlert
- Migrate all Alert.alert('Success', ...) calls to showSuccessAlert
- Affected handlers: handleAddGuests, handleUpdateLocation, handleMarkNoShow

* refactor: migrate medium-priority screens to unified alert system

- AvailabilityDetailScreen.ios.tsx: 4 Alert.alert calls migrated
- RescheduleScreen.tsx/ios/android: 3 Alert.alert calls each migrated
- EditLocationScreen.tsx/ios: 4 Alert.alert calls each migrated
- Removed unused Alert imports

* refactor: migrate remaining medium-priority screens to unified alert system

- BookingDetailScreen.tsx: 2 Alert.alert calls migrated
- AvailabilityListScreen.tsx: 1 Alert.alert call migrated
- AddGuestsScreen.tsx: 6 Alert.alert calls migrated
- MarkNoShowScreen.tsx: 2 Alert.alert calls migrated
- EditAvailabilityOverrideScreen.tsx: 4 Alert.alert calls migrated
- EditAvailabilityOverrideScreen.ios.tsx: 2 Alert.alert calls migrated
- Removed unused Alert imports

* refactor: migrate medium-priority app routes to unified alert system

Migrated 24 app route files from direct Alert.alert() calls to unified
alert utilities (showErrorAlert, showSuccessAlert, showInfoAlert):

- reschedule.tsx, reschedule.ios.tsx
- edit-location.tsx, edit-location.ios.tsx
- add-guests.tsx, add-guests.ios.tsx
- mark-no-show.tsx, mark-no-show.ios.tsx
- view-recordings.tsx, view-recordings.ios.tsx
- meeting-session-details.tsx, meeting-session-details.ios.tsx
- profile-sheet.tsx, profile-sheet.ios.tsx
- edit-availability-hours.tsx, edit-availability-hours.ios.tsx
- edit-availability-day.tsx, edit-availability-day.ios.tsx
- edit-availability-name.tsx, edit-availability-name.ios.tsx
- edit-availability-override.tsx, edit-availability-override.ios.tsx
- booking-detail.tsx, booking-detail.ios.tsx

This enables cross-platform alert support where native Alert.alert()
is used on iOS/Android and toast notifications on web (browser extension).

* refactor: migrate lower-priority components to unified alert system

Migrated Alert.alert calls to showSuccessAlert/showErrorAlert/showInfoAlert in:
- event-types/index.ios.tsx (copy link, delete, duplicate success alerts)
- event-type-detail.tsx (copy link, create/update success, validation errors, info alerts)
- deep-links.ts (error alerts for link failures)
- LogoutButton.tsx (error alert)
- BookingModals.tsx and .ios.tsx (report booking info alerts)
- AdvancedTab.tsx (info alert for unsaved event type)
- BookingListScreen.tsx (success/error/info alerts for bulk actions)

Confirmation dialogs with buttons remain as Alert.alert (out of scope).

* fix: restore Alert import for confirmation dialogs, migrate remaining info alert

- AdvancedTab.tsx: Added back Alert import for timezone selector confirmation dialog (out of scope), migrated private links info alert to showInfoAlert
- deep-links.ts: Added back Alert import for request reschedule confirmation dialog (out of scope)

* some ui dialoes were missing

* fixed multi hours ui issues on Availability detail page for android and web

* fix: add __DEV__ check for web platform in showErrorAlert

The showErrorAlert function was showing error toasts to production users
on web platform, bypassing the __DEV__ check that exists for native platforms.
This fix ensures consistent behavior across all platforms - error alerts
are only shown in development mode, while production errors are logged
to console.

Co-Authored-By: unknown <>

* fix: address dual dialogs on web and onSuccess timing issues

- BookingDetailScreen.tsx: Add Platform.OS === 'android' guard to AlertDialog
  to prevent dual dialogs rendering on web (FullScreenModal + AlertDialog)
- RescheduleScreen.android.tsx: Restore original Alert.alert with callback
  to ensure onSuccess() is called after user dismisses the alert

Co-Authored-By: unknown <>

* fix: restore Alert.alert with callback for native platforms

- AddGuestsScreen.tsx: Use platform-specific handling - Alert.alert with
  callback on iOS/Android, showSuccessAlert on web
- EditAvailabilityOverrideScreen.tsx: Same pattern - wait for user
  acknowledgment on native platforms before calling onSuccess()

Co-Authored-By: unknown <>

* fix: RescheduleScreen timing and GlobalToast useState pattern

- RescheduleScreen.tsx: Use platform-specific handling - Alert.alert with
  callback on iOS/Android, showSuccessAlert on web
- GlobalToast.tsx: Replace useMemo with useState for Animated.Value to
  guarantee instance preservation across renders

Co-Authored-By: unknown <>

* fix: restore Alert.alert with callback for iOS delete success

AvailabilityDetailScreen.ios.tsx: Use Alert.alert with callback to ensure
router.back() is called after user dismisses the success alert

Co-Authored-By: unknown <>

* feat(companion): new event type detail page  (#26678)

* fix: skip stale run-ci label check on workflow re-runs (#26590)

* fix: trust community PRs when maintainer pushes to the branch

When a maintainer merges main into a community PR branch, the new SHA
invalidates the run-ci label timing check because the label was added
before the new push. This fix adds a check to trust the PR if the
person who pushed the latest commit has write access.

This handles the case where a maintainer:
- Merges main into a community PR to resolve conflicts
- Pushes any changes to help the contributor

The security model is maintained because:
- Only users with write access can trigger this trust
- The maintainer has reviewed the code by pushing to it

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* fix: skip stale label check on workflow re-runs

Instead of implicitly trusting maintainer pushes (which could be just
a sync action without code review), use github.run_attempt to detect
re-runs. If run_attempt > 1, it means the workflow was explicitly
re-triggered (via run-ci.yml or manual re-run), so we skip the stale
label check.

This avoids the need to remove and re-add the 'run-ci' label after
syncing a community PR with main, while keeping the explicit approval
flow intact.

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* Simplify comment about re-runs in PR workflow

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>

* fix: Text cursor barely visible in calendar event name field (#26563)

* fix: cursor visibility in input fields

* fix: cursor visibility in input fields with suffix addons

* fix: text cursor visibility in input fields

---------

Co-authored-by: Keith Williams <keithwillcode@gmail.com>

* fix: PayPal setup page inconsistent spacing and button styling (#26612)

* chore: api v2 generate swagger only in dev (#26617)

* feat: add BUILD_FROM_BRANCH option to release-docker workflow (#26615)

* feat: add BUILD_FROM_BRANCH option to release-docker workflow

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>

* fix: sanitize branch names with slashes for valid Docker tags

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>

* refactor: extract common logic into prepare job to avoid duplication

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>

---------

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

* feat: add Cubic AI to Devin review integration workflow (#26618)

* feat: add Cubic AI to Devin review integration workflow

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>

* fix: update permissions to allow posting PR comments

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>

* fix: remove sensitive API response logging from CI workflow

Address Cubic AI review feedback: Remove the debug log that outputs the
full Devin API response, which could expose sensitive session tokens or
authentication data in CI logs. The session URL is still logged when
successfully extracted.

Co-Authored-By: unknown <>

---------

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

* chore: enable/disable slots workers via env (#26621)

* chore: enable/disable slots workers via env

* fix: address Cubic AI review feedback

- Fix incorrect JSDoc comment for getSerializableContext method
- Remove debug console.log statement from slots controller
- Fix port suffix condition to preserve original behavior

Co-Authored-By: unknown <>

---------

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

* chore: USE_POOL env var for api v2 prisma pooling

* fix list numbering in Manual setup section of README (#26620)

* Revert "chore: USE_POOL env var for api v2 prisma pooling"

This reverts commit a97092619f.

* feat: limit badges to 2 with hover/click popover in UserListTable (#26556)

* feat: limit badges to 2 with hover tooltip in UserListTable

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

* refactor: reuse LimitedBadges component with clickable popover for mobile

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

* refactor: move LimitedBadges to components/ui with hover+click support

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

* refactor: fix Biome lint issues in LimitedBadges and UserListTable

- Refactor LimitedBadges to concrete component with BadgeItem type
- Move exports to end of files to comply with useExportsLast rule
- Add explicit types to callback parameters for useExplicitType rule
- Convert nested ternary to if-else for filterType calculation
- Remove unused imports (Row, Table types)
- Update ResponseValueCell and UserListTable to use new LimitedBadges API

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

* fix: add proper types for filterType and getFacetedUniqueValues

- Add FilterType import from @calcom/types/data-table
- Add FacetedValue import from @calcom/features/data-table
- Type filterType as FilterType to allow reassignment to different ColumnFilterType values
- Type getFacetedUniqueValues return as Map<FacetedValue, number>

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

* add vertical gap

* fix: address code review feedback for LimitedBadges

- Add index to id for unique keys in ResponseValueCell.tsx
- Restore orange variant for group options in UserListTable.tsx
- Fix useMemo dependency array (add t, remove dispatch)
- Fix import ordering with biome
- Convert ternary operators to if-else statements for biome compliance

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

* refactor: remove id from BadgeItem type, use label as key

- Remove id field from BadgeItem type in LimitedBadges
- Use label as React key instead of id
- Remove unused rowId parameter from ResponseValueCell
- Update all consumers to not pass id field

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

* refactor: use index for key instead of label in LimitedBadges

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

* Revert "refactor: use index for key instead of label in LimitedBadges"

This reverts commit 1daaac47e596fd6b5f5583847faa10b131783349.

---------

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

* chore: add database-backed feature flag for sidebar tips section (#26516)

* chore: remove tips section from sidebar

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* chore: add feature flag for sidebar tips section

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* chore: use database-backed feature flag for sidebar tips section

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

---------

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

* feat: add automated stale PR completion workflow with Devin API (#26627)

* feat: add stale PR completion workflow with Devin API

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* feat: only trigger for community PRs (non-calcom org members)

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* refactor: use author_association pattern from pr.yml for community check

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* refactor: simplify workflow - use community label check and let Devin gather PR details

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

---------

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

* feat: add Devin PR conflict resolver workflow (#26624)

* feat: add Devin PR conflict resolver workflow

Adds a GitHub Actions workflow that automatically detects PRs with merge
conflicts and spins up Devin sessions to resolve them.

How it works:
1. Triggers on push to main branch (when main updates could cause conflicts)
2. Also supports manual trigger via workflow_dispatch
3. Lists all open PRs and checks their mergeable status
4. For PRs with conflicts (mergeable=false, mergeable_state=dirty):
   - Checks if a Devin session was already created (avoids duplicates)
   - Creates a new Devin session with instructions to resolve conflicts
   - Posts a comment on the PR with the Devin session link

The workflow follows the same pattern as cubic-devin-review.yml for
consistency.

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

* fix: skip draft PRs in conflict detection workflow

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

* refactor: use GitHub Search API to filter draft PRs at API level

Instead of filtering draft PRs in the loop, use the GitHub Search API
with 'draft:false' filter which is more efficient as it filters at the
API level rather than fetching all PRs and filtering locally.

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

* style: remove explanatory comments from workflow

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

* style: remove all unnecessary explanatory comments

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

* refactor: use GraphQL for batched PR fetching and labels for tracking

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

* feat: add support for resolving conflicts on fork PRs

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

* fix: check response.ok before parsing Devin API response

Address Cubic AI review feedback: Add response.ok check before parsing
the response body to explicitly handle HTTP error status codes from the
Devin API. This distinguishes API failures (authentication errors,
server errors) from successful responses that might be missing expected
fields.

Co-Authored-By: unknown <>

* fix: improve Devin API error logging with PR number

Co-Authored-By: unknown <>

* feat: add pr_number input for manual fork PR conflict resolution

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

* feat: add maximum 15 PRs safety net limit

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>

* feat: make stale PR workflow fork-aware with workflow_dispatch support (#26633)

* feat: make stale PR workflow fork-aware with workflow_dispatch support

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

* fix: add null check for pr.head.repo in stale PR workflow

When a fork is deleted after a PR is created, pr.head.repo can be null
(documented GitHub API behavior). This would cause a TypeError when
accessing properties like fork, full_name, or clone_url.

Added a null check that fails gracefully with a clear error message
when the source repository has been deleted.

Co-Authored-By: unknown <>

---------

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

* feat: reuse existing Devin session for Cubic AI review feedback (#26632)

* feat: reuse existing Devin session for Cubic AI review feedback

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

* refactor: parse session ID from PR comments instead of API search

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

* fix: add error handling for message send API call in Cubic-Devin workflow

Addresses Cubic AI review feedback: The POST request to send a message
to an existing Devin session now checks the HTTP status code and fails
the step if the message wasn't delivered successfully. This prevents
posting a misleading comment claiming feedback was sent when the API
call actually failed.

Co-Authored-By: unknown <>

---------

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

* chore: Remove stale label when work is completed (#26638)

* chore: Remove stale label when work is completed

* Mark as ready for review too

* feat: add retry mechanism for UNKNOWN mergeable status PRs (#26635)

* feat: add retry mechanism for UNKNOWN mergeable status PRs

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

* fix: remove redundant filtering logic for unknown mergeable status PRs

Address Cubic AI review feedback by:
- Having processPR return isTargetPR in the unknown case (like the conflict case)
- Simplifying the main loop to just push PRs to unknownPRs without re-checking
  draft status and devin label (already checked in processPR)

Co-Authored-By: unknown <>

---------

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

* chore: Add sentry http integration (#26634)

* chore: ignore fork PRs in devin-conflict-resolver workflow (#26640)

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

* limits and advanced tabs

* availability tab

* basics tab

* black toggles!!

* new recurring, others tab and update basics

* version 1

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Anshumancanrock <109489361+Anshumancanrock@users.noreply.github.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: cal.com <morgan@cal.com>
Co-authored-by: Anas Najam <129951478+anzz14@users.noreply.github.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com>
Co-authored-by: Volnei Munhoz <volnei@cal.com>

* fix: address Cubic AI review feedback

- Add HTTP error handling for Devin API session creation in cubic-devin-review.yml
- Localize aria-label in LimitedBadges.tsx using t() function
- Improve Docker tag sanitization in release-docker.yaml to handle all invalid characters
- Avoid logging raw error objects and sensitive API response data in devin-conflict-resolver.yml
- Fix selectedSchedule dependency array issue in event-type-detail.tsx using ref pattern

Co-Authored-By: unknown <>

* chore: add translation key for show_x_more_items aria-label

Co-Authored-By: unknown <>

* fix: reset schedule ref on id change and add i18n pluralization

- Reset hasAutoSelectedScheduleRef when event type id changes to handle component reuse
- Add proper i18next pluralization variants (_one/_other) for show_x_more_items

Co-Authored-By: unknown <>

* revert: remove i18n changes from LimitedBadges and common.json

Per user request - i18n not needed in companion for now

Co-Authored-By: unknown <>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Anshumancanrock <109489361+Anshumancanrock@users.noreply.github.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: cal.com <morgan@cal.com>
Co-authored-by: Anas Najam <129951478+anzz14@users.noreply.github.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com>
Co-authored-by: Volnei Munhoz <volnei@cal.com>
2026-01-10 17:57:42 +05:30
Udit TakkarandGitHub 0330d14210 feat: system admin blocklist table (#25039)
* feat: system admin blocklist table

* chore: text

* fix: type error

* fix: type error

* fix: type error

* fix: frontend bug

* chore: improvments

* refactor: use shared components

* refactor: improvements

* fix: delete

* refactor: support multiple watchlist

* chore: update translation

* fix: type err

* fix: bulk bug

* tests: add unit test

* refactor: file

* refactor: file

* fix: type error

* fix: type error

* chore: translation

* refactor: use shared comments

* fix: imports

* fix: type error
2026-01-09 08:19:54 -03:00
Pedro CastroandGitHub 51639e38d7 fix(auth): block OAuth linking for unverified accounts (#26598)
* fix(auth): sanitize unverified accounts during OAuth linking

- Add AccountSanitizationService for secure account cleanup
- Clear webhooks, API keys, credentials, and sessions for unverified accounts
- Reset password and 2FA settings during OAuth conversion
- Nullify redirect URLs on event types

Only affects accounts that never completed email verification

* fix(auth): block OAuth linking for unverified accounts

  Replace sanitization with simpler blocking approach:
  - Unverified CAL accounts cannot link to OAuth (Google/SAML)
  - Add user-friendly error message with recovery path
  - Remove AccountSanitizationService (no data loss risk)
2026-01-09 11:04:39 +00:00
4cd664315d feat: update translations via @LingoDotDev (#26511)
Co-authored-by: Lingo.dev <support@lingo.dev>
2026-01-08 22:27:14 +00:00
KartikandGitHub 2f932f617c fix: remove "+" from Add Guests translations (#26582) 2026-01-08 14:19:26 +00:00
Pedro CastroandGitHub 170203051f fix: handle existing users on invite token flow (#26217)
* fix(auth): validate user before signup with invite token

Validate if user already exists before creating account when
signing up with team or organization invite tokens. Existing users
are redirected to login to accept the invitation.

- Add user existence check in signup handlers
- Return 409 for existing users with redirect to login
- Extract signup fetch logic to dedicated module
- Add e2e test coverage

* fix(auth): address code review feedback

- Fix fetchSignup tests to use vi.spyOn for proper mock restoration
- Add content-type validation before parsing JSON response
- Guard against undefined error in Stripe callback
- Use t() for localized error message
- Fix race condition in handlers by catching P2002 on create

* fix(auth): address additional code review feedback

- Add INVALID_SERVER_RESPONSE constant to follow established pattern
- Check error.meta.target includes email before returning USER_ALREADY_EXISTS
to avoid false positives from other unique constraint violations
- Add select: { id: true } to user.create calls since downstream functions only
need the user id

* test: add unit tests for P2002 handling in signup handlers

- Add shared test suite covering all P2002 edge cases
- Ensure 409 only for email constraint violations
- Fix non-token paths to use atomic create + catch pattern

* fix: update error message copy per review feedback

* fix(auth): address code review feedback and prevent orphan Stripe customers

- Add user existence check before Stripe customer creation (token flow)
- Add select clause to user.create for consistency
- Fix showToast argument order (pre-existing bug)
- Use toHaveURL instead of waitForURL in E2E tests

* fix(auth): resolve 500 errors by fixing Prisma error detection across module boundaries

The instanceof check for PrismaClientKnownRequestError fails when different
Prisma client instances are loaded. Added fallback check by constructor name

* fix(auth): validate invitedTo before upsert on team invite signup

* test(auth): update P2002 tests for new invite flow

P2002 tests now use non-token flow since token flow uses upsert
Added tests for invitedTo validation on invite signup

* fix(auth): add guards and P2002 handling per review feedback

- Guard existingUser check with if (foundToken?.teamId)
- Guard username check with if (username) for premium flow
- Add `select` clause to findFirst/findUnique queries
- Add try-catch on upsert for race condition P2002 errors

* fix(auth): narrow P2002 handling to email/username targets
2026-01-06 22:10:36 +00:00
Amit SharmaGitHubamit@cal.com <samit91848@gmail.com>amit@cal.com <samit91848@gmail.com>amit@cal.com <samit91848@gmail.com>amit@cal.com <samit91848@gmail.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>
eacfcd15a4 feat: Hubspot write to meeting object (#26039)
* feat: Hubspot write to meeting object

* fix: translate hardcoded strings and remove debug console.log

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* refactor

* fix: improve static value detection for placeholder replacement

- Changed condition from startsWith/endsWith to includes('{') to properly detect embedded placeholders
- Strings like 'Hello {name}!' are now correctly processed for placeholder replacement
- Pure placeholder tokens that can't be resolved return null
- Partially resolved values are returned as-is

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* refactor: split WriteToObjectSettings into types and utils files

- Extract interfaces, enums, and type definitions to WriteToObjectSettings.types.ts
- Extract constants and utility functions to WriteToObjectSettings.utils.ts
- Update main component to use the new utility functions
- Improves code organization and maintainability

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* revert: restore original static value detection logic

Per user request - the startsWith/endsWith check was intentional

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* test: add unit tests for HubSpot CRM service

Tests cover:
- ensureFieldsExistOnMeeting: field validation against HubSpot properties
- getTextValueFromBookingTracking: UTM parameter extraction
- getTextValueFromBookingResponse: placeholder replacement
- getDateFieldValue: date field resolution for different date types
- getFieldValue: main field value resolution for all field types
- generateWriteToMeetingBody: write-to-meeting body generation
- getContacts: contact search functionality

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* fix: correct type errors in HubSpot CRM service tests

- Import WhenToWrite enum from crm-enums
- Replace string literals with WhenToWrite.EVERY_BOOKING enum values
- Add missing whenToWrite property to field config objects

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* fix: use type casting for intentional type errors in tests

- Cast numeric fieldValue to string for testing non-string handling
- Cast invalid field type string to CrmFieldType for testing unsupported types

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* fix: prevent unhandled promise rejections in HubSpot CRM tests

- Re-apply mockGetAppKeysFromSlug implementation in beforeEach to ensure
  mock is always set correctly after clearAllMocks
- Change vi.resetAllMocks() to vi.clearAllMocks() to preserve mock
  implementations between tests
- Add explicit types to satisfy biome lint rules
- This fixes the 'Cannot read properties of undefined (reading client_id)'
  errors that were causing CI to fail with exit code 1

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* refactor: convert HubSpot tests to black-box testing through public methods

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* fix: properly type mock CalendarEvent in HubSpot tests

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* fix: properly type TFunction in mock CalendarEvent

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* chore: graceful owner fail test

* refactor

* fix: type check

* fix: remove null fields

* Update packages/app-store/hubspot/lib/CrmService.ts

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

---------

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-06 14:58:46 -03:00
750408ec21 feat: update translations via @LingoDotDev (#26497)
Co-authored-by: Lingo.dev <support@lingo.dev>
2026-01-06 15:01:45 +00:00
Hariom BalharaandGitHub a056c3217e chore: Add impersonation context support to booking audit (#26014)
## What does this PR do?

Adds infrastructure to track impersonation context in booking audit records and displays it in the UI. When an admin impersonates another user and performs booking actions, the audit system now:
- Records the **admin** as the actor (who actually performed the action)
- Stores the **impersonated user's UUID** in a separate `context` field
- Displays **"Impersonated By"** in the booking logs UI when viewing audit details

This separation ensures audit trail integrity (the admin is accountable) while preserving full context about whose account was being used.

### Changes
- Added `uuid` to `impersonatedBy` session object for actor identification
- Added `uuid` to top-level `User` type in next-auth types for session enrichment
- Added `context Json?` field to `BookingAudit` Prisma model
- Added `BookingAuditContextSchema` for type-safe context handling with `actingAsUserUuid` field
- Updated producer service interface and implementation to pass context through all queue methods
- Updated consumer service to persist context to database
- Updated repository to store and fetch context in BookingAudit records
- Added `impersonatedBy` field to `EnrichedAuditLog` type in `BookingAuditViewerService`
- Added `enrichImpersonationContext` method to resolve impersonated user details
- Updated booking logs UI to display "Impersonated By" in expanded details
- Added `impersonated_by` translation key

Link to Devin run: https://app.devin.ai/sessions/3f1252527aef4ead9401bdf055c0817b
Requested by: hariom@cal.com (@hariombalhara)

## 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 infrastructure change
- [ ] 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 type checks pass: `yarn type-check:ci --force`
2. Verify existing audit tests still pass: `TZ=UTC yarn test`
3. To fully test impersonation context display:
   - Have an admin impersonate a user
   - Perform a booking action (create, cancel, reschedule)
   - Navigate to the booking's audit logs
   - Expand the details for the action
   - Verify "Impersonated By" row appears showing the impersonated user's name
   - Verify the BookingAudit record has:
     - `actorId` pointing to the admin's AuditActor
     - `context` containing `{ actingAsUserUuid: "<impersonated-user-uuid>" }`

## Human Review Checklist

- [ ] Verify the `context` field schema design is appropriate for future extensibility
- [ ] Confirm the `uuid` addition to User type in next-auth doesn't break existing auth flows
- [ ] Check that the optional `context` parameter doesn't break existing queue method callers
- [ ] Verify no migration file is needed (or if squashing is handled separately)
- [ ] Verify the UI displays "Impersonated By" correctly when impersonation context is present
- [ ] Confirm `enrichImpersonationContext` handles edge cases (null context, invalid context, deleted user)

## Checklist

- [x] My code follows the style guidelines of this project
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have checked if my changes generate no new warnings
2026-01-06 16:16:18 +05:30
bbfb17ae5c feat: update translations via @LingoDotDev (#26445)
Co-authored-by: Lingo.dev <support@lingo.dev>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2026-01-05 15:18:03 +00:00
Hariom BalharaGitHubhariom@cal.com <hariombalhara@gmail.com>Udit TakkarDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
a7fd7890a7 feat: integrate BookingHistory with Bookings V3 design (#26301)
* Integrate BookingHistory with Bookings V3 design

* Enhance booking features by integrating booking audit functionality

- Updated the booking page to retrieve user feature statuses for "bookings-v3" and "booking-audit".
- Modified BookingDetailsSheet and BookingListContainer components to accept and utilize the new bookingAuditEnabled prop.
- Adjusted the BookingHistory display logic to conditionally render based on the bookingAuditEnabled state.
- Refactored SegmentedControl to support generic types for better type safety.

This change improves the user experience by allowing conditional access to booking audit features based on user permissions.

* Refactor BookingDetailsSheet to manage active segment state with Zustand store

- Removed local state management for active segment in BookingDetailsSheet and integrated Zustand store for better state synchronization.
- Introduced useActiveSegmentFromUrl hook to sync active segment with URL query parameters.
- Updated BookingDetailsSheet to handle derived active segment logic based on bookingAuditEnabled state.
- Adjusted SegmentedControl to ensure it defaults to "info" when activeSegment is null.

This refactor enhances the maintainability and responsiveness of the booking details component.

* refactor: rename useBiDirectionalSyncBetweenZustandAndNuqs to useBiDirectionalSyncBetweenStoreAndUrl

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

---------

Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-05 16:21:35 +05:30
Anik Dhabal BabuandGitHub acee514c42 fix: show empty screen from event type availability tab (#26396)
* fix

* update

* fix

* Remove copying of App Store static files step

Removed step to copy App Store static files from the workflow.
2026-01-05 10:40:14 +05:30
3704324474 feat: update translations via @LingoDotDev (#26340)
Co-authored-by: Lingo.dev <support@lingo.dev>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2025-12-31 13:31:47 +00:00
spandevandGitHub 11150309d4 fix: added message in schedule bulk update (#26334) 2025-12-31 10:02:40 +00:00
d3e5cfb311 feat: update translations via @LingoDotDev (#26313)
Co-authored-by: Lingo.dev <support@lingo.dev>
2025-12-30 14:29:47 +00:00
Joe Au-YeungGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Udit TakkarSyed Ali Shahbaz
2b61bddf7b feat: add completed onboarding column to organization members table (#25582)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
2025-12-30 10:57:49 -03:00
1c6f5d9ec0 feat: update translations via @LingoDotDev (#26219)
Co-authored-by: Lingo.dev <support@lingo.dev>
2025-12-29 02:18:32 +00:00
Syed Ali ShahbazandGitHub 0b7f51410a chore: Add webhook version documentation link to webapp (#26121)
* init

* further improvement
2025-12-22 10:22:41 +00:00
Pedro CastroandGitHub 9ae2381755 fix(auth): validate IdP authority before SAML account linking (#26005)
* fix(auth): validate IdP authority before SAML account linking

Adds verification that SAML IdP is authoritative for the email domain
before allowing account conversion

* fix(auth): deny by default on missing SAML tenant + optimize membership query

 - Block account conversion when tenant is missing (deny by default)
 - Replace JOIN + ILIKE with two indexed lookups for O(1) performance

* refactor(auth): apply data minimization to security logs
2025-12-20 17:45:18 +00:00
Benny JooandGitHub 6e5b812286 fix: add missing Korean translation (#26075) 2025-12-20 15:02:03 +05:30
Alex van AndelGitHubcubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
8568cab283 fix: Handle error when no default calendar exists for a o365 account (#26074)
* fix: Handle error when no default calendar exists for a o365 account

* Update packages/app-store/office365calendar/api/callback.ts

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

---------

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-12-20 06:33:46 +00:00
Peer RichelsenGitHubpeer@cal.com <peer@cal.com>peer@cal.com <peer@cal.com>peer@cal.com <peer@cal.com>peer@cal.com <peer@cal.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
125ed4f6f7 feat: update favicons with new Cal design (#25392)
* feat: add environment-based favicons (prod vs dev)

- Add cal-prod.png (dark/gray) favicon for production environments
- Add cal-dev.png (red) favicon for development/localhost environments
- Update FAVICON_16 and FAVICON_32 constants to switch based on IS_PRODUCTION

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

* feat: add higher resolution icons for all icon types (apple-touch, android-chrome, mstile)

- Add 180x180 apple-touch-icon for prod and dev
- Add 150x150 mstile icons for prod and dev
- Add 192x192 and 256x256 android-chrome icons for prod and dev
- Update all icon constants to use IS_PRODUCTION switching

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

* refactor: simplify favicon to single new design

- Remove environment-based favicon switching
- Update all icon files with new Cal favicon design
- Remove dev/prod icon variants
- Update constants to use static icon paths

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

* feat: add favicon.ico with new Cal favicon design

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

* chore: update favicon icons with final design

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

* chore: update favicon icons with final design v3

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

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-12-19 13:12:14 +00:00
3423777ee3 feat: gmail, outlook, yahoo links during email verification (#26038)
* added gmail, outlook, yahoo links during email verification

* added proton

* enable for self-hosters too

* undo i18n

* Discard changes to companion/bun.lock

* nit

* refactor: code quality improvments

---------

Co-authored-by: Dhairyashil <dhairyashil10101010@gmail.com>
2025-12-18 19:56:38 +00:00
975fb21d86 feat(atoms): add ListEventTypes atom to enable event type management (#25047) (#25113)
* feat: add ListEventTypes atom (#25047)

* feat: add ListEventTypes atom for Platform (#25047)

- Add EventTypeListItem component in @calcom/features
- Add ListEventTypesPlatformWrapper with delete functionality
- Implement useAtomGetAllEventTypes hook
- Update backend to include slug, description, length
- Add 11 unit tests (65% coverage)
- Add 3 i18n keys

No breaking changes. Backward compatible.

* refactor(eventtypes): improve EventTypeListItem readability

- Extract EventTypeContent and EventTypeActions sub-components
- Add formatEventTypeDuration helper (90min → '1h 30m')
- Use Badge for duration display (consistency with EventTypeDescription)
- Use polymorphic Wrapper component (DRY)
- Add comprehensive tests
- Reduce main component size

Addresses @volnei feedback

* refactor: replace window.confirm with ConfirmationDialog

- Replace native window.confirm with ConfirmationDialogContent

- Update test mocks for Dialog components

- Fix HTML nesting (div instead of p for Badge container)

- Follows Cal.com pattern from AvailabilitySettings

Addresses @ThyMinimalDev feedback

* fix: add aria-label to options button for accessibility

* test: update getBulkEventTypes test to include new fields (description, slug, length)

* refactor: move EventTypeListItem to atoms package

---------

Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
2025-12-18 12:24:41 -03:00
Hariom BalharaGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
f1011ddd08 chore: Improves the core booking audit architecture by adding new capabilities and simplifying the existing interfaces. (#25872)
* feat(booking-audit): extract core audit system changes from PR 25125

This PR extracts core audit infrastructure changes without integration changes:

1. New action services introduced:
   - SeatBookedAuditActionService
   - SeatRescheduledAuditActionService

2. Simplification of ActionService interface:
   - Streamlined IAuditActionService interface
   - Reduced TypeScript burden with cleaner type definitions

3. ActionSource support:
   - Added BookingAuditSource enum (API_V1, API_V2, WEBAPP, WEBHOOK, UNKNOWN)
   - Added source and operationId fields to BookingAudit model

4. New AuditAction types:
   - SEAT_BOOKED
   - SEAT_RESCHEDULED
   - APP actor type

5. New BookingAuditAccessService:
   - Permission-based access control for audit logs
   - Added readTeamAuditLogs and readOrgAuditLogs permissions

6. Fixes in the logs viewer flow:
   - Enhanced BookingAuditViewerService with improved filtering
   - Local AttendeeRepository for actor enrichment

Changes are contained within packages/features/booking-audit with minimal
outside changes (permission registry only).

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

* refactor(booking-audit): streamline action handling and enhance localization

- Replaced action icon retrieval with a mapping object for improved clarity and performance.
- Introduced constants for actor role labels to simplify role retrieval.
- Added new localization strings for audit log permission errors and organization requirements.
- Updated various service and repository interfaces to enhance type safety and clarity.
- Removed deprecated architecture documentation and adjusted related imports for consistency.

These changes aim to improve code maintainability and user experience in the booking audit system.

* fix(booking-audit): enhance actor role localization and operation ID tracking

- Updated actor role labels in the booking logs view to use lowercase for consistency.
- Improved localization by wrapping actor role display in a translation function.
- Added operationId field to audit logs for better correlation of actions across multiple bookings.
- Enhanced BookingAuditViewerService to include operationId in enriched audit logs.
- Updated integration tests to verify consistent operationId across related audit logs.

These changes aim to improve localization accuracy and facilitate better tracking of user actions in the booking audit system.

* feat: integrate credential repository and enhance app actor handling

- Added CredentialRepository to manage app credentials, including a method to find credentials by ID.
- Updated BookingAudit system to support app actors identified by credential ID, improving actor attribution and audit clarity.
- Introduced a new utility function to map app slugs to display names, enhancing the user experience in audit logs.
- Modified relevant interfaces and types to accommodate the new credential handling and app actor structure.
- Enhanced BookingAuditViewerService to display app names based on credentials, ensuring accurate representation in audit logs.

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-12-18 12:46:24 +00:00
Syed Ali ShahbazandGitHub 056922b6ee feat: add webhook versioning (#23861)
* add webhook version schema

* version the code

* update version from numeric to date val

* migration

* update schema and build factory

* update string

* move version picker

* tooltip instead of infobadge

* --

* fix type

* --

* fix type

* fix type

* --

* fix messed up merge

* improvements to payloadfactory

* extract version off of DB and instead keep it in IWebhookRepository

* fix webhookform

* fix type safety and routing ambiguity

* scalable with easier factory extensions and base definition

* fix types

* --

* --

* clean up prisma/client type imports

* fix

* type fix

* type fix

* cleanup

* add tests and registry changes

* unintended file inclusion

* type-fix

* select in repo

* --

* explicit return type

* --

* fix type

* fixes

* feedback 1

* feedback 2

* use enum instead of string

* fixes
2025-12-18 09:36:22 +02:00
Calcom BotandGitHub c20f6cbdd6 feat: update translations via @LingoDotDev (#24385)
Hey team,

[**Lingo.dev**](https://lingo.dev) here with fresh translations!

### In this update

- Added missing translations
- Performed brand voice, context and glossary checks
- Enhanced translations using Lingo.dev Localization Engine

### Next Steps

- [x] Review the changes
- [x] Merge when ready
2025-12-17 13:30:35 -03:00
Dhairyashil ShindeandGitHub 12e07f20d4 feat: Add Holidays feature to block availability on public holidays (#25561)
* feat: add holidays feature for automatic availability blocking- Add UserHolidaySettings model for storing user preferences- Generate static holiday data for 20 countries using date-holidays- Create HolidayService for runtime holiday queries- Add TRPC router with endpoints for country selection and holiday toggles- Create Holidays tab UI in Availability page with conflict warnings- Integrate holiday blocking into getUserAvailability calculation- Show holiday indicator on blocked dates in booker page- Add warning in OOO modal when dates overlap with holidays

* feat: add optimizations, tests, and code quality improvements

- Add memoization/caching to HolidayService for better performance
- Optimize checkConflicts DB query with OR conditions for specific dates
- Add HolidayService unit tests (10 tests)
- Add error handling with Alert component for failed queries
- Memoize HolidayListItem component to prevent unnecessary re-renders
- Extract magic numbers into constants.ts
- Use TRPCError consistently in handlers
- Add missing i18n keys for error messages
- Update handlers to follow Cal.com patterns (default exports, minimal comments)
- Add regeneration instructions in constants

* refactor: replace static JSON with Google Calendar API integration

- Add GoogleHolidayService to fetch holidays from Google Calendar public calendars
- Add HolidayCache Prisma model for caching API responses
- Add GOOGLE_CALENDAR_API_KEY and HOLIDAY_CACHE_DAYS env variables
- Support 38 countries via Google Calendar holiday calendars
- Update HolidayService methods to async with database caching
- Update all TRPC handlers for async holiday methods
- Fix UI to display holiday dates correctly
- Remove static holidays.json and generate script

* use we instead of calcom in i18n message

* address cubics comments

* move holidays from availability to ooo

* public holidays filter for holidays

* follow i18n _one and _other pattern

* remove holiday feature flag

* revert lint command code change

* revert lint command code change 2.0

* revert lint command code change 3.0

* bye bye my christmas emoji :crying-emoji

* remove comments

* refactor(holidays): add repository pattern, split services, and add tests

- Create HolidayRepository for database operations
- Split GoogleHolidayService into GoogleCalendarClient and HolidayCacheService
- Add dependency injection to HolidayService and HolidayCacheService
- Update TRPC handlers to use HolidayRepository
- Add tests for HolidayRepository and calculateHolidayBlockedDates
- Update calendar IDs to use official holiday format (244 countries + religions)

* fix: address PR review feedback

- Remove unused date-holidays package
- Add pluralization for and_more_holidays_with_conflicts translation
- DRY: spread GOOGLE_RELIGIOUS_HOLIDAY_CALENDARS into GOOGLE_HOLIDAY_CALENDARS
- Add select to userHolidaySettings query in getUserAvailability
- Optimize checkConflicts with pre-computed timestamps

* refactor(holidays): apply proxy pattern and move logic to service

- Rename HolidayCacheService to HolidayServiceCachingProxy (proxy pattern)
- Remove HOLIDAY_CACHE_DAYS env var, use constant directly
- Add isSupportedCountry() method to HolidayService
- Add getUserSettings() and updateSettings() to HolidayService
- Move toggleHoliday logic from handler to service
- Move checkConflicts logic from handler to service
- Add findBookingsInDateRanges() to HolidayRepository
- Simplify all handlers to just call service methods

* feat(bookings): add backend validation to prevent booking on holidays

Adds explicit holiday conflict validation during booking creation to
handle the race condition where a host enables a holiday after a guest
selects a date but before they submit the booking.

Changes:
- Add checkHolidayConflict validation with HolidayRepository integration
- Integrate ensureNoHolidayConflict in RegularBookingService
- Add BookingOnHoliday error code with proper HTTP 400 response
- Handle holiday error display in BookEventForm with name interpolation
- Hide trace ID for expected validation errors
- Add unit tests for holiday conflict validation

* fix failing type check

* fix: address PR review comments for holiday feature

- Change error code from BAD_REQUEST to INTERNAL_SERVER_ERROR in
  toggleHoliday handler (errors are internal failures, not bad input)
- Refactor ensureNoHolidayConflict to use Promise.all for parallel
  user checking instead of sequential loop

* refactor: use Promise.all with logging in loop for holiday check

- Check all users in parallel using Promise.all
- Log conflicts inside the loop as they are detected
- Wait for all checks to complete before throwing error

* fix(holidays): use host timezone for holiday conflict checks

The holiday feature was checking booking dates against holidays using
server/local timezone instead of the host's timezone. This caused
bookings near midnight boundaries to incorrectly pass or fail the
holiday check.

Example: A booking at Dec 24th 8PM UTC (which is Dec 25th in IST)
was not being blocked for an Indian host with Christmas as a holiday.

Changes:
- Add .utc() to holiday date formatting for consistency
- Fetch host's timezone in checkHolidayConflict
- Convert booking time to host's timezone before comparison
- Add findUserSettingsWithTimezone to HolidayRepository
- Update error message to clarify it's the host's local time
- Add timezone edge case tests

* fix(holidays): align holiday blocking with OOO pattern for consistent timezone handling

- Simplify calculateHolidayBlockedDates to match OOO pattern using dayjs.utc()
- Fix date range query to use full day bounds (startOfDay/endOfDay) so holidays
  stored at midnight UTC are correctly found during booking validation
- Remove separate checkHolidayConflict booking-time validation - holidays now
  block through oooExcludedDateRanges like OOO does
- Remove getHolidayOnDate from HolidayService (no longer needed)
- Remove findUserSettingsWithTimezone from HolidayRepository (no longer needed)
- Clean up related tests

Holiday blocking now works exactly like OOO:
1. Holidays are added to datesOutOfOffice in calculateHolidayBlockedDates
2. buildDateRanges processes them via processOOO with .tz(timeZone, true)
3. oooExcludedDateRanges excludes those dates from availability
4. ensureAvailableUsers uses oooExcludedDateRanges to block bookings

This ensures consistent timezone handling where Dec 25th blocks all hours
of Dec 25th in the host's timezone, regardless of booker's timezone.

* update test

* update .env.example file
2025-12-15 16:39:10 +00:00
Hariom BalharaGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Udit Takkar
2218a45d83 feat: extract core booking audit infrastructure from PR 25125 (#25729)
* feat: extract core booking audit infrastructure from PR 25125

This PR contains only the core booking audit infrastructure changes from PR 25125,
excluding integration changes with booking flows.

Included:
- All packages/features/booking-audit/* (core audit services, actions, repository)
- packages/features/di/containers/BookingAuditViewerService.container.ts
- packages/features/tasker/tasker.ts (audit task types)
- packages/features/bookings/lib/types/actor.ts (actor types for audit)
- packages/features/bookings/repositories/BookingRepository.ts (getFromRescheduleUid method)
- apps/web/modules/booking/logs/views/booking-logs-view.tsx (UI for viewing audit logs)
- apps/web/public/static/locales/en/common.json (translations)

Excluded (integration changes):
- packages/trpc/server/* (tRPC handlers)
- packages/features/ee/round-robin/* (round-robin integration)
- packages/features/bookings/lib/handleCancelBooking.ts
- packages/features/bookings/lib/handleConfirmation.ts
- packages/features/bookings/lib/onBookingEvents/BookingEventHandlerService.ts
- packages/features/bookings/lib/service/RegularBookingService.ts
- apps/api/v2/* (API v2 integration)

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

* fix: make booking audit interfaces backwards-compatible with main

- Add queueAudit method back to BookingAuditProducerService interface for backwards compatibility
- Implement queueAudit method in BookingAuditTaskerProducerService
- Make userTimeZone parameter optional in BookingAuditViewerService
- Add BookingAuditTaskProducerActionData type for legacy queueAudit method
- Use any generics in BookingAuditActionServiceRegistry (matching PR 25125)
- Fix type assertions in BookingAuditTaskConsumer

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

* fix switch eslint and ts

* feat: enhance BookingAuditViewerService with logging and type improvements

- Added ISimpleLogger dependency to BookingAuditViewerService for better error handling.
- Updated actor type in enriched audit logs to use AuditActorType for improved type safety.
- Replaced console.error with logger for error reporting when no rescheduled log is found.

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2025-12-15 10:51:30 +00:00
Peer RichelsenandGitHub 411483a447 added OAuth badges (#25830) 2025-12-12 17:11:21 +00:00
sean-brydonandGitHub b46fb82695 feat: minium reschedule notice on events (#25575)
* wip

* add i18n and essential tests

* fix UI and add migration

* fixes

* add logic on book event

* restore comment

* remove dev debug box

* extract min reschedule notice to util

* one more replace

* add to disable reschedule component

* tidy up state

* restore lock

* restore file

* fix zod utils

* respond to cubic feedback

* fix type error

* unit tests

* add zod util

* build tests with nul minReshceuldeNotice

* fix stuff
2025-12-12 10:53:01 -03:00
Kartik LabhshetwarGitHubcubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
8dc8d87ad0 feat: add time shift badge for recurring events with shifted local times (#25568)
* feat: highlight recurring bookings with time shift badge across DST

* Update packages/lib/__tests__/timeShift.test.ts

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

* refactor: show time shift badge only on first shift in bookings view and occurrences

* refactor: update recurring bookings display logic and wrap booking title text

* refactor: add getFirstShiftFlags helper for time shift flags and update components

---------

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-12-11 20:18:00 +00:00
Udit TakkarandGitHub da4fec9c27 chore: add missing translation (#25753) 2025-12-12 01:45:43 +05:30
Dhairyashil ShindeandGitHub 26b4385679 feat: Add public OOO notes display on booking pages (#25471)
* feat: ooo message on booking page

* make ooo days selectable even when no redirect booking

* handle long notes

* remove unused i18n key

* Private notes stay private on the server, No accidental data leaks through client-side payloads

* address cubics comments

* fix: replace toggle with checkbox for OOO note visibility

- Replace Switch with Checkbox for "show note publicly" option
- Remove "OOO Message:" prefix from displayed notes on booking page
- Update i18n text to "Show note on public booking page"
- Remove unused ooo_message i18n key

* fix the accessibility issue by using proper htmlFor and id association

* only allow selecting OOO dates when the note is public
2025-12-11 11:31:59 +00:00