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>
* refactor: move WebWrapper files from packages/platform to apps/web/modules
Move the following WebWrapper files to their appropriate locations in apps/web/modules:
- EventTypeWebWrapper and related tab wrappers to apps/web/modules/event-types/components/wrappers/
- BookerWebWrapper to apps/web/modules/bookings/components/
- ConferencingAppsViewWebWrapper to apps/web/modules/apps/components/
- SelectedCalendarsSettingsWebWrapper to apps/web/modules/calendars/components/
- AddMembersWithSwitchWebWrapper to apps/web/modules/event-types/components/
This reduces the number of files in packages/platform that import from @calcom/web,
improving the separation between platform and web-specific code.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: move web-specific hooks to apps/web and update imports
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* fix
* fix
* fix
* fix
* fix
* fix
* fix
* add back comments
* fix
* fix
* fix
* fix
* fix: correct relative import paths in moved WebWrapper files
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* final
* fix: use package alias for event-type hooks instead of deeply nested relative paths
- Move sortHosts function to @calcom/lib/bookings/hostGroupUtils.ts for shared access
- Add exports for useEventTypeForm, useHandleRouteChange, useTabsNavigations to @calcom/atoms package.json
- Update EventTypeWebWrapper.tsx to use @calcom/atoms package alias instead of ../../../../../packages/... paths
- Update useEventTypeForm.ts to import sortHosts from @calcom/lib instead of @calcom/web
- Re-export sortHosts from HostEditDialogs.tsx for backward compatibility
This addresses the Cubic AI review feedback about fragile deeply nested relative paths that bypass proper package resolution.
Co-Authored-By: unknown <>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* 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>
* 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>
* 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
Pasquale VitielloGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>pasquale@cal.com <pasquale@cal.com>Rajiv Sahal
* fix: improve cleanup for managed event types in e2e tests
- Add deleteAllUserEventTypes method to EventTypesRepositoryFixture
- Update afterAll cleanup to delete user event types before deleting users
- This ensures child event types of managed event types are properly cleaned up
- Fixes flaky tests caused by incomplete cleanup between test runs
- Add explicit return types to fixture methods to satisfy lint rules
- Replace @ts-ignore with @ts-expect-error for better type safety
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* fix
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
## What does this PR do?
Adds audit logging for the reschedule request flow. When an organizer requests an attendee to reschedule a booking, this action is now logged to the booking audit system.
This is part of the booking audit integration effort, following the pattern established in PR #26046 (booking creation/rescheduling audit) and PR #26458 (cancellation audit).
## Changes
- Added audit logging call to `requestReschedule.handler.ts` using `BookingEventHandlerService.onRescheduleRequested()`
- Captures audit data:
- `rescheduleReason`: The reason provided for requesting the reschedule (nullable string)
- `rescheduledRequestedBy`: Email of the user who requested the reschedule
- Uses `makeUserActor(user.uuid)` to identify the actor performing the action
- Added required `source` parameter for action source tracking (passed as `"WEBAPP"` from tRPC router)
- Updated `RescheduleRequestedAuditActionService` schema to use simpler field structure
- Updated test helper `getTrpcHandlerData` to pass `source: "WEBAPP"` parameter
## Updates since last revision
- Changed `source` parameter from optional with default to required - tests now explicitly pass `source: "WEBAPP"` instead of relying on a default value
## 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. N/A - follows established audit pattern with existing infrastructure tests.
## How should this be tested?
1. Log in as a user with a booking
2. Navigate to the booking and click "Request Reschedule"
3. Provide a reschedule reason and submit
4. Verify the audit log is created with the correct data (requires access to audit log storage/database)
The audit logging follows the same pattern as other booking audit integrations, so if those are working, this should work as well.
## Checklist
- [x] My code follows the style guidelines of this project
- [x] I have checked if my changes generate no new warnings
---
**Link to Devin run**: https://app.devin.ai/sessions/ae84d093c4594a5d89b88c45639a6a06
**Requested by**: @hariombalhara
## Human Review Checklist
- [ ] Verify the audit data schema matches `RescheduleRequestedAuditActionService` expectations (fields: `rescheduleReason`, `rescheduledRequestedBy`)
- [ ] Confirm the schema change from change-based fields (`{ old, new }`) to simple nullable strings is intentional
- [ ] Confirm `user.uuid` is available in the tRPC session context
- [ ] Note: API v2 does not have a reschedule request endpoint, so no API v2 changes are needed
* fix(auth): add URL validation for organization logo fields
- Add URL validation utility for server-side fetched URLs
- Validate logo URLs in tRPC organization schema
- Validate logo URLs in API v2 team DTOs
- Add graceful fallback in logo route for invalid URLs
- Only allow HTTPS and image data URLs
- Add unit tests for URL validation
* fix: add missing IP range and type validation
- Add RFC 6598 CGNAT range (100.64.0.0/10) to blocked IPs
- Add @IsString() decorator before custom URL validators
- Add boundary tests for new IP range
* fix: address review feedback
- Export validateUrlForSSRFSync via @calcom/platform-libraries
- Fix nullable/optional order in Zod schema
* fix: block localhost hostname and explicit null check
- Add localhost to BLOCKED_HOSTNAMES for sync validation
- Use explicit null check (url == null) instead of falsy check
* fix: allow empty string in URL validation
* refactor: extract shared validation logic
- Extract validateUrlCore() to eliminate duplication between sync/async versions
- Add JSDoc to all exported functions for better discoverability
- Remove redundant comments that repeated function names
- Simplify existing comments to be more concise
* fix: reject empty strings in URL validator
Previously if (!url) allowed empty strings to bypass validation.
Now explicitly checks for null/undefined only
2026-01-08 22:03:54 +00:00
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: Add email verification requirement for API v1 and v2 email updates
- API v2 (/v2/me): Implement email verification check when updating primary email
- Store new email in metadata as emailChangeWaitingForVerification when verification is required
- Send verification email using sendChangeOfEmailVerification
- Allow immediate email change if new email is already a verified secondary email
- Add hasEmailBeenChanged and sendEmailVerification flags to response
- Add tests to verify email verification behavior
- Add findVerifiedSecondaryEmail method to UsersRepository
- Add PrismaFeaturesRepository to MeModule providers
- API v1 (/v1/users/{userId}): Implement same email verification logic
- Check if email-verification feature flag is enabled
- Store new email in metadata when verification is required
- Send verification email for unverified email changes
- Allow immediate change for verified secondary emails
- Preserve existing API v1 response format
- Test fixtures: Add createSecondaryEmail method to UserRepositoryFixture
This fixes the vulnerability where users could update their primary email
without verification via API endpoints.
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* update
* update
* refactor: Extract business logic to MeService and add platform-managed bypass
- Create MeService with all business logic extracted from MeController
- Update MeController to delegate to MeService (thin controller pattern)
- Add PrismaWorkerModule to MeModule imports to provide PrismaWriteService
- Add isPlatformManaged bypass: platform-managed users can update email without verification
- Fix test cleanup to use delete by ID instead of email to avoid failures when email changes
- Remove hasEmailBeenChanged and sendEmailVerification response flags per reviewer feedback
- Add comprehensive documentation to @ApiOperation describing email verification behavior
- Update tests to remove flag assertions
Addresses PR comments:
- supalarry: Extract logic to service layer
- supalarry: Allow platform-managed users to update email without verification
- supalarry: Remove response flags and document behavior in @ApiOperation instead
- cubic-dev-ai: Fix module dependency for PrismaFeaturesRepository
- cubic-dev-ai: Fix test cleanup issue
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* docs: Simplify API operation description
Remove internal implementation details about metadata staging and shorten the description to focus on API consumer behavior.
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* fix
* update
* update
* update
* remove comment
* addressed commit
* review addressed
* use repository
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-08 15:51:11 +00:00
Eunjae LeeGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: First high level changes to getUsersAvailability
* Fix usage of getUserAvailability where getUsersAvailability is unused
* Fix user.schema.ts in APIv2
* User handler did not provide initial data
* Small ts fixes
* Set user non-nullable in getTimezoneFromDelegatedCredential
* Small ts fixes, ensure consumers are aware its nonnullable
* Mode is defaulted to none
* Mode is defaulted to none, fix ts when directly using fn (temp)
* test: add e2e test for workflow partial update time/timeUnit preservation
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: time and timeUnit partial update workflows api v2
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-08 09:26:55 -03:00
MorganGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: set attendeeSeatId in evt for seated booking reschedule emails
When an attendee reschedules a seated booking, the reschedule/cancel links
in emails were using bookingUid instead of seatUid after the first reschedule.
This was because evt.attendeeSeatId was not being set before sending the email.
This fix ensures that evt.attendeeSeatId is set to bookingSeat.referenceUid
so that the email links consistently use seatUid for seated bookings.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* test: add E2E test for seatUid preservation across multiple reschedules
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: use valid time slots within availability window for E2E test
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: make E2E test self-contained to avoid shared state issues
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: update E2E test to validate seatUid usability across reschedules
Co-Authored-By: morgan@cal.com <morgan@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-08 14:15:40 +02:00
Volnei MunhozGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* refactor: replace shouldServeCache with mode parameter for calendar cache control
Replace the boolean shouldServeCache parameter with a new CalendarFetchMode type
that can have values 'slots', 'overlay', and 'booking'. This provides better
control over when to serve cache vs relay on calendar providers.
- 'slots' mode: Check feature flags and use cache when available (for getting
actual calendar availability)
- 'overlay' mode: Don't use cache (for overlay calendar availability)
- 'booking' mode: Don't use cache (for booking confirmation)
- undefined: Same as 'slots' for backwards compatibility
The cache decision logic is now centralized in getCalendar.ts based on the mode
parameter.
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: update CalendarService.test.ts to use mode parameter
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* refactor: use shared GetAvailabilityParams type across all calendar services
- Import GetAvailabilityParams and GetAvailabilityWithTimeZonesParams from @calcom/types/Calendar
- Replace inline type definitions with shared types in all calendar service implementations
- Update BaseCalendarService, CalendarCacheWrapper, and CalendarTelemetryWrapper
- Ensures consistent typing and follows DRY principles
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: add missing IntegrationCalendar import and update mock getAvailability signature
- Add IntegrationCalendar back to sendgrid CalendarService imports
- Update bookingScenario mock getAvailability to use typed params object
- Add listCalendars method to mock Calendar object
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: update test files to use typed params object for getAvailability methods
- Update CalendarCacheWrapper.test.ts to call getAvailability/getAvailabilityWithTimeZones with params object
- Update getCalendarsEvents.test.ts toHaveBeenCalledWith assertions to expect params object
- All 32 tests now pass
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* refactor: consolidate to single GetAvailabilityParams type for both getAvailability methods
- Remove GetAvailabilityWithTimeZonesParams, use GetAvailabilityParams for both methods
- Add mode parameter to getAvailabilityWithTimeZones calls
- Update wrapper classes to pass mode through to underlying calendar
- Update test files to include mode in getAvailabilityWithTimeZones calls and assertions
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* refactor: use EventBusyDate with optional timeZone for getAvailabilityWithTimeZones
- Add optional timeZone field to EventBusyDate type
- Update getAvailabilityWithTimeZones return type to use EventBusyDate[]
- Update Google Calendar service and wrapper classes to use the new type
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: type errors and remove unused calendar watching methods
- Fix type errors in CalendarCacheWrapper.ts (convert null to undefined for timeZone)
- Fix type errors in getCalendarsEvents.ts (ensure timeZone is always present)
- Remove unused watchCalendar/unwatchCalendar from Calendar interface
- Remove unused startWatchingCalendarsInGoogle/stopWatchingCalendarsInGoogle from GoogleCalendarService
- Remove unused imports (uuid, uniqueBy, GOOGLE_WEBHOOK_URL, ONE_MONTH_IN_MS)
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: remove watchCalendar/unwatchCalendar from CalendarTelemetryWrapper
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* refactor: remove verbose JSDoc param comments from wrapper classes
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* refactor: make mode parameter required in getCalendar
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: add required mode parameter to all getCalendar callers
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: provide default mode value in getBusyCalendarTimes
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: add mode parameter to remaining getCalendar callers
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: add mode parameter to vital and wipemycalother reschedule
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: add mode parameter to credential-sync API endpoint
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* refactor: add 'none' mode to CalendarFetchMode and use as default
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* test: add mode parameter to getCalendarsEvents test calls
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* Update packages/app-store/delegationCredential.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-08 09:07:41 -03:00
Syed Ali ShahbazGitHubcubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Refactors the link and verify-booking-token API routes to call confirmHandler directly instead of using the tRPC caller pattern. This simplifies the code by removing the need for session getter, legacy request building, and context creation.
Changes:
- apps/web/app/api/link/route.ts: Use confirmHandler directly with ctx and input
- apps/web/app/api/verify-booking-token/route.ts: Use confirmHandler directly with ctx and input
- Updated tests to mock confirmHandler instead of tRPC caller
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-08 08:23:48 +00:00
Benny JooGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: remove @calcom/web imports from packages/features to eliminate circular dependency
- Migrate UserTableUser and MemberPermissions types to packages/features/users/types/user-table.ts
- Migrate useGeo hook to packages/features/geo/GeoContext.tsx
- Migrate buildLegacyRequest to packages/lib/buildLegacyCtx.ts
- Migrate Calendar component to packages/features/calendars/weeklyview/components/
- Move test utilities (bookingScenario, fixtures) to packages/features/test/
- Update all imports in packages/features to use new locations
- Add re-exports in apps/web for backward compatibility
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: delete original implementation files and fix type issues
- Delete original calendar component files in apps/web (keep only re-export stubs)
- Migrate OutOfOfficeInSlots to packages/features/bookings/components
- Convert apps/web OutOfOfficeInSlots to re-export stub
- Fix className vs class issue in Calendar.tsx
- Fix @calcom/trpc import violation in user-table.ts by using structural type
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: add missing isGroup and contains fields to UserTableUser attributes type
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update customRole type to match actual Prisma Role model
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix build
* fix
* fix
* cleanup weeklyview
* fix
* refactor to mv MemberPermissions to types package
* add types dependency to features
* fix
* fix
* fix
* fix
* fix
* fix
* rename
* rename
* migrate
* migrate
* migrate
* fix
* fix
* fix
* refactor: move test utilities from packages/features/test to tests/libs
- Move bookingScenario utilities to tests/libs/bookingScenario
- Move fixtures to tests/libs/fixtures
- Update all imports in packages/features test files to use new location
- Update all imports in apps/web test files to use new location
- Eliminates duplication of test utilities between packages/features and apps/web
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: correct relative import paths for tests/libs in test files
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: replace test utility implementations with re-exports to tests/libs
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: fix test import paths and move signup handler tests to apps/web
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: move buildLegacyCtx to packages/lib and restore handlers to packages/features
- Move buildLegacyCtx from apps/web/lib to packages/lib to break circular dependency
- Update apps/web/lib/buildLegacyCtx.ts to re-export from @calcom/lib
- Restore signup handlers and tests to packages/features/auth/signup/handlers
- Update handler imports to use @calcom/lib/buildLegacyCtx instead of @calcom/web/lib/buildLegacyCtx
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update recurring-event.test.ts imports to use tests/libs path
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: delete test re-export files and update imports to use tests/libs directly
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update remaining test imports to use tests/libs directly
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update handleRecurringEventBooking calls to match function signature (1 arg)
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* remove
* migrate tests
* migrate tests
* refactor: update test mock imports by removing and using async for mock creators.
* fix type errors
* fix: add type assertion for MockUser in p2002.test-suite.ts
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: restore locale import in compareReminderBodyToTemplate.test.ts using relative path
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* feat: create @calcom/testing package and migrate tests from /tests directory
- Created new @calcom/testing package in /packages/testing
- Moved all files from /tests to /packages/testing
- Updated all imports across the codebase to use @calcom/testing alias
- Removed /tests directory at root level
This allows other packages like @calcom/features and @calcom/web to import
testing utilities using the @calcom/testing alias instead of relative paths.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* fix
* fix: add missing useBookings export to @calcom/atoms package
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: add missing useCalendarsBusyTimes and useConnectedCalendars exports to @calcom/atoms
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* chore: add @calcom/testing as explicit devDependency to packages that use it
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: move setupVitest.ts into @calcom/testing package
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* chore: add biome rules to restrict @calcom/testing imports
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* rename libs to lib
* rename libs to lib
* add rule
* add rule
* refactor: remove @calcom/features imports from @calcom/testing
- Move mockPaymentSuccessWebhookFromStripe to fresh-booking.test.ts
- Replace ProfileRepository.generateProfileUid() with uuidv4()
- Clone Tracking type into @calcom/testing/src/lib/types.ts
- Update imports in expects.ts and getMockRequestDataForBooking.ts
- Move source files into src/ folder
- Move CalendarManager mock to @calcom/features
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: add explicit exports for nested paths in @calcom/testing
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* improve
* improve
* fix
* fix
* fix type checks
* fix type checks
* fix type checks
* fix tests
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
gray-matter uses yaml.safeLoad() which was removed in js-yaml 4.x, causing 500
errors on app store pages after the js-yaml 4.1.1 update (CWE-1321 fix)
- Add parseFrontmatter function using yaml.load with JSON_SCHEMA
- Add type guard for safe type narrowing
- Add unit tests for frontmatter parsing and security
- Remove gray-matter dependency
* feat: api v2 add missing event type fields for advanced settings
Add 9 event type fields to API v2 that were available in tRPC but missing from the platform API:
- disableCancelling: disable cancelling for guests/organizer
- disableRescheduling: disable rescheduling for guests/organizer
- canSendCalVideoTranscriptionEmails: send Cal Video transcription emails
- autoTranslateInstantMeetingTitleEnabled: auto-translate instant meeting titles
- interfaceLanguage: preferred booking interface language
- allowReschedulingPastBookings: allow rescheduling past events
- allowReschedulingCancelledBookings: allow booking via reschedule link
- customReplyToEmail: custom reply-to email for confirmations
- showOptimizedSlots: optimize time slot arrangement
Updated output/input schemas, transformation services, and E2E tests.
* fix(api-v2): add proper OpenAPI types for nullable event type fields
Add explicit type and nullable properties to @ApiPropertyOptional decorators
for fields with `boolean | null` or `string | null` types. Without these,
Swagger was generating incorrect "type": "object" instead of the correct types.
Fixed fields:
- disableCancelling: type: Boolean, nullable: true
- disableRescheduling: type: Boolean, nullable: true
- interfaceLanguage: type: String, nullable: true
- allowReschedulingCancelledBookings: type: Boolean, nullable: true
- customReplyToEmail: type: String, nullable: true
- showOptimizedSlots: type: Boolean, nullable: true
* refactor: customReplyToEmail was intentionally excluded from this PR. The web UI
restricts this field to only allow the user's own verified emails via a
dropdown, but implementing the same validation in the API requires additional
business logic. This will be addressed in a separate PR with proper email
ownership validation.
* feat(api-v2): add validation for interfaceLanguage field
Add @IsIn validation to interfaceLanguage field to only accept supported
locales. This ensures API v2 matches the web UI behavior where users can
only select from a predefined dropdown of supported languages.
Changes:
- Add SUPPORTED_LOCALES constant to @calcom/platform-constants
- Add @IsIn([...SUPPORTED_LOCALES]) validation to create/update DTOs
- Add E2E tests for invalid locale rejection (400 error)
- Add cross-reference comments in i18n.json and api.ts to keep in sync
* docs(api): add default values to event type input field documentation
Added default value documentation to @DocsPropertyOptional decorators
for the new event type fields in API v2 (2024_06_14):
- disableCancelling: false
- disableRescheduling: false
- canSendCalVideoTranscriptionEmails: true
- autoTranslateInstantMeetingTitleEnabled: false
- allowReschedulingPastBookings: false
- allowReschedulingCancelledBookings: false
- showOptimizedSlots: false
This improves API documentation by clearly communicating default
values to API consumers in the OpenAPI spec.
* feat(api-v2): refactor event type settings to object types for future extensibility
- Convert disableRescheduling from boolean to object with disabled and minutesBefore properties
- Convert disableCancelling from boolean to object with disabled property
- Move canSendCalVideoTranscriptionEmails into CalVideoSettings as sendTranscriptionEmails
- Remove autoTranslateInstantMeetingTitleEnabled (Enterprise-only feature)
- Add DisableRescheduling_2024_06_14 and DisableCancelling_2024_06_14 input/output types
- Add transformation methods for new object types in input and output services
- Update E2E tests for new API contract
BREAKING CHANGE: disableRescheduling and disableCancelling now accept objects instead of booleans
* fix(api-v2): prevent clearing calVideoSettings when only sendTranscriptionEmails is provided
Only include calVideoSettings in transformed output if it has properties,
avoiding unintentional reset of existing settings during updates.
* feat(api-v2): add OAuth2 controller skeleton for auth module
- Add new OAuth2 module under /auth with controller, service, repository, and DTOs
- Implement skeleton endpoints:
- GET /v2/auth/oauth2/clients/:clientId - Get OAuth client info
- POST /v2/auth/oauth2/clients/:clientId/authorize - Generate authorization code
- POST /v2/auth/oauth2/clients/:clientId/exchange - Exchange code for tokens
- POST /v2/auth/oauth2/clients/:clientId/refresh - Refresh access token
- Create input DTOs for authorize, exchange, and refresh operations
- Create output DTOs for client info, authorization code, and tokens
- Register OAuth2Module in endpoints.module.ts
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* chore: add missing functions to platform libraries
* feat(api-v2): integrate OAuthService from platform-libraries into OAuth2 controller
- Add OAuthService export to platform-libraries
- Refactor OAuth2Service to use OAuthService.validateClient() and OAuthService.verifyPKCE()
- Remove duplicate local implementations of validateClient and verifyPKCE methods
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* feat(api-v2): use local validateClient and verifyPKCE implementations
- Remove OAuthService export from platform-libraries (will be deprecated)
- Reimplement validateClient and verifyPKCE methods locally in OAuth2Service
- Use verifyCodeChallenge and generateSecret from platform-libraries directly
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* refactor(api-v2): separate repositories for OAuth2, access codes, and teams
- Create AccessCodeRepository for access code Prisma operations
- Add findTeamBySlugWithAdminRole method to TeamsRepository
- Move generateAuthorizationCode, createTokens, verifyRefreshToken to OAuth2Service
- Update OAuth2Repository to only contain OAuth client operations
- Update OAuth2Module to import TeamsModule and provide AccessCodeRepository
Addresses PR review comments to properly separate concerns
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* feat(api-v2): implement JWT token creation and verification for OAuth2
- Implement createTokens method using jsonwebtoken to sign access and refresh tokens
- Implement verifyRefreshToken method to verify JWT refresh tokens
- Add ConfigService injection for CALENDSO_ENCRYPTION_KEY access
- Import ConfigModule in OAuth2Module for dependency injection
Based on logic from apps/web/app/api/auth/oauth/token/route.ts and
apps/web/app/api/auth/oauth/refreshToken/route.ts
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: refactor and dayjs import fix
* feat(api-v2): add ApiAuthGuard to getClient endpoint and e2e tests for OAuth2
- Add @UseGuards(ApiAuthGuard) to getClient endpoint for authentication
- Add comprehensive e2e tests for all OAuth2 endpoints:
- GET /v2/auth/oauth2/clients/:clientId
- POST /v2/auth/oauth2/clients/:clientId/authorize
- POST /v2/auth/oauth2/clients/:clientId/exchange
- POST /v2/auth/oauth2/clients/:clientId/refresh
- Tests cover happy paths and error cases (invalid client, invalid code, etc.)
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* chore(api-v2): hide OAuth2 endpoints from Swagger documentation
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* hide endpoints from doc
* fix(api-v2): address PR feedback for OAuth2 controller
- Fix P0 critical bug: token_type field name mismatch in DecodedRefreshToken interface
- Add @Equals('authorization_code') validation to exchange.input.ts grantType
- Add @Equals('refresh_token') validation to refresh.input.ts grantType
- Add @IsNotEmpty() validation to get-client.input.ts clientId
- Add @Expose() decorators to all output DTOs for proper serialization
- Add security test assertion to verify clientSecret is not returned in response
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* feat(api-v2): implement redirect behavior for OAuth2 authorize endpoint
- Update authorize endpoint to return HTTP 303 redirect with authorization code
- Add exact match validation for redirect URI (security requirement)
- Implement error handling with redirect to redirect URI and error query params
- Add state parameter support for CSRF protection
- Update e2e tests to verify redirect behavior (303 status, Location header, error redirects)
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* refactor(api-v2): address PR feedback for OAuth2 authorize endpoint
- Make redirectUri a required input parameter (remove optional fallback)
- Move buildRedirectUrl and mapErrorToOAuthError to oauth2Service
- Add return statements to res.redirect() calls
- Simplify controller by delegating redirect URL building to service
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* wip move code outside of api v2
* feat(oauth): wire up dependency injection for OAuthService and repositories
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* refactor: oAuthService used in routes
* fix imports
* fix(api-v2): return 404 for invalid client ID instead of redirect in authorize endpoint
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix(api-v2): fix E2E test URL paths and remove bootstrap() in authenticated section
- Remove bootstrap() call in authenticated section to match working test pattern
- Change URL paths from /api/v2/... to /v2/... in authenticated section
- Keep bootstrap() and /api/v2/... paths in unauthenticated section
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix(api-v2): mock getToken from next-auth/jwt for E2E tests
- Add jest.mock for next-auth/jwt getToken function
- Mock returns null for unauthenticated tests
- Mock returns { email: userEmail } for authenticated tests
- Remove withNextAuth helper since ApiAuthGuard uses ApiAuthStrategy
which calls getToken directly, not NextAuthStrategy
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix tests and code review
* cleanup generate secrets
* cleanup controller
* chore: remove console.log from OAuthService.validateClient
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* Update apps/web/app/api/auth/oauth/refreshToken/route.ts
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* fix(api-v2): add bootstrap() to authenticated E2E tests and update URL paths to /api/v2/
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* Merge remote-tracking branch 'origin/devin/oauth2-controller-skeleton-1765988792' and remove console.log from token route
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* chore: remove dead code
* refactor
* refactor: generateAuthCode trpc handler and getClient trpc handler
* remove pkce check for refreshToken endpoint
* Update packages/trpc/server/routers/viewer/oAuth/getClient.handler.ts
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* refactor: error handling
* refactor: error handling
* refactor: error handling
* remove console log
* provide redirectUri in generateAuthCodeHandler
* provide redirectUri in authorize view
* refactor: replace HttpError with ErrorWithCode in OAuth files
- Update OAuthService to use ErrorWithCode instead of HttpError
- Update mapErrorToOAuthError to check ErrorCode instead of status codes
- Update token/route.ts and refreshToken/route.ts to use ErrorWithCode
- Add ErrorWithCode export to platform-libraries
- Use getHttpStatusCode to map ErrorCode to HTTP status codes
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: update generateAuthCode handler to use ErrorWithCode instead of HttpError
The handler was still checking for HttpError in its catch block, but OAuthService
now throws ErrorWithCode. This caused the error messages to be lost and replaced
with 'server_error' instead of the specific error messages.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: update OAuth2 controller to use ErrorWithCode instead of HttpError
The controller was still checking for HttpError in its catch blocks, but OAuthService
now throws ErrorWithCode. This caused all errors to return 500 Internal Server Error
instead of the correct HTTP status codes (400, 401, 404).
Also added getHttpStatusCode export to platform-libraries.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: add explicit unknown type annotation to catch blocks in OAuth2 controller
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: change NotFoundException to HttpException in authorize endpoint
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: handle err with ErrorWithCode in authorize endpoint catch block
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: move errorWithCode
* fix: error code rfc
* fix: no need to handle errors there is a middleware
* refactor errors
* refactor errors
* refactor redirecturi and state from api
* refactor: address PR comments for OAuth2 controller
- Remove unused GetOAuth2ClientInput class
- Change API tag from 'Auth / OAuth2' to 'OAuth2'
- Move OAuthClientFixture to separate fixture file (oauth2-client.repository.fixture.ts)
- Add 'type' property to OAuth2ClientDto for confidential/public client type
- Rename 'clientId' to 'id' in OAuth2ClientDto (using @Expose mapping)
- Clean up duplicate provider declarations in oauth2.module.ts
- Update e2e tests to use new fixture and verify type property
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.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>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-authored-by: Volnei Munhoz <volnei@cal.com>
## What does this PR do?
> **⚠️ Note: This PR does not enable booking audit in production.** The `BookingAuditTaskerProducerService` has an [`IS_PRODUCTION` guard](https://github.com/calcom/cal.com/blob/integrate-booking-creation-reschedule-audit/packages/features/booking-audit/lib/service/BookingAuditTaskerProducerService.ts#L106-L108) that skips audit task queueing in production environments. This allows the integration to be tested in development before enabling it in production.
Integrates audit logging for booking cancellations, following the pattern established in PR #26046 for booking creation/rescheduling audit.
- Related to #25125 (Booking Audit Infrastructure)
### Changes:
- Add audit logging for single booking cancellation via `onBookingCancelled`
- Add audit logging for bulk recurring booking cancellation via `onBulkBookingsCancelled`
- Pass `userUuid` and `actionSource` from webapp cancel route (WEBAPP)
- Pass `userUuid` and `actionSource` from API-v2 bookings service (API_V2)
- Create `getAuditActor` helper to derive actor from userUuid or create synthetic guest actor
- Add `getUniqueIdentifier` helper for generating unique actor identifiers
- Add warning log when `actionSource` is "UNKNOWN" for observability
- Add integration tests for booking cancellation audit
### Audit Data Captured:
- `cancellationReason` (simple string value)
- `cancelledBy` (simple string value)
- `status` (old → new, e.g., "ACCEPTED" → "CANCELLED")
### Updates since last revision:
- Simplified `CancelledAuditActionService` schema: `cancellationReason` and `cancelledBy` are now stored as simple nullable strings instead of change objects (old/new), since cancellation is a one-time event where tracking previous values doesn't apply
- Added integration tests for cancelled booking audit in `booking-audit-cancelled.integration-test.ts`
- Added `getUniqueIdentifier` helper function in actor.ts for generating unique identifiers with prefixes
## 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.
- [ ] I confirm automated tests are in place that prove my fix is effective or that my feature works.
## How should this be tested?
1. Cancel a single booking via the webapp - verify audit record is created with actor and actionSource="WEBAPP"
2. Cancel a single booking via API v2 - verify audit record is created with actionSource="API_V2"
3. Cancel all remaining bookings in a recurring series - verify bulk audit records are created with shared operationId
4. Cancel via unauthenticated cancel link - verify guest actor is created with synthetic email (prefixed with "param-" or "fallback-")
5. Run integration tests: `yarn test packages/features/booking-audit/lib/service/__tests__/booking-audit-cancelled.integration-test.ts`
## Human Review Checklist
- [ ] Verify `onBookingCancelled` and `onBulkBookingsCancelled` methods exist in `BookingEventHandlerService`
- [ ] Review the `getAuditActor` fallback logic - creates synthetic email with "fallback-" or "param-" prefix when no userUuid available
- [ ] Confirm the simplified schema for `cancellationReason`/`cancelledBy` (no longer tracking old→new) is intentional
- [ ] Note: Audit logging calls are awaited directly - if audit service fails, the cancellation will fail. Confirm this is the desired behavior.
- [ ] Verify `CancelledAuditDisplayData` type no longer includes `previousReason` and `previousCancelledBy` fields
---
Link to Devin run: https://app.devin.ai/sessions/42404e76a66946fe9e46fa07fb12e779
Requested by: @hariombalhara (hariom@cal.com)
Replace N sequential queries with single batch queries in:
- getOutputRecurringBookings
- getOutputRecurringSeatedBookings
Uses existing batch repository methods. Reduces database roundtrips
from O(n) to O(1) for recurring booking lookups
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
* 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 SharmaGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* 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
Peer RichelsenGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* 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>