* feat: add organization.passwordReset PBAC permission
Allow org admins/owners to reset passwords for members of their
organization via a new PBAC permission. Previously this was only
available to system-level admins.
- Add PasswordReset to CustomAction enum and PERMISSION_REGISTRY
- Create migration to grant permission to admin_role (owner has wildcard)
- Add org-scoped tRPC endpoint using createOrgPbacProcedure
- Handler validates org membership, prevents self-targeting, and blocks
resetting owner passwords
- Wire permission through MemberPermissions, getOrgMembersPageData, and
the org members table UI dropdown
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use targeted select in org password reset to avoid over-fetching
Replace findById with findForPasswordReset repository method that only
selects email, name, and locale instead of the full userSelect which
includes sensitive fields like twoFactorSecret and backupCodes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: add unit tests for sendPasswordReset handler
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## What does this PR do?
Adds a `displayLocations` property to the `OptInFeatureConfig` interface to control where opt-in features are displayed (settings page, banner, or both), and applies this filtering at the callers' side.
## How to test locally
```
update "Feature" set enabled = true where slug='bookings-v3';
```
Run it to globally enable the flag, and then go to the settings page to see the "Features" menu.
---
**Changes:**
- Added `OptInFeatureDisplayLocation` type with values `"settings"` | `"banner"`
- Added optional `displayLocations` property to `OptInFeatureConfig` interface
- Added helper functions:
- `getFeatureDisplayLocations()` - returns display locations with default of `['settings']`
- `shouldDisplayFeatureAt()` - checks if a feature should display at a specific location
- `getOptInFeaturesForLocation()` - filters features by location
- Updated `getOptInFeaturesForScope()` to accept an optional `displayLocation` parameter for filtering
- Simplified `HAS_*_OPT_IN_FEATURES` constants to use `getOptInFeaturesForScope(scope, "settings").length > 0`
- Updated `FeatureOptInService.listFeaturesForUser()` to filter by 'settings' location
- Updated `FeatureOptInService.listFeaturesForTeam()` to filter by 'settings' location
- Updated `useFeatureOptInBanner` hook to check for 'banner' location before showing
**Default behavior:** If `displayLocations` is omitted, features default to `['settings']` only.
## Mandatory Tasks (DO NOT REMOVE)
- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - internal config change only.
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works.
## How should this be tested?
1. Verify the helper functions work as expected:
- `getFeatureDisplayLocations({ slug: "test", ... })` should return `["settings"]` (default)
- `getFeatureDisplayLocations({ slug: "test", displayLocations: ["banner"] })` should return `["banner"]`
- `shouldDisplayFeatureAt(feature, "settings")` should return `true` for features without `displayLocations`
- `getOptInFeaturesForScope("user", "banner")` should only return user-scoped features with `"banner"` in their `displayLocations`
2. Verify caller-side filtering:
- `listFeaturesForUser()` and `listFeaturesForTeam()` should only return features with 'settings' in displayLocations
- Banner hook should only show features with 'banner' in displayLocations
- `HAS_*_OPT_IN_FEATURES` constants should only be true if there are features with 'settings' location
## Checklist
- [x] My code follows the style guidelines of this project
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] My changes generate no new warnings
---
### Human Review Checklist
- [ ] Verify the default behavior (defaulting to `['settings']`) matches requirements
- [ ] Confirm the filtering logic is applied correctly in all callers (service methods, banner hook, constants)
- [ ] Verify the banner hook correctly prevents showing features without 'banner' in displayLocations
- [ ] Note: The test mock returns all features regardless of `displayLocation` parameter - the filtering logic in `getOptInFeaturesForScope` isn't directly tested. Consider if this is acceptable or if tests should be added.
**Link to Devin run:** https://app.devin.ai/sessions/a064ee43a56d458caf2892b55959f1ea
**Requested by:** @eunjae-lee
2026-01-29 10:17:50 +01:00
Hariom BalharaGitHubhariom@cal.com <hariombalhara@gmail.com>hariom@cal.com <hariombalhara@gmail.com>hariom@cal.com <hariombalhara@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add image resizing endpoint for organization onboarding
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* chore: add translation keys for image upload errors
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: rename endpoint to resizeBase64Image with imageType enum and Zod validation
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: use ImageUploader and BannerUploader components for organization brand onboarding
Replace server-side image resizing endpoint with client-side cropping using existing ImageUploader and BannerUploader components. This approach:
- Avoids sending large base64 payloads to the server (preventing 413 errors)
- Provides better UX with cropping functionality
- Aligns with team onboarding which already uses ImageUploader
- Removes unnecessary server-side code
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Revert formatting change
* fix: correct max file size from 10mb to 5mb in translations
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Add Remove bvutton too
* fix: correct banner dimension, indentation, and import order
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-29 08:55:13 +00:00
+3
Alex van AndelGitHubalex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* chore: Disables syncing of calendarList on overlay calendar fetch
* Unwrap ToggledConnectedCalendars
* Pick the right type for connectedCalendars
* further type amends
* Type fixes, tons of em
* Some further fixups consistent with what was before
* fix: resolve type incompatibility in getConnectedDestinationCalendars return type
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: update DestinationCalendarProps to accept tRPC handler return type
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: use generic type for DestinationCalendarProps to accept tRPC enriched types
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: simplify DestinationCalendarProps type for better compatibility
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: export ConnectedCalendar type for consistent type inference
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: use permissive type for connectedCalendars to accept tRPC enriched types
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: export ConnectedCalendar and ConnectedDestinationCalendars types from platform-libraries
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: update ConnectedCalendar type to use boolean | null for primary field
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* Update ConnectedCalendarItem
* Undo some of Devins fixes, more fixes
* Fixup the destination calendar return type, historically not null
* Change init to undefined to deal with null
* Approach to connect selected calendars with the right credential
* This return type is used way too much everywhere, not refactoring
* Add the selectedCalendars to the type
* Actually fix overlay calendar
* set calendarsToLoad param as required
* Apply suggestion from @cubic-dev-ai[bot]
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* Add new translation for 'Calendar Settings'
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Alex van AndelGitHubalex@cal.com <me@alexvanandel.com>alex@cal.com <me@alexvanandel.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: lazy load KBar data fetching hooks only when opened
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* refactor: move KBar data fetching into RenderResults for proper lazy loading
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: remove sticky positioning from page headers in pages using ShellMain
* correct fix (mostly)
* fix: disable sticky headers on routing forms and members pages
Applied disableSticky={true} to remaining affected pages:
- Routing Forms page
- Organization Members view
- Platform Members view
---------
Co-authored-by: Dhairyashil <dhairyashil10101010@gmail.com>
* wip flow
* add tests
* WIP migrateing view
* push back step
* fix tests and logic for adding new members to existing teams
* few UI fixes
* type fixes
* fix nits
* few UI + re-route fixes
* fix teamId when migrating
2026-01-26 17:03:12 +01:00
Benny JooGitHubbenny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: move booking-audit client components from packages/features to apps/web/modules
This is part of the larger effort to move tRPC-dependent UI components from packages/features to apps/web/modules to eliminate circular dependencies.
Changes:
- Move BookingHistory.tsx and BookingHistoryPage.tsx to apps/web/modules/booking-audit/components/
- Update imports in apps/web to use the new location
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: move formbricks client from packages/features to apps/web/modules
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: move hooks and stores from packages/features to apps/web/modules
- Move useAppsData hook from packages/features/apps/hooks to apps/web/modules/apps/hooks
- Move onboardingStore from packages/features/ee/organizations/lib to apps/web/modules/ee/organizations/lib
- Move useWelcomeModal hook from packages/features/ee/organizations/hooks to apps/web/modules/ee/organizations/hooks
- Move useAgentsData hook from packages/features/ee/workflows/hooks to apps/web/modules/ee/workflows/hooks
- Update all import paths in consuming files
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: move onboardingStore test file to apps/web/modules
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-26 13:11:14 +00:00
Benny JooGitHubbenny@cal.com <sldisek783@gmail.com>benny@cal.com <sldisek783@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: save progress
* chore:
* feat: add input dialog
* fix: type error
* feat: mass apply dialog
* test: per host location
* test: fix test
* fix: address Cubic AI review feedback (confidence >= 9/10)
- Remove PII (address, phone number) from tracing logs in RegularBookingService.ts
- Constrain HostLocation.type to EventLocationType["type"] for compile-time validation
Co-Authored-By: unknown <>
* fix: translation
* refactor: improvements
* fix: correct grammar in custom host locations tooltip
Change 'custom host locations is enabled' to 'custom host locations are enabled' (plural subject requires plural verb).
Addresses Cubic AI review feedback (confidence 9/10).
Co-Authored-By: unknown <>
* refactor: improvements
* fix: auth
* fix: check
* refactor: improvements
* fix: address Cubic AI review feedback (confidence >= 9/10)
- Add scheduleId to newly created hosts in update.handler.ts to persist
host-specific schedules during create operations
- Change host location deletion filter from !host.location to
host.location === null to only delete when explicitly set to null
- Fix static-link per-host locations to use actual link instead of type
in locationBodyString for bookingLocationService.ts
Co-Authored-By: unknown <>
* fix: preserve existing host scheduleId when not explicitly provided
Change scheduleId handling for existing hosts from 'host.scheduleId ?? null'
to 'host.scheduleId === undefined ? undefined : host.scheduleId' so that
when the client doesn't provide a scheduleId, the existing value is preserved
instead of being cleared to null.
Co-Authored-By: unknown <>
* fix; type erro
* fix; type erro
* fix; type erro
* refactor: move repository
* refactor: move repository
* fix: add singular/plural translations for location_applied_to_hosts
Addresses Cubic AI review feedback (confidence 9/10) to fix '1 hosts' rendering as '1 host' by using i18next plural format with _one and _other suffixes.
Co-Authored-By: unknown <>
* refactor: feedback
* fix: type err
* fix: use uuid in schema and remove attendee locaiton
* fix: type err
* fix: type err
* fix: validate eventTypeId as integer in massApplyHostLocation schema
Co-Authored-By: unknown <>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-23 11:18:43 -03:00
Eunjae LeeGitHubunknown <>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>
* fix(coss-ui): convert /settings/my-account/general to coss-ui
* update guide
* fix: add menuPosition fixed to TimezoneSelect in TravelScheduleModal
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: use menuPortalTarget to render TimezoneSelect dropdown above dialog footer
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: use Object.assign for type-safe styles in TimezoneSelect
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* revert comment
* fix: guard document access for SSR in TravelScheduleModal
Addresses Cubic AI review feedback: menuPortalTarget={document.body} will
throw during server rendering where document is undefined. Added typeof
check to guard against SSR.
Co-Authored-By: unknown <>
* change dialog backdrop from blur to dim
* fix: add menuPlacement auto to open dropdown upward on mobile
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: use menuPlacement top on mobile for TimezoneSelect dropdown
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: make timezone button stack vertically on mobile to prevent overflow
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: make timezone select and button 50/50 width on larger viewports
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix date range picker issue on mobile
* prevent travel schedule dialog dismissal with date picker
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-23 11:19:00 +00:00
Eunjae LeeGitHubeunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>eunjae@cal.com <hey@eunjae.dev>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: allow normal users to see userId filter with only themselves as option
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: return empty map when canReadOthersBookings is false and currentUser doesn't exist
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: use generic type parameter for Table to fix type compatibility
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* perf: disable listSimpleMembers query when canReadOthersBookings is false
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: move organization members page from /settings/organizations/members to /members
- Create new /members route under main-nav with same functionality
- Add permanent redirect from /settings/organizations/members to /members
- Include loading skeleton and server actions for the new route
Co-Authored-By: peer@cal.com <peer@cal.com>
* refactor: Deduplicate organization members page logic (#27168)
* refactor(web): extract shared org members data fetching logic
- Extract data fetching, coaching, and permission logic into [getOrgMembersPageData.ts](cci:7://file:///Users/dhairyashilshinde/work/cal.com/apps/web/modules/members/getOrgMembersPageData.ts:0:0-0:0)
- Deduplicate logic between [/members](cci:7://file:///Users/dhairyashilshinde/work/cal.com/apps/web/app/%28use-page-wrapper%29/%28main-nav%29/members:0:0-0:0) and pages
- Reduce page component size and improve maintainability
* safe guard for org id null
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com>
2026-01-22 22:43:34 +00:00
Peer RichelsenGitHubpeer@cal.com <peer@cal.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fixed text issue
* matched style of api keys page
* made changes to the upgradetip
* made changes to the upgradetip
* made changes to the upgradetip
* Refactor TextField component properties
---------
Co-authored-by: Pallav <90088723+pallava-joshi@users.noreply.github.com>
2026-01-22 19:14:39 +00:00
Peer RichelsenGitHubpeer@cal.com <peer@cal.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add assigned badge to team event types
Add an 'Assigned' badge to Round Robin and Collective event types
when the current user is a host/participant of the event type.
This provides visibility to users without edit permissions that
they are included in the rotation.
Changes:
- Add isCurrentUserHost flag in getEventTypesFromGroup handler
- Display blue 'Assigned' badge in event types listing view
- Add i18n translation for 'assigned' text
Co-Authored-By: ali@cal.com <ali@cal.com>
* refactor: remove redundant isTeamEvent check for assigned badge
Co-Authored-By: ali@cal.com <ali@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ali@cal.com <ali@cal.com>