* fix: Yarn installation fails in windows due to mixed path separators in app-store-cli
* fix: normalize paths for cross-platform Biome compatibility in app-store-cli
* fix(ui): improve Variables Dropdown styling consistency
- Change focus ring from brand-800 to subtle for consistent design
- Add rounded-md to dropdown container for visual consistency
- Add rounded-md to DropdownMenuItem for rounded corners
- Remove redundant hover:bg-muted and conditional bg-muted styling
Fixes#25848
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: restore keyboard navigation active state indicator
Keep the conditional bg-muted styling for the selected item during
keyboard navigation, while still removing the redundant hover:bg-muted
since DropdownMenuItem already handles hover styling.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: simiondolha <simiondolha@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
2026-01-13 14:53:11 -03:00
Alex van AndelGitHubalex@cal.com <me@alexvanandel.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>Keith WilliamsAnik Dhabal Babu
* refactor: split large org creation transaction into smaller batches
The prisma.team.create call at L418 was creating the organization along with
all orgProfiles and memberships in a single large transaction, which could
timeout when there are many members.
This change splits the operation into smaller, separate transactions:
1. Create the organization (team) with just metadata and organizationSettings
2. Create org profiles in batches of 50 using Promise.all
3. Create memberships in batches of 100 using createMany
4. Fetch created profiles to rebuild the member-profile mapping
This approach avoids transaction timeouts while maintaining the same
functionality and data integrity.
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* Apply suggestion from @cubic-dev-ai[bot]
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>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
The AES256 encryption used for 2FA requires exactly 32 bytes.
The previous command `openssl rand -base64 32` generates a 44-character
base64 string (32 bytes encoded in base64), which is too long.
Changed to `openssl rand -base64 24` which generates exactly 32
characters (24 bytes encoded in base64 = 32 characters).
This was causing 2FA setup failures with "Something went wrong" errors
and RangeError: Invalid key length in self-hosted Docker installations.
Fixes#22365
Co-authored-by: simiondolha <simiondolha@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2026-01-13 11:46:39 -03:00
Eunjae LeeGitHubeunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>sean-brydon
* feat: add tri-state UI settings pages and auto opt-in preference
TASK 5: Tri-state UI with ToggleGroup
- Create shared TeamOrgFeaturesSettings component
- Create user features settings page (features-view.tsx)
- Create team features settings page
- Create org features settings page
TASK 6: Add auto opt-in preference
- Add autoOptInExperimentalFeatures field to User and Team models
- Add migration for new fields
- Add TRPC endpoints for auto opt-in preference (using repository pattern)
- Add auto opt-in checkboxes to settings pages
Also adds i18n keys for feature opt-in UI.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
refactor: rename autoOptInExperimentalFeatures to autoOptInFeatures
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
refactor: apply PBAC procedure pattern to featureOptIn router
- Create createTeamPbacProcedure for team-scoped endpoints
- Create createOrgPbacProcedure for organization-scoped endpoints
- Refactor all team/org endpoints to use the new PBAC procedures
- Significantly reduces boilerplate code for permission checks
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
add features pages
implement hooks
update style
update style
rename slug to featureId
show Features page on the side bar only if OPT_IN_FEATURES.length > 0
revert unncessary renaming
revert some changes
remove some changes
* fix repository usage
* test: add unit tests for PBAC utility procedures
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: add 'disabled by organization' badge for Team Level Features page
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* a little clean up
* feat: add effectiveReason to computeEffectiveStateAcrossTeams for better UI feedback
- Update computeEffectiveStateAcrossTeams to return both enabled state and reason
- Add EffectiveStateReason type with 6 possible values
- Update FeatureOptInService to include effectiveReason in resolved state
- Simplify useUserFeatureOptIn.getBlockedWarning to use effectiveReason directly
- Add feature_no_explicit_enablement_warning translation
- Invalidate feature list when auto-opt-in setting changes in all hooks
* test: add tests for FeatureOptInService.listFeaturesForTeam and refactor router to use TeamRepository
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* make it clearer about auto opt in
* move hooks to apps/web/module
* fix
* fix: move types to packages/features/feature-opt-in, fix imports and test mocks
- Move types.ts from apps/web/modules/feature-opt-in/hooks to packages/features/feature-opt-in
- Update FeaturesSettings.tsx to import types from new location
- Update hooks to import types from @calcom/features/feature-opt-in/types
- Fix organization features-view import path (~/settings/organizations -> ~/ee/organizations)
- Fix PermissionCheckService mock in util.test.ts to use class syntax
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add validation for team ID and remove isPublic from featureOptIn handler
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: resolve biome lint errors in feature-opt-in files
- Add explicit return types to functions and methods
- Replace ternary operators with if-else statements
- Replace forEach with for...of loops to avoid useIterableCallbackReturn
- Extract helper functions to reduce function complexity
- Add explicit type annotations to variables
- Move exports to end of file to satisfy useExportsLast rule
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: resolve type errors in featureOptIn router
- Replace ctx.organizationId with ctx.user.organization.id
- Add null checks for organizationId in org procedures
- Remove incorrect type annotation from featureOptInRouter
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: address PR feedback on feature opt-in implementation
- Refactor createMutationCallbacks to useMutationCallbacks hook with useLocale internally
- Restore comment on featureOptIn prop in FeaturesSettings.tsx
- Revert getAllTeamIds helper, use ternary operator instead
- Use ctx.user.organizationId with proper guard clauses
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix type error
* feat: disable toggle when feature is blocked by higher level
- Add isBlockedByHigherLevel function to UseFeatureOptInResult interface
- Implement blocking detection for user level (org/team disabled)
- Implement blocking detection for team level (org disabled)
- Organization level never blocked (top level)
- Update FeaturesSettings to disable ToggleGroup when blocked
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* change order of toggle buttons
* feat: add policy field (permissive/strict) to feature opt-in config
- Add OptInFeaturePolicy type with 'permissive' and 'strict' modes
- Update computeEffectiveStateAcrossTeams to handle both policies:
- Permissive: user opt-in can activate; disables only win if ALL teams disable
- Strict: user opt-in alone not enough; ANY explicit disable blocks
- Add new EffectiveStateReason values for strict policy
- Update FeatureOptInService to read policy from config
- Add unit tests for all 9 policy scenarios from spec
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: rewrite test file with scenario tables and make policy required
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix type
* fix types
* make policy required
* disable toggle group if blocked by higher level
* refactor: move PBAC procedures to packages/trpc/server/procedures
- Move util.ts to pbacProcedures.ts in procedures folder for better reusability
- Move util.test.ts to pbacProcedures.test.ts alongside the main file
- Update imports in _router.ts to use new location
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: remove redundant null checks in featureOptIn router
The createOrgPbacProcedure middleware already validates organizationId
and throws if null. Use non-null assertion (!) instead of redundant
runtime checks since the middleware guarantees the value exists.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: improve middleware typing to avoid non-null assertions
Remove explicit return type from createOrgPbacProcedure to let TypeScript
infer the extended context type. This allows handlers to use ctx.organizationId
directly (typed as number) instead of ctx.user.organizationId! assertions.
The middleware validates organizationId and adds it to the context, so
downstream handlers can safely access ctx.organizationId as a number.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat(pbac): use featureOptIn permissions instead of generic team/org permissions
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat(pbac): add PBAC to team features page and pass canEdit to views
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add effectiveReason to IFeatureOptInService and update listFeaturesForTeam interface
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add feature_any_team_disabled to isUserBlockedByHigherLevel check
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add strict-policy reasons to warning helper function
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
2026-01-13 15:37:53 +01:00
MorganGitHubunknown <>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* chore: deploy api v2 on vercel
* fix: replace console.log with logger.log in Vercel handler
Address Cubic AI review feedback to use the logging framework
consistently instead of console.log in the serverless handler.
Co-Authored-By: unknown <>
* chore: enable esModuleInterop
* chore: deploy api v2 on vercel
* chore: deploy api v2 on vercel
* Update apps/api/v2/src/bootstrap.ts
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* fixup! Merge branch 'main' into deploy-api-v2-vercel
* Revert "chore: deploy api v2 on vercel"
This reverts commit 45c704a48e8396c46118069e1a25d8d7a5ee84be.
* chore: deploy api v2 on vercel
* fix: address Cubic AI review feedback in main.ts
- Replace console.log with logger.log for consistent logging
- Replace console.error with logger.error for consistent error logging
- Restore comma: true option in qs.parse to support comma-separated arrays
Co-Authored-By: unknown <>
* fix: remove comma: true from qs.parse to maintain backward compatibility
The main branch does not have comma: true in the query parser, so adding
it would be a breaking change for existing API consumers. Removing it to
maintain consistency with the current production behavior.
Co-Authored-By: unknown <>
* chore: deploy api v2 on vercel
* small fixes
* chore: add try catch around bootstrap.ts
* fix: use NestJS Logger and throw error instead of process.exit in bootstrap
- Replace console.error with logger.error for consistent logging
- Replace process.exit(1) with throw error to avoid breaking Vercel serverless instance reuse
Addresses Cubic AI review feedback (confidence 10/10 for both issues)
Co-Authored-By: unknown <>
* chore: try log redis url
* fix: sanitize REDIS_URL logging to avoid exposing credentials
Replace full REDIS_URL logging with a boolean check that only indicates
whether Redis is configured, without exposing the connection string.
Addresses Cubic AI review feedback (confidence 9/10)
Co-Authored-By: unknown <>
* chore: remove unnecessary logs
* fix: prisma adapter
* chore: handle USE_POOL platform libraries
* fix: use JSON.stringify for Vite define value
Wrap usePool with JSON.stringify() to properly serialize the string value.
Without this, Vite injects the raw value as an identifier instead of a
string literal, breaking runtime behavior.
Addresses Cubic AI review feedback (confidence 9/10)
Co-Authored-By: unknown <>
* fix: docker file builds
* fix: correct Dockerfile build order for platform packages
Reorder builds to match the dependency graph from dev:build script:
constants → enums → utils → types → libraries → trpc → api-v2
platform-libraries depends on the other platform packages, so they
must be built first.
Addresses Cubic AI review feedback (confidence 9/10)
Co-Authored-By: unknown <>
* fix: docker file builds
* chore: add docker build
* chore: upgrade nest/bull
---------
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>
* Integrate creation/rescheduling booking audit
* fix: add missing hostUserUuid to booking audit test data
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix-ci
* feat: enhance booking audit with seat reference
- Added support for seat reference in booking audit actions.
- Updated localization for booking creation to include seat information.
- Modified relevant services to pass attendee seat ID during booking creation.
* fix: update test data to match schema requirements
- Add seatReferenceUid: null to default mock audit log data
- Add seatReferenceUid: null to multiple audit logs test case
- Convert SEAT_RESCHEDULED test data to use numeric timestamps instead of ISO strings
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Allow nullish seatReferenceUid
* feat: enhance booking audit to support rescheduledBy information
- Updated booking audit actions to include rescheduledBy details, allowing tracking of who rescheduled a booking.
- Refactored related services to accommodate the new rescheduledBy parameter in booking events.
- Adjusted type definitions and function signatures to reflect the changes in the booking audit context.
* Avoid possible run time issue
* Fix imoport path
* fix failing test due to merge from main\
* Pass useruuid
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* remove header and add standard pagination
* Remove unused props from OutOfOfficeEntriesList
Removed unnecessary props from the data table component.
* removed standard pagination
* fix
* Update OutOfOfficeEntriesList.tsx
* remove unnecessary padding
---------
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
- Create unified date/time formatter with Intl-first approach and dayjs fallback
- Add support for is/lt/nb locales in Booker components
- Unify date formatting across Booker (Header, dates, weekdays)
- Update translation pipeline to include is, lt, nb
- Add tests for new locales and formatter
- Add timezone support in dayjs fallback
- Add formatter caching with circuit breaker
- Use unified formatDateTime in Header.tsx
* fix integration test
* fix: enable DI for FeatureOptInService
* create containers/FeaturesRepository.ts
* refactor: convert FeatureOptInService and FeaturesRepository to moduleLoader pattern
- Create feature-specific tokens in feature-opt-in/di/tokens.ts and flags/di/tokens.ts
- Update modules to use bindModuleToClassOnToken for type-safe dependency injection
- Simplify containers to use moduleLoader.loadModule() for automatic dependency loading
- Import feature-specific tokens in central tokens.ts using spread operator
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: rename FeatureOptInServiceInterface to IFeatureOptInService
Follow the codebase convention of using 'I' prefix for interface files and names.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: export featuresRepositoryModule for backward compatibility
The FeaturesRepository module was refactored to use moduleLoader pattern but
AvailableSlots.ts still imports featuresRepositoryModule. This adds the export
to maintain backward compatibility.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-13 11:02:00 +01:00
sean-brydonGitHubunknown <>sean@cal.com <Sean@brydon.io>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add skip trial feature for teams/orgs billing page
Co-Authored-By: sean@cal.com <Sean@brydon.io>
* feat: add translation strings for skip trial feature and fix lint-staged config
Co-Authored-By: sean@cal.com <Sean@brydon.io>
* fix: use IS_TEAM_BILLING_ENABLED instead of IS_SELF_HOSTED
Co-Authored-By: sean@cal.com <Sean@brydon.io>
* fix: use correct DialogHeader props in billing-view.tsx
Co-Authored-By: sean@cal.com <Sean@brydon.io>
* restore lint staged config file
* invalidate trpc cache
* fix: update role filter and error message in skipTrialForTeam handler
- Changed role filter to include both OWNER and ADMIN roles to match authorization logic
- Updated error message to reflect that both owners and admins can skip the trial
Addresses Cubic AI review feedback on PR #26584
Co-Authored-By: unknown <>
* fix: optimize skipTrialForTeam to query only specific team by ID
Address Cubic AI review feedback: Replace findAllAcceptedTeamMemberships
(which fetches all teams) with TeamRepository.findById (which fetches
only the specific team needed). Authorization is already validated
earlier in the handler, so this redundant query was inefficient.
Co-Authored-By: unknown <>
* fix static methods
* feat: use pbac
* fix: remove redundant team query in getSubscriptionStatus handler
Co-Authored-By: sean@cal.com <Sean@brydon.io>
* add pbac to skip team handler
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-13 09:17:42 +00:00
Hariom BalharaGitHubhariom@cal.com <hariombalhara@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: optimize routing form mutation to avoid costly name update triggers
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Add load test script for form responses
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Copy changes
* Move search bar inline with new button
* Get rid of no more results message
* Change hidden badge to (hidden)
* Remove Cal.ai badge from sidebar
* Add dropdown to create button when there is multiple options
* Fix delete dialog
* Saved filters updates
* More string fixes
* Switch members table to use names
* Fix member spacing
* Fix routing form identifier field
* Fix routing forms stuff
* Only show SMS hint on SMS options
* Make workflow delete button minimal
* Fix padding on workflow steps
* Remove min width on workflow title
* Fix delete workflow PR
* Fix org profile buttons
* Fix org profile screen partially scrolled down
* Improve logos & banner uploads
* Personal profile fixes
* Fix settings general view stuff
* Sentence case consistency
* Fix stuff I broke
* Fix fab
* Fix hidden translation string
* Fix text fields
* Make button small for solo users too
* fix: update E2E tests to match sentence case labels in routing forms
* fix: update tests to match sentence case label changes
- insights.e2e.ts: chart titles (14 strings)
- event-types.e2e.ts: Organizer phone number location
- EditLocationDialog.test.tsx: phone number labels
* fix: address Cubic AI review feedback (confidence 9+)
- Replace hardcoded text-gray-500 with text-muted in TextField.tsx hint section
- Replace text locator with data-testid in E2E test for location select
Co-Authored-By: unknown <>
* fix: update E2E tests for sentence case label changes
- Use data-testid selectors for location options (more reliable than text)
- Update field identifiers in routing-forms tests to match new labels
- Fix Long text selector in manage-booking-questions test
* fix: replace text locator with data-testid in manage-booking-questions E2E test
Replace fragile text="Long text" locator with resilient
page.getByTestId("select-option-textarea") selector per E2E best practices.
Addresses Cubic AI review feedback (confidence 9/10).
Co-Authored-By: unknown <>
* fix: use .last() for multiple location select items
---------
Co-authored-by: Pedro Castro <pedro@cal.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Add filtering to SelectedCalendarRepository.findNextSubscriptionBatch to
exclude generic calendars (holidays, contacts, shared, imported, resources)
based on their externalId suffixes.
Changes:
- Add GENERIC_CALENDAR_SUFFIXES constant mapping providers to their
generic calendar suffixes in AdaptersFactory
- Add getGenericCalendarSuffixes method to AdapterFactory interface
- Update findNextSubscriptionBatch to accept and use genericCalendarSuffixes
parameter to filter out calendars with matching externalId suffixes
- Update CalendarSubscriptionService.checkForNewSubscriptions to pass
generic calendar suffixes from the adapter factory
- Update tests to cover the new filtering logic
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* checkpoint 1
* checkpoint 2
* update extension header
* fix some minor ios ui bugs
* fix(companion): restore username fetching for URL fallback display
Addresses Cubic AI review feedback (confidence 9/10): The username was
hardcoded to 'username' but still used by BasicsTab as a fallback for
URL display when bookingUrl is unavailable. This restores the useEffect
that fetches the actual username from CalComAPIService.getUsername().
Co-Authored-By: unknown <>
* complete devins code change
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-13 05:37:56 +05:30
Joe Au-YeungGitHubjoe@cal.com <j.auyeung419@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Eunjae Lee
* Add db schema
* Add `CredentialRepository.findByTeamIdAndSlugs`
* Add enabled app slugs for attribute syncing
* Create repository for `IntegrationAttributeSync`
* Create zod schemas
* Create `AttributeSyncUserRuleOutputMapper`
* Create `IntegrationAttributeSyncService`
* Create DI contianer
* Create trpc endpoints
* Create page
* Include team name in `CredentialRepository.findByTeamIdAndSlugs`
* Update schema and relations
* Update types and schemas
* Add more methods to IntegrationAttributeSyncRepository
* Add more services to `IntegrationAttributeSyncService`
- getById
- Init updateIncludeRulesAndMappings
* Refactor `getTeams.handler` to use repository
* Create `createAttributeSync` trpc endpoint
* Create `updateAttributeSync` trpc endpoint
* Add router to trpc
* Create attribute sync child components
* Pass custom actions to `FormCard`
* Create `IntegrationAttributeSyncCard`
* Pass inital props via server side
* Fix prop
* Only refetch on mutation
* Fixes
* Add form error when duplicate field and attribute combo
* Add `updateTransactionWithRUleAndMappings` logic
* Adjust zod schemas
* Service add `updateIncludeRulesAndMappings`
* Pass orgId from server to component
* Rename types
* Add deleteById method to repository
* Add name to integrationAttributeSync
* Add deleteById method to service
* Rename method
* Add deleteAttributeSync trpc endpoint
* Make the IntegrationAttributeSyncCard a dummy component
* test: add tests for IntegrationAttributeSync feature
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Move creating a attribute sync record to the service
* Add i18n strings
* Safe select credential in find by id and team
* Fix default credentialId value in form
* Update repository return types
* Add i18n string
* Make credentialId optional for form schema
* Fix label
* Add cascade deletes
* Add verification that syncs belong to org
* Create mapper for repository output
* Type fixes
* Remove old test file
* Pass `attributeOptions` from parent to children
* Infer types from zod schema
* Type fixes
* Type fix
* Clean up
* Add i18n strings
* Remove unused file
* Address feedback
* Add migration file
* Address feedback
* Add validation for new integration values
* Remove unused router
* Move away from z.infer to z.ZodType
* Clean up comments
* Type fix
* Type fixes
* Type fix
* fix: add passthrough to syncFormDataSchema to preserve extra fields
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: remove incorrect test that expected extra fields to pass through syncFormDataSchema
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Add indexes
* Add aria label
* Address feedback - consistent validation
* Fix import paths for attribute types
* refactor: change attributeSyncRules array to singular attributeSyncRule
The database schema enforces a one-to-one relationship between
IntegrationAttributeSync and AttributeSyncRule (via @unique constraint),
and the UI only supports a single rule. This change makes the TypeScript
type match the database schema and UI behavior.
Changes:
- Update IntegrationAttributeSync interface to use attributeSyncRule: AttributeSyncRule | null
- Update mapper to return singular rule instead of wrapping in array
- Update UI component to access sync.attributeSyncRule directly
- Update IIntegrationAttributeSyncUpdateParams Omit type
- Update tests to use attributeSyncRule: null instead of attributeSyncRules: []
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: implement FeatureOptInService (#25805)
* feat: implement FeatureOptInService WIP
* clean up
* feat: consolidate feature repositories and add updateFeatureForUser
- Implement updateFeatureForUser in FeaturesRepository (similar to updateFeatureForTeam)
- Move getUserFeatureState and getTeamFeatureState from PrismaFeatureOptInRepository to FeaturesRepository
- Update FeatureOptInService to use only FeaturesRepository
- Add setUserFeatureState and setTeamFeatureState methods to FeatureOptInService
- Update _router.ts to remove PrismaFeatureOptInRepository usage
- Remove PrismaFeatureOptInRepository.ts and FeatureOptInRepositoryInterface.ts
- Update features.repository.interface.ts and features.repository.mock.ts
- Add integration tests for updateFeatureForUser, getUserFeatureState, getTeamFeatureState
- Update service.integration-test.ts to use FeaturesRepository
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: rename updateFeatureForUser to setUserFeatureState
Rename to match the convention used for setTeamFeatureState
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: return FeatureState type from getUserFeatureState and getTeamFeatureState
* fix integration tests
* clean up logics
* update services and router
* refactor: change getUserFeatureState and getTeamFeatureState to accept featureIds array
- Renamed getUserFeatureState to getUserFeatureStates
- Renamed getTeamFeatureState to getTeamFeatureStates
- Changed parameter from featureId: string to featureIds: string[]
- Changed return type from FeatureState to Record<string, FeatureState>
- Updated FeatureOptInService to use the new batch methods
- Added tests for querying multiple features in a single call
- Optimized listFeaturesForTeam to fetch all feature states in one query
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: add getFeatureStateForTeams for batch querying multiple teams
- Added getFeatureStateForTeams method to query a single feature across multiple teams in one call
- Updated FeatureOptInService.resolveFeatureStateAcrossTeams to use the new batch method
- Replaces N+1 queries with a single database query for team states
- Added comprehensive integration tests for the new method
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: combine org and team state queries into single call
- Include orgId in the teamIds array passed to getFeatureStateForTeams
- Extract org state and team states from the combined result
- Reduces database queries from 3 to 2 in resolveFeatureStateAcrossTeams
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: use team.isOrganization and clarify computeEffectiveState comment
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: use MembershipRepository.findAllByUserId with isOrganization
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: add featureId validation using isOptInFeature type guard
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* less queries
* add fallback value
* fix type error
* move files
* add autoOptInFeatures column
* use autoOptInFeatures flag within FeatureOptInService
* add setUserAutoOptIn and setTeamAutoOptIn
* fix computeEffectiveState logic
* rewrite computeEffectiveState
* clean up integration tests
* clean up in afterEach
* fix type error
* refactor: use FeaturesRepository methods instead of direct Prisma calls
Replace all manual userFeatures and teamFeatures Prisma operations with
the new setUserFeatureState and setTeamFeatureState repository methods.
Changes include:
- Admin handlers (assignFeatureToTeam, unassignFeatureFromTeam)
- Test fixtures and integration tests
- Playwright fixtures
- Development scripts
This ensures consistent feature flag management through the repository
pattern and supports the new tri-state semantics (enabled/disabled/inherit).
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* clean up
* fix the logic
* extract some logic into applyAutoOptIn()
* remove wrong code
* refactor: convert setUserFeatureState and setTeamFeatureState to object params with discriminated union
- Convert multiple positional parameters to single object parameter
- Use discriminated union types: assignedBy required for enabled/disabled, omitted for inherit
- Update all callers across repository, service, handlers, fixtures, and tests
* fix type error
* use Promise.all
* fix
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Prevent duplicate field and attribute mappings
* Add validation that attribute belongs to the org
* fix: address Cubic AI review feedback
- Add @@index([credentialId]) to IntegrationAttributeSync model for efficient cascade deletes and credential-based queries (confidence: 9/10)
- Fix translation key from 'credential_required' to 'attribute_sync_credential_required' to match existing locale definition (confidence: 10/10)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: address remaining cubic review feedback
- RuleBuilder.tsx: Use unique IDs for React keys instead of array index to prevent reconciliation bugs when removing conditions
- updateAttributeSync.handler.ts: Add early organization check before service calls for consistency
- createAttributeSync.handler.ts: Add CredentialNotFoundError class for type-safe error handling instead of string matching
- IntegrationAttributeSyncService.test.ts: Replace expect.fail() with proper Vitest rejects.toSatisfy() pattern
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Pull test file from main
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
2026-01-12 22:57:28 +00:00
Anik Dhabal BabuGitHubanik@cal.com <adhabal2002@gmail.com>anik@cal.com <adhabal2002@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: resolve API v2 test flakes by using UUID-only slug
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* fix: add beforeAll cleanup to prevent test flakes from leftover data
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(api): add bookingUrl field to event types API v2 response
Add a new bookingUrl field to EventTypeOutput_2024_06_14 that contains
the full, correct booking URL for each event type. This fixes the issue
where companion app and Chrome extension were hardcoding cal.com URLs
instead of using organization subdomains.
Changes:
- Add bookingUrl field to EventTypeOutput_2024_06_14 type definition
- Update repository to include organization data when fetching users
- Add buildBookingUrl method to compute URL using getOrgFullOrigin
- Include bookingUrl in getResponseEventType return object
The booking URL is computed using the first user's organization slug
(if any) to generate the correct subdomain URL (e.g., i.cal.com/keith/30min
for organization users instead of cal.com/keith/30min).
* fix: include organization data in getEventTypeByIdWithHosts
Update getEventTypeByIdWithHosts to use usersInclude to fetch
organization slug data, ensuring bookingUrl is computed correctly
for the GET /v2/event-types/{eventTypeId} endpoint.
* test: add unit tests and E2E assertions for bookingUrl field
* fix(api-v2): correct bookingUrl format for org users and fix double slashes
Fix issues with bookingUrl field in event types API v2 response:
- Remove trailing slashes from base URLs to prevent double slashes
- Use profile.username instead of user.username for organization users
(profile contains clean username without org suffix)
- Include user profiles in repository queries to access profile data
- Create local org-domains utility to replace @calcom/features dependency
which isn't available in API v2 runtime
Changes:
- Add apps/api/v2/src/lib/org-domains.ts with getOrgFullOrigin function
adapted from @calcom/features/ee/organizations/lib/orgDomains
- Update event-types.repository.ts to include profiles in usersInclude
- Update buildBookingUrl() to prioritize profile data when available
- Update unit tests to cover organization user profile scenarios
Fixes:
- Double slashes in URLs (e.g., http://localhost:3000//user/slug)
- Incorrect username format for org users (e.g., owner1-acme instead
of owner1)
- Missing organization subdomain in booking URLs (e.g., should be
http://acme.localhost:3000/owner1/30min not
http://localhost:3000/owner1-acme/30min)
* deslop ai code
* handle empty username in both code and write test for it, use select instead of include
* feat(api-v2): reuse core org domain logic for event type bookingUrl
Export getOrgFullOrigin and subdomainSuffix from @calcom/platform-libraries/organizations
to reuse existing core logic instead of duplicating it in API v2. This ensures consistency
across the codebase and reduces maintenance burden.
- Export getOrgFullOrigin and subdomainSuffix from platform-libraries/organizations
- Update output-event-types.service to import from @calcom/platform-libraries/organizations
- Remove duplicate org-domains.ts file from API v2
- Update test mocks to use platform-libraries import path
- buildBookingUrl method now uses core getOrgFullOrigin function
This addresses feedback to reuse core code rather than introducing duplicate logic.
* test(api-v2): exclude bookingUrl from output comparison in e2e test
* refactor(api-v2): reuse core logic for event type bookingUrl
Replace duplicated username/org extraction logic in buildBookingUrl with
core functions. Use getBookerBaseUrlSync from @calcom/platform-libraries/organizations
for base URL generation, and add enrichUserWithProfile method that follows
the same pattern as core's UserRepository.enrichUsersWithTheirProfiles.
The enrichment logic is applied synchronously since profiles are already
fetched by the repository, avoiding the need to make the service async.
This ensures consistency with core patterns while maintaining the existing
synchronous API contract.
- Replace getOrgFullOrigin with getBookerBaseUrlSync
- Add enrichUserWithProfile method following core enrichment pattern
- Simplify buildBookingUrl to use enriched user data
- Update tests to mock getBookerBaseUrlSync and verify enrichment flow
* trailing slash cubic comment
* address review comments
* address review comments 2
* better code
* Updated the test to give the user an organization
* address review comments again
* Revert "address review comments again"
This reverts commit 622ea3fc8dcd7f5c3113614afcfc86beadecca0e.
* allow both the full UserWithProfile and the partial EventTypeUser (from select queries) to use the same getUserMainProfile() method, eliminating code duplication without changing the performance-optimized repository queries.
* reveiw points
2026-01-12 14:57:17 -03:00
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add DEVIN_ACTIONS_PAT instructions for pushing to forked PRs
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: simplify PAT instructions to be high-level
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: allow workflow_dispatch to run on draft PRs
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: only process targeted PR when pr_number is provided
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add critical fork PR error handling instruction to stale PR workflow
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>
* use cross-platform rimraf for build scripts
* fix: use cross-platform rimraf for build scripts
* fix: replace cp with npx shx cp for cross-platform compatibility
* Update schema.prisma
2026-01-12 22:56:18 +05:30
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: use pull_request_target for conflict resolver label trigger
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: update if condition to check for pull_request_target event name
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>
resolver validation
- Change git diff from HEAD^1 to HEAD^2 to show PRs contribution
(matches GitHubs Files changed view) instead of what main brought in
- Replace fixed 50-file threshold with relative threshold (original PR files + 10)
- A 20-file PR with 100 files in merge = bad
- A 100-file PR with 108 files in merge = fine
2026-01-12 16:47:08 +00:00
Eunjae LeeGitHubeunjae@cal.com <hey@eunjae.dev>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* docs: add moduleLoader pattern documentation to knowledge-base
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* docs: rewrite DI section to use moduleLoader pattern as primary approach
- Replace manual module loading examples with moduleLoader pattern
- Add Mistake 4 about manual module loading being not type-safe
- Update Core Concepts to explain moduleLoader components
- Show both depsMap (multiple deps) and dep (single dep) usage
- Emphasize build-time type safety throughout
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* docs: extract DI pattern to separate file
- Move DI documentation from knowledge-base.md to di-pattern.md
- Add brief reference in knowledge-base.md pointing to the new file
- Keeps knowledge-base.md focused on quick notes while DI gets its own detailed guide
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-12 15:26:47 +00:00
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Keith WilliamsGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: make OOO team member select close after selection
Replace the custom always-visible scrollable list with a proper Select
component that closes after selection like a normal dropdown. The Select
component uses onMenuScrollToBottom for infinite scroll and onInputChange
for search functionality.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: also convert Team OOO member select to use Select component
Both 'Select team member' sections now use the proper Select component
that closes after selection. Removed unused useInViewObserver import.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: add menuPlacement='bottom' to Team OOO member select
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>
- Update devin-conflict-resolver.yml to check maintainerCanModify for fork PRs
- Instead of skipping fork PRs entirely, now checks if maintainer access is enabled
- Posts friendly comment asking contributors to enable 'Allow edits from maintainers'
- Adds 'maintainer-access-requested' label to track which PRs have been notified
- Update stale-pr-devin-completion.yml to post similar comment when triggered
- Both workflows avoid duplicate comments by checking for existing requests
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>