* fix: add vi.mock calls to prevent InstantBookingCreateService test flake
Add two vi.mock() calls ported from cal repo to prevent
'Closing rpc while fetch was pending' errors:
1. Mock @calcom/app-store/calendar.services.generated with a Proxy
to prevent real calendar modules (feishu, lark) from triggering
async getAppAccessToken fetch calls during test worker shutdown.
2. Mock @calcom/features/ee/organizations/di/OrganizationRepository.container
to prevent deep transitive import chain from triggering a Vitest
module-resolution RPC still in flight at shutdown.
Also removes the narrow feishucalendar mock which is now covered by
the broader calendar.services.generated Proxy mock.
* fix: update bookingScenario to use Proxy-based CalendarServiceMap
Replace the plain-object CalendarServiceMap mock with a Proxy-based
implementation that catches ALL calendar service accesses. This prevents
real calendar modules (feishu, lark, etc.) from being imported during
tests, which was causing 'Closing rpc while fetch was pending' errors
when the Vitest worker shut down.
Also update mockCalendar to use a shared mock map directly instead of
dynamically importing calendar.services.generated, avoiding loading
real calendar service modules during test execution.
* feat(bookings): add booking audit logging to instant bookings
wire up BookingEventHandlerService.onBookingCreated in
InstantBookingCreateService to emit audit events, matching the
pattern already used in RegularBookingService and
RecurringBookingService.
* refactor: extract fireBookingEvents and reuse existing orgId
* refactor: derive orgId once and pass to both webhook trigger and audit event
* fix: add missing return in webhook map callback
* refactor: make creationSource required for instant bookings
Both callers (WEBAPP and API_V2) always set creationSource, so validate
it upfront and use CreationSource enum type instead of string | null.
* fix: use ErrorWithCode instead of Error, pass userUuid to audit events
* fix: pass null for hostUserUuid in instant booking audit data
Instant bookings have status AWAITING_HOST with no assigned host,
so the booker's UUID should not be recorded as hostUserUuid.
* fix: address devin review - hostUserUuid and creationSource validation
* fix: address review - bookingMeta, getOrgIdFromMemberOrTeamId, required creationSource
- pass userUuid via bookingMeta instead of separate param (matches RegularBookingService pattern)
- restore getOrgIdFromMemberOrTeamId for proper org resolution instead of eventType.team.parentId
- make creationSource required with runtime validation instead of defaulting to WEBAPP
* fix: enforce creationSource at compile time instead of runtime
use Required<Pick<>> to make creationSource required in the type
signature. removes the runtime check since TypeScript catches
missing creationSource at build time.
* fix: simplify type signature and derive hostUserUuid from booking relation
- Replace Required<Pick<CreateInstantBookingData, 'creationSource'>> with inline { creationSource: CreationSource }
- Include user relation in booking create query to derive hostUserUuid
- Pass newBooking.user?.uuid instead of hardcoding null for userUuid in audit data
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* chore: trigger CI
* fix: add missing impersonatedByUserUuid to instant booking meta
The CreateBookingMeta type requires impersonatedByUserUuid. Set it to
null for non-impersonated instant bookings.
* fix: show 'awaiting host' in audit log for instant bookings
Use booking status AWAITING_HOST to display "Booked (awaiting host)"
instead of "Booked with Unknown" when no host has accepted yet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add booking audit for instant meeting accept via connect-and-join
Extract fireInstantBookingAcceptedAuditEvent to InstantBookingCreateService
and fire it right after the DB update, before side-effect notifications.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add audit logging tests for instant booking creation
* fix: simulate audit failure in resilience test (identified by cubic)
The test 'should not throw when booking audit event fails' was not
actually simulating an audit failure. Added vi.spyOn on
BookingEventHandlerService.prototype.onBookingCreated to reject with
an error, and assert the spy was called, proving the try/catch in
fireBookingEvents properly catches the error without breaking the
booking flow.
Co-Authored-By: bot_apk <apk@cognition.ai>
* test: add audit event tests for connectAndJoin and fix InstantBooking audit test
* test
---------
Co-authored-by: Hariom Balhara <1780212+hariombalhara@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: hariom@cal.com <hariombalhara@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: bot_apk <apk@cognition.ai>
* Add Famulor app integration to app store
Introduces the Famulor app as a new automation integration in the app store, including configuration, API handler, assets, and documentation. Updates redirectApps utility to include 'famulor' for redirection support.
* fixed - famulor
* Update packages/app-store/famulor/api/add.ts
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Update packages/app-store/famulor/config.json
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* yarn app-store:build
---------
Co-authored-by: Sahitya Chandra <sahityajb@gmail.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com>
* fix: use i18n for apps count with proper pluralization
Replace hardcoded "${installedAppsNumber} apps" with
t("number_apps", { count: installedAppsNumber }) for proper
i18n pluralization support. Removes the TODO comment that
flagged this issue.
Closes#28407
* fix: update e2e test to match i18n singular/plural apps count
---------
Co-authored-by: Sahitya Chandra <sahityajb@gmail.com>
Co-authored-by: Romit <85230081+romitg2@users.noreply.github.com>
* fix: mock @calcom/lib/i18n in EventManager.test.ts to prevent vitest worker shutdown flake
TranslationService transitively imports @calcom/lib/i18n which triggers slow
module resolution via vite's RPC. When the vitest worker shuts down before it
completes, it causes 'Closing rpc while fetch was pending' errors.
Mocking the module prevents the actual module resolution during test loading.
Co-Authored-By: romitgabani1 <romitgabani1.work@gmail.com>
* chore: remove explanatory comments per review feedback
Co-Authored-By: romitgabani1 <romitgabani1.work@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: block localhost and loopback addresses in SSRF protection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: block loopback IPs by hostname in SSRF protection
Add 127.0.0.1, ::1, [::1], and 0.0.0.0 to blocked hostnames list for
defense-in-depth protection against SSRF attacks targeting localhost.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Romit <romitgabani1.work@gmail.com>
Co-authored-by: Romit <85230081+romitg2@users.noreply.github.com>
* fix: join multiple Reply-To addresses as comma-separated string
Some SMTP providers (e.g., SendLayer) reject emails when Reply-To is
passed as an array to nodemailer, which serializes it as multiple
Reply-To headers. Using a comma-joined string is RFC 2822 compliant
and works universally across all SMTP providers.
Fixes#28610
* test: add unit tests for getReplyToHeader SMTP compatibility
- Verify replyTo is always returned as comma-separated string, not array
- Test single email, multiple emails, and empty email cases
- Add RFC 5322 compliance test for SMTP compatibility
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: add RFC 5322 reference comment to getReplyToHeader tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Lawrence Christian <67164412+LCNDevs@users.noreply.github.com>
Co-authored-by: Romit <85230081+romitg2@users.noreply.github.com>
Co-authored-by: Romit <romitgabani1.work@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix: improve German translation for reschedule button
* fix: use accurate German translation for reschedule button
Change "Neuen Termin buchen" (Book new appointment) to "Neu terminieren"
(Re-schedule) to align with the English "Reschedule" meaning.
---------
Co-authored-by: Romit <romitgabani1.work@gmail.com>
* fix: mock delegationCredential in getRoutedUsers test to prevent flaky worker shutdown errors
The getRoutedUsers.test.ts file only tests the pure sync function
getRoutedUsersWithContactOwnerAndFixedUsers, but importing getRoutedUsers.ts
triggers a heavy transitive import chain:
getRoutedUsers.ts
-> @calcom/app-store/delegationCredential
-> _utils/getCalendar
-> calendar.services.generated (all calendar services)
-> CalendarService.ts -> ics/tsdav
Sometimes the vitest worker finishes tests and shuts down before all async
module resolution completes, causing:
Error: [vitest-worker]: Closing rpc while "fetch" was pending
Mock @calcom/app-store/delegationCredential to cut off the import chain
since the tested function doesn't use it.
* Clean up comments in getRoutedUsers.test.ts
Removed comments about mocking delegationCredential to improve code clarity.
* fix(form-builder): show default label when field label is only whitespace
* fix: add validation to ensure label is not empty or whitespace
* fix: enhance label validation to prevent empty or whitespace labels in FormBuilder
* fix: refactor label validation in FormBuilder to streamline whitespace checks
* chore: retrigger CI (flaky vitest worker shutdown)
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: restore moveTeamToOrg admin endpoint for organization migration
- Add moveTeamToOrg and removeTeamFromOrg functions to orgMigration.ts
- Restore API endpoint at /api/orgMigration/moveTeamToOrg
- Restore admin UI page at /settings/admin/orgMigrations/moveTeamToOrg
- Add helper functions for team redirect management
- Support moving team members along with the team
This endpoint allows admins to migrate teams to organizations after org creation,
which is needed as a temporary solution until proper org admin permissions are implemented.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: move moveTeamToOrg to lib/orgMigration and fix redirect URL
- Move moveTeamToOrg and removeTeamFromOrg functions from playwright/lib to lib/orgMigration.ts
- Update API endpoint to import from lib/orgMigration instead of playwright/lib
- Fix redirect URL format: use / instead of /team/
- Fix import path: use ../playwright/lib/orgMigration instead of ./playwright/lib/orgMigration
- Rename unused _dbRemoveTeamFromOrg in playwright file to satisfy linter
- Remove duplicate functions from playwright/lib/orgMigration.ts
This fixes the Vercel deployment failure caused by importing from test-only directories
in production API routes, and corrects the redirect URL format to match the original implementation.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: reuse existing createTeamsHandler for moveTeamToOrg endpoint
- Remove custom orgMigration.ts implementation
- Update API endpoint to call existing createTeamsHandler with org owner impersonation
- Remove moveMembers option from UI (always moves members by design)
- Fix Vercel deployment by removing playwright import from production code
- Use OrganizationRepository.adminFindById to fetch org owner
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: migrate moveTeamToOrg admin page and API to App Router
- Move admin page from pages/settings/admin/orgMigrations to app/(use-page-wrapper)/settings/(admin-layout)/admin/orgMigrations
- Convert API route from pages/api/orgMigration/moveTeamToOrg.ts to app/api/orgMigration/moveTeamToOrg/route.ts
- Create client view component in modules/settings/admin/org-migrations/
- Remove old pages directory files and getServerSideProps
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: correct import paths for App Router compatibility
- Fix @calcom/lib/server to @calcom/lib/server/i18n for getTranslation
- Fix @calcom/ui barrel import to specific component paths
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: use TFunction type for getFormSchema parameter
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: use buildLegacyRequest for App Router session compatibility
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Remove unused fn
* cleanup
* cleanup
* fix: ui
* fix: handle slug conflict error when moving team to organization
- Intercept Prisma P2002 unique constraint error when moving a team
- Convert to user-friendly CONFLICT error with clear message
- Add test case for slug conflict scenario
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: use isPending instead of isLoading for tRPC mutation
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fixes
* fix: remove PII (emails) from admin log statement
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: use instanceof pattern for Prisma error detection
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fixes
* fix: use i18n key for slug conflict error message instead of hardcoded English string
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: narrow P2002 catch scope to only prisma.team.update call
Separates the try-catch for prisma.team.update (slug conflict) from
creditService.moveCreditsFromTeamToOrg to avoid misattributing credit
service P2002 errors as slug conflicts.
Co-Authored-By: bot_apk <apk@cognition.ai>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: bot_apk <apk@cognition.ai>
* refactor: evt creation
* refactor: evt creation
* refactor: evt creation
* fix: type
* test: update unit tests
* chore: add comments
* fix: handle undefined in withConditional to match NonNullable<T> type
Co-Authored-By: unknown <>
* refactor: evt
* fix: type err
* refactor: remove add videoCallData
* refactor: use error with code
* test: update unit test
* refactor: feedback
* refactor: remove conditional
* refactor: more strict types
* fix: type err
* chor: remove un used
* refactor: improve recurring event handling in RegularBookingService
Removed unnecessary whitespace and clarified comments regarding the attachment of recurring configurations in the booking handler. Adjusted logic to ensure that recurring settings are only applied when relevant.
* refactor: test
* fix: type error
* refactor: improve code
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: remove attendee endpoint
* fix: remove attendee email from error logs to avoid logging PII
Co-Authored-By: unknown <>
* fix: add isBookingAuditEnabled to removeAttendee handler
Align removeAttendee.handler.ts with the new onAttendeeRemoved interface
that requires isBookingAuditEnabled, following the same pattern used in
addGuests.handler.ts.
Co-Authored-By: bot_apk <apk@cognition.ai>
* style: apply biome formatting to conflict-resolved files
Co-Authored-By: bot_apk <apk@cognition.ai>
* chore: implement PR feedback
* fixup
* revert: biome formatting changes
* chore: implement feedback part 1
* chore: implement feedback part 2
* fix: await cancellation email flow to prevent uncaught promise rejections
The fire-and-forget .then() chain on prepareAttendeePerson() left
rejections from that promise uncaught. Await both prepareAttendeePerson()
and sendCancelledEmailToAttendee() so errors are properly handled.
sendCancelledEmailToAttendee() already has an internal try/catch, so
awaiting it will not cause the overall removeAttendee flow to fail on
email errors.
Addresses Cubic AI review (confidence 9/10).
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: implement feedback part 3
* chore: implement devin feedback
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: bot_apk <apk@cognition.ai>
* fix: add missing vi.mock() calls to prevent vitest worker shutdown flakiness
Add vi.mock() calls for modules that trigger background network requests
or database connections during import. These transitive imports can cause
the vitest worker RPC to shut down while pending fetch/network operations
are still in flight, resulting in flaky test failures with:
Error: [vitest-worker]: Closing rpc while "fetch" was pending
The primary modules mocked are:
- @calcom/app-store/delegationCredential (triggers credential lookups)
- @calcom/prisma (triggers database initialization)
- @calcom/features/calendars/lib/CalendarManager (triggers calendar API calls)
- @calcom/features/auth/lib/verifyEmail (triggers email service)
- @calcom/lib/domainManager/organization (triggers domain lookups)
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: remove conflicting empty prisma mocks from files with prismock/prismaMock setups
- Remove vi.mock('@calcom/prisma', () => ({ default: {}, prisma: {} })) from 28 files
that already have prismock/prismaMock test doubles. Vitest hoists all vi.mock() calls
and the last one wins, so these empty mocks were overriding the functional test doubles.
- Fix CalendarSubscriptionService.test.ts to reuse the shared mock from
__mocks__/delegationCredential instead of creating a new unconfigured vi.fn()
- Remove DelegationCredentialRepository.test.ts empty prisma mock (different pattern)
- Remove vi.mock from inside beforeEach in intentToCreateOrg.handler.test.ts
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: add comprehensive delegationCredential mock exports to prevent CI test failures
The vi.mock blocks for @calcom/app-store/delegationCredential were missing
exports that the code under test transitively imports (e.g.
enrichUsersWithDelegationCredentials, enrichUserWithDelegationCredentialsIncludeServiceAccountKey,
buildAllCredentials, getFirstDelegationConferencingCredentialAppLocation).
Added all exports with passthrough implementations so the booking flow
works correctly without triggering real network requests.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: correct credential mock return shapes to match real module API
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: revert unintended yarn.lock changes
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: Sink url shortner for sms workflow reminders
* fix: remove hardcoded dub values
* update .env.example
* fix: unit tests
* chore: add tests for scheduleSmsReminder and utils
* review refactor
* fix: type check
* review refactor
* fix: update test to account for smsReminderNumber fallback from main
Co-Authored-By: unknown <>
* feat: add feature flag for sink and more tests to verify
* fix: type check
* use proper feature flags for sink
* Apply suggestion from @keithwillcode
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
* feat: add platform URL support for reschedule and cancel links in workflow emails
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* feat: pass platform URL data to CalendarEventBuilder in workflow emails
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* Revert "feat: pass platform URL data to CalendarEventBuilder in workflow emails"
This reverts commit 1d4d3623c93cd4eeeef18ffdad0597fe583b6a55.
* chore: provide platform metadat to workflow email task
* fixup! chore: provide platform metadat to workflow email task
* test: add unit tests for platform URL handling in EmailWorkflowService
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* test: update WorkflowService tests to include platform params in tasker payload
Co-Authored-By: morgan@cal.com <morgan@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: move useAppsData to features + replace useIsPlatform with isPlatform prop in DisconnectIntegrationModal
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* refactor: remove old useAppsData from web (moved to features)
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: align checkBookingAccessWithPBAC with listing logic for personal event types
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: align permission strings with doesUserIdHaveAccessToBooking granular permissions
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* change implementation
* remove unused code
* test: add getBookingDetails tests for personal event type booking access
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: remove unused MembershipRole import
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* test: convert BookingDetailsService tests to integration tests
Replace unit tests with mocks by integration tests using real database.
Tests verify org/team admin access to personal event type bookings.
- Org admin viewing team member's personal event booking (fails on main, passes on PR)
- Team admin viewing team member's personal event booking (fails on main, passes on PR)
- Non-admin denied access (passes on both)
- Owner viewing own booking (passes on both)
- Non-existent booking returns Forbidden (passes on both)
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* test: refactor integration tests to use repositories instead of direct prisma calls
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* test: replace direct prisma usage with TestXXXRepository pattern in integration tests
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* test: use production repositories (OrganizationRepository, BookingRepository, UserRepository) instead of test repos for setup
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* test: inline test repository logic into integration test file
The TestXXXRepository classes were thin wrappers around single prisma
calls with barely any logic, so the indirection wasn't justified.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The Dialpad conferencing integration's URL regex only accepted
alphanumeric characters in the meeting room path ([a-zA-Z0-9]+),
causing valid personal meeting URLs containing hyphens, dots, or
underscores to fail validation.
For example, https://meetings.dialpad.com/mmit-russ is rejected
despite being a valid Dialpad personal meeting link. The sample URL
shown in the error message (alphanumeric only) passes, but
real-world room names commonly use hyphens and other characters.
Updated the urlRegExp character class from [a-zA-Z0-9] to
[a-zA-Z0-9._-] to match all valid Dialpad meeting room slugs.
Fixes issue introduced in #15444.
Co-authored-by: Sahitya Chandra <sahityajb@gmail.com>
* fix: correct admin password banner message to require both password length and 2FA
The banner message incorrectly used 'or' implying only one condition was needed,
but the code requires BOTH a password of at least 15 characters AND 2FA enabled.
Updated the message to clearly state both requirements and added a hint that
users need to log out and log back in after updating their security settings.
Fixes#9527
Co-Authored-By: unknown <>
* fix: auto-sign-out INACTIVE_ADMIN users after enabling 2FA
When an INACTIVE_ADMIN user enables 2FA, automatically sign them out so
they can log back in with refreshed session role, dismissing the banner.
This matches the existing behavior for password changes.
Co-Authored-By: unknown <>
* feat: add dynamic admin banner message based on inactiveAdminReason
Co-Authored-By: unknown <>
* Remove and add various localization strings
* Update common.json
* Add cookie consent checkbox message and remove entries
* test: add unit tests for AdminPasswordBanner and inactiveAdminReason logic
Co-Authored-By: unknown <>
* fix: add expires field to session mock to fix type check
Co-Authored-By: unknown <>
* fix: wrap CALENDSO_ENCRYPTION_KEY mutations in try/finally to prevent env state leaks
Addresses Cubic AI review feedback (confidence 9/10): when a test fails
early, the CALENDSO_ENCRYPTION_KEY env var was not being restored, which
could leak state into subsequent tests. Wrapped the env mutation in
try/finally blocks to guarantee cleanup.
Co-Authored-By: bot_apk <apk@cognition.ai>
* fix: add missing 'expires' field to buildSession in AdminPasswordBanner test
The Session type requires 'expires' to be a string, but buildSession was
not providing it, causing a type error caught by CI type-check.
Co-Authored-By: bot_apk <apk@cognition.ai>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: bot_apk <apk@cognition.ai>
* perf: add paginated host endpoints and delta-based host updates for event type editor
- New cursor-paginated tRPC endpoints: getHostsForAssignment, getHostsForAvailability, searchTeamMembers, getChildrenForAssignment, exportHostsForWeights, getHostsWithLocationOptions
- Delta-based host update support in update.handler.ts (pendingHostChanges, pendingChildrenChanges)
- Repository additions: EventTypeRepository.findChildrenByParentId, HostRepository pagination, MembershipRepository.searchMembers, UserRepository.findByIdsWithPagination
- Remove teamMembers from getEventTypeById initial load
- Shared types: PendingHostChangesInput, PendingChildrenChangesInput, HostUpdateInput
Co-Authored-By: unknown <>
* fix: revert getTranslation import path to @calcom/i18n/server
Co-Authored-By: unknown <>
* fix: guard findChildrenByParentId to only run when pendingChildrenChanges exists
Co-Authored-By: unknown <>
* refactor: remove delta-based saving logic from backend PR
Move pendingHostChanges/pendingChildrenChanges processing out of backend PR.
These changes belong in the frontend PR since they are tightly coupled
to the new frontend delta tracking components.
Backend PR now contains only read-side optimizations:
- Paginated host/children/member endpoints
- Repository methods
- getEventTypeById optimizations
Co-Authored-By: unknown <>
* refactor: move getEventTypeById changes to frontend PR for type safety
Reverts getEventTypeById.ts, eventTypeRepository.ts, API v2 atom service,
and platform libraries to main. The backend PR now only adds new
infrastructure (paginated endpoints, repository methods, findChildrenByParentId)
without changing existing return types. The getEventTypeById optimizations
will be in the frontend PR instead.
Co-Authored-By: unknown <>
* refactor: move findTeamMembersMatchingAttributeLogic pagination to frontend PR
The handler's return type change (adding nextCursor/total) breaks frontend
files on main that expect the old shape. Moving these changes to the
frontend PR keeps the backend PR purely additive.
Co-Authored-By: unknown <>
* fix: address Cubic review comments - empty array filter, stable total count, Set lookup
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Fix inifnite pagination loop
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: derive teamId from event type to prevent cross-team enumeration in exportHostsForWeights
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: restore doc comment to correct method hasAnyTeamMembershipByUserId
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: use memberUserIds?.length to handle empty array filter in findHostsForAssignmentPaginated
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: use explicit undefined check for memberUserIds to preserve empty array semantics
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: rename findChildrenByParentId to findChildrenByParentIdIncludeOwner
The method selects owner with user profile data, so the name should
reflect the included relation per Cal.com repository naming conventions.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: rename host repository methods to follow naming conventions
- findHostsForAvailabilityPaginated -> findHostsPaginatedIncludeUser
- findHostsForAssignmentPaginated -> findHostsPaginatedIncludeUserForAssignment
Repository methods should not be named after use-cases (Availability/Assignment)
but should describe what data they include, per Cal.com conventions.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: standardize slice(0, limit) across all pagination methods
Replace slice(0, -1) with slice(0, limit) in all HostRepository
pagination methods for consistency. slice(0, limit) is clearer about
intent since it directly references the limit parameter.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* perf: only run total count query on first page in findByIdsWithPagination
Wrap the count query in a !cursor guard so it only runs on the first
page request, avoiding an extra database query on every scroll.
Consistent with the hasFixedHosts optimization in HostRepository.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* test: add integration tests for paginated host endpoints
Tests cover getHostsForAvailability and getHostsForAssignment handlers:
- Basic host retrieval
- Cursor-based pagination across multiple pages
- Host data fields (isFixed, priority, weight, name, email)
- Search filtering by name
- memberUserIds filtering (including empty array returning zero results)
- hasFixedHosts only present on first page
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: extract EventTypeHostService and make TRPC handlers thin
- Create EventTypeHostService at packages/features/host/services/ with all
DTO types and business logic for 5 event-type-host endpoints
- Refactor all 5 handlers to delegate to the service (thin handlers)
- Add 17 unit tests covering DTO mapping, authorization, segment filtering,
default values, and pagination pass-through
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* docs: add PR review context comments to EventTypeHostService
Reference key review decisions from PR #28156 as code comments:
- searchTeamMembers: membership check + repository delegation per @eunjae-lee
- exportHostsForWeights: cross-team enumeration security fix per @hariombalhara
- exportHostsForWeights: repository method instead of direct Prisma per @hariombalhara
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Revert "docs: add PR review context comments to EventTypeHostService"
This reverts commit 1a1596e012e971f349f01339ce7572516042f1b3.
* fix: use explicit undefined/null check for memberUserIds in searchMembers
Fixes empty array semantics so memberUserIds: [] correctly returns zero
results instead of all members. Now consistent with HostRepository pattern
which uses 'memberUserIds !== undefined' instead of 'memberUserIds?.length'.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: replace TRPCError with ErrorWithCode in EventTypeHostService
Per AGENTS.md rules, services in packages/features/ should use
ErrorWithCode instead of TRPCError. The errorConversionMiddleware
will automatically convert it to the appropriate TRPCError at the
router layer.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Remove comment
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: remove unused teamId from exportHostsForWeights schema
teamId was originally accepted by the schema when the handler used it
directly. After the security fix to derive teamId server-side from the
event type, the field became dead code. Removing it to keep the API
contract accurate.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Abstract types
* Update imports
---------
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>