⚠️ Breaking changes
- Gate validation rules behind the record creation form flag (#28004) by @thomtrp
- Verify IMAP and SMTP server certificates by default (#28115) by @charlesBochet
- Stop the New AI Provider form from shadowing built-in providers (#28155) by @etiennejouan
✨ New features
- feat(slack): continue one agent conversation per Slack thread (#27365) by @abdulrahmancodes
- feat: allow API keys to export records (#27941) by @Weiko
- feat(usage-limit): cap an application's credits across all usage (#27998) by @etiennejouan
- feat(cli): add twenty app generate-client (#28015) by @Weiko
- feat(slack): store the agent chat thread on the Slack request (#28070) by @abdulrahmancodes
- feat(billing): support more than two billing plans with server-declared plan switches (#28080) by @etiennejouan
- feat(cli): show where app generate-client saves the client (#28087) by @Weiko
- feat(cli): add a terminal progress bar to human output (#28099) by @Weiko
- feat(cli): show app install progress instead of the job id (#28100) by @Weiko
- feat: show install stats on developer app owner page (#28143) by @martmull
💅 Improvements & UX
- Import the last 31 days of Teams transcripts when an account connects (#27677) by @ehconitin
- Count and import older Teams transcripts on request (#27678) by @ehconitin
- Add an Import history section to the Teams transcripts settings (#27679) by @ehconitin
- Bound code interpreter tokens by the agent's role (#27817) by @prastoin
- Recover SSE live updates after stream teardown and register listeners without delay (#27835) by @thomtrp
- Preserve CodeEditor contracts (#27845) by @bosiraphael
- Stabilize OverflowingList state and focus (#27847) by @bosiraphael
- Let the AI chat create, update and delete agents (#27872) by @FelixMalfait
- [Campaigns 1/2] Polish composer and editor (#27873) by @Bonapara
- Keep record counts right when the server rejects a created record (#27889) by @thomtrp
- Back up morph relation fields with a head row behind a feature flag (#27912) by @charlesBochet
- Let callers choose the agent's output format, starting with workflow AI steps (#27919) by @FelixMalfait
- Keep the run's roles in workflow AI steps without an application (#27925) by @prastoin
- Update Standard, Custom, Call Recorder and Last contact app icons (#27927) by @Bonapara
- Let server routes forward the authorization header (#27934) by @abdulrahmancodes
- Record creation form: Create another (#27937) by @thomtrp
- Complete Toast lifecycle ownership (#27938) by @bosiraphael
- Record creation form: move Edit into the Options menu (#27946) by @thomtrp
- Turn the campaigns INDEX view back into a table and add a list view on top (#27949) by @neo773
- Centralize Dropdown page focus (#27951) by @bosiraphael
- Show the member count on message list record pages (#27952) by @neo773
- Identify the upstream account before saving an app connection (#27954) by @ehconitin
- Measure table cell tooltips in the hover overlay instead of in every cell (#27956) by @charlesBochet
- Marketplace launch UX pass: consent screen, states and copy (#27958) by @martmull
- Use fastDeepEqual when loading records and speed up link detection, formatting and overflowing lists (#27967) by @charlesBochet
- Fix trigger variable paths advertised to workflow AI tools (#27968) by @thomtrp
- Redesign the developer mode switch and let it control the log console (#27969) by @Bonapara
- Virtualize record table columns horizontally (#27970) by @charlesBochet
- Add a lint rule that flags twenty-ui overrides (#27971) by @bosiraphael
- Keep finished workflow runs from being reverted by older query responses (#27972) by @thomtrp
- Let Cmd+J toggle the log console on settings pages (#27973) by @martmull
- Remove the Workflow version column from the workflow runs index (#27974) by @thomtrp
- Remember the log console source across reloads (#27975) by @martmull
- Fix app front component widget showing "No Data" after install (#27976) by @martmull
- Validate runAgent input with the resolver validation pipe (#27979) by @prastoin
- Set application logo only once its file is stored (#27980) by @martmull
- Show linked Teams accounts in Teams chat settings (#27987) by @abdulrahmancodes
- Build twenty-shared before running twenty-oxlint-rules tests (#27988) by @charlesBochet
- Show application logo for app actors in log console (#27989) by @martmull
- Show one actionable admin banner per application configuration issue (#27991) by @martmull
- Fix code step editor cursor jumping to the end while typing (#27994) by @thomtrp
- [Campaigns 2/2] Upgrade existing workspaces (#27995) by @Bonapara
- Let admins remove linked Teams accounts from Teams settings (#27996) by @abdulrahmancodes
- Estimate a Teams history import from the pages that can import a transcript (#27997) by @ehconitin
- Show uninstall progress from 10% instead of 0% (#28002) by @martmull
- Record creation form: reorder fields with drag and drop (#28005) by @thomtrp
- Clean up twenty-ui overrides that render identically (#28006) by @bosiraphael
- Read tool roles from the role permission config only (#28007) by @prastoin
- Rework plan comparison layout on mobile (#28008) by @ijreilly
- Remove the IS_INITIAL_OBJECT_VIEW_ENABLED feature flag (#28009) by @thomtrp
- Explain validation rules with an example in object settings (#28011) by @thomtrp
- Send record events to application workflows without their related records (#28013) by @thomtrp
- Developers settings page, MCP in AI, Logs toggle, and retire Advanced mode (#28016) by @FelixMalfait
- Hide permissions card in app install modal when no permission is requested (#28018) by @martmull
- Add app publishing to npm and private registries (#28019) by @Weiko
- Flag available updates for tarball apps in the installed apps list (#28021) by @martmull
- Show each role's owning app in the roles table (#28022) by @martmull
- Simplify SearchInput slots (#28023) by @bosiraphael
- Show draft tag on email threads regardless of visibility (#28028) by @ijreilly
- Settle app lifecycle jobs that ended while the event stream was down (#28029) by @martmull
- Refetch the footer count when a junction table changes (#28030) by @neo773
- Backfill the head row of existing morph relation fields (#28032) by @charlesBochet
- Fix missing Microsoft Teams app logo (#28038) by @ehconitin
- Let the call recorder set the Recording Bot field on calendar events (#28039) by @ehconitin
- Copy morph relation references onto heads and serve them by flag (#28050) by @charlesBochet
- Open a new event stream when the SSE connection is re-established (#28051) by @thomtrp
- Let Tabs.Panel shrink on the block axis (#28052) by @bosiraphael
- Clean up twenty-ui overrides in cards, forms and buttons (#28054) by @bosiraphael
- Head each chat message with its author in the inbox (#28055) by @FelixMalfait
- Remove the unused actorContext from workflow tools (#28056) by @thomtrp
- Refuse application tokens on core workflow writes (#28058) by @thomtrp
- Fix front scale drift (#28060) by @BOHEUS
- Center Dialog.Description like Dialog.Title (#28063) by @bosiraphael
- Hide anchored tooltips when the anchor is hidden (#28064) by @bosiraphael
- Stop Chip from clipping its start and end elements (#28065) by @bosiraphael
- Document Teams chat setup (#28067) by @abdulrahmancodes
- Fix icon alignment in core object tables (#28071) by @FelixMalfait
- Reserve the standard application universal identifier for registrations (#28074) by @prastoin
- Add comment-sparingly rules to CLAUDE.md (#28075) by @prastoin
- React to AI chat messages with emojis (#28077) by @FelixMalfait
- Let Ada stay silent when a message needs no reply (#28079) by @FelixMalfait
- Restrict workflow run step updates to form values on readable runs (#28095) by @thomtrp
- Select isOnlineMeeting so Teams history finds calendar meetings (#28096) by @ehconitin
- Explain validation rule syntax errors in plain words (#28103) by @thomtrp
- Show recipients a plain page when a tracking or unsubscribe link fails (#28110) by @neo773
- Say which campaign detail is missing when a send is refused (#28111) by @neo773
- Refuse to send a campaign whose list is in the trash (#28112) by @neo773
- Show example values as placeholders for simple fields in the record creation form (#28116) by @thomtrp
- Show example values as placeholders for composite fields in the record creation form (#28117) by @thomtrp
- Ask only for the URL and the email in record form links and emails fields (#28120) by @thomtrp
- Show a placeholder instead of No country, No currency or No calling code in empty form pickers (#28130) by @thomtrp
- Respect user open record preference when front components open records (#28132) by @ehconitin
- Drop shared mailbox mail the upstream provider marked as spam (#28134) by @neo773
- Use table-like currency and phone inputs in record forms (#28137) by @thomtrp
- Check the target application on agent deletion and skill writes (#28139) by @prastoin
- Fix record index crash on view filters on morph relation fields (#28140) by @charlesBochet
- Require STARTTLS and flag invalid mail server certificates (#28141) by @charlesBochet
- Check every morph target join column in empty record filters (#28144) by @charlesBochet
- Fix logo URL parsing (#28150) by @BOHEUS
- Cancel billing before removing members on workspace soft delete (#28152) by @etiennejouan
- Match every morph target join column in relation filters (#28159) by @charlesBochet
- Keep the currency and calling-code picker focus ring visible in forms (#28162) by @thomtrp
🐛 Bug fixes
- fix(front): pre-fill currency field default in record creation form (#27257) by @hussnainahmedd
- fix(i18n): extract the Fields, Chat, Task and Thread tab titles (#27327) by @mmabas77
- fix(i18n): translate Twenty's own labels on custom and application objects (#27328) by @mmabas77
- fix(i18n): translate hard-coded front-end labels (#27331) by @mmabas77
- fix(i18n): translate server-side texts that reach users (#27335) by @mmabas77
- fix(cli): continue with a warning on Node versions newer than the app SDK's range (#27490) by @Weiko
- fix(ai): stop refetching the tool index on every chat step mount (#27689) by @FelixMalfait
- fix(i18n): backfill and enforce Lingui across frontend packages (#28069) by @martmull
- fix(ai-chat): cancel removed AI chat uploads and keep the message when send is refused (#28081) by @etiennejouan
- fix(billing): make direct subscription creation idempotent (#28084) by @etiennejouan
🔧 Developer & API
- Refuse credential-less /graphql requests before validation (#27965) by @charlesBochet
- Fix record exports with CLI OAuth sessions (#27992) by @Weiko
- Restore app translation extraction in the standalone CLI (#28014) by @Weiko
- Test CLI app publishing against a local registry in CI (#28037) by @Weiko
- Add app install to the CLI (#28041) by @Weiko
🏗️ Internal changes (2)
- docs: fix workflow trigger variable paths (#28072) by @thomtrp
- docs: align breach notification FAQ with 72-hour DPA target (#28153) by @FelixMalfait
🎉 New contributors
Full changelog (134 PRs)
- fix(front): pre-fill currency field default in record creation form (#27257) by @hussnainahmedd
- fix(i18n): extract the Fields, Chat, Task and Thread tab titles (#27327) by @mmabas77
- fix(i18n): translate Twenty's own labels on custom and application objects (#27328) by @mmabas77
- fix(i18n): translate hard-coded front-end labels (#27331) by @mmabas77
- fix(i18n): translate server-side texts that reach users (#27335) by @mmabas77
- feat(slack): continue one agent conversation per Slack thread (#27365) by @abdulrahmancodes
- fix(cli): continue with a warning on Node versions newer than the app SDK's range (#27490) by @Weiko
- Import the last 31 days of Teams transcripts when an account connects (#27677) by @ehconitin
- Count and import older Teams transcripts on request (#27678) by @ehconitin
- Add an Import history section to the Teams transcripts settings (#27679) by @ehconitin
- fix(ai): stop refetching the tool index on every chat step mount (#27689) by @FelixMalfait
- Bound code interpreter tokens by the agent's role (#27817) by @prastoin
- i18n - translations (#27822) by @github-actions
- Recover SSE live updates after stream teardown and register listeners without delay (#27835) by @thomtrp
- Preserve CodeEditor contracts (#27845) by @bosiraphael
- Stabilize OverflowingList state and focus (#27847) by @bosiraphael
- Let the AI chat create, update and delete agents (#27872) by @FelixMalfait
- [Campaigns 1/2] Polish composer and editor (#27873) by @Bonapara
- Keep record counts right when the server rejects a created record (#27889) by @thomtrp
- Back up morph relation fields with a head row behind a feature flag (#27912) by @charlesBochet
- Let callers choose the agent's output format, starting with workflow AI steps (#27919) by @FelixMalfait
- Keep the run's roles in workflow AI steps without an application (#27925) by @prastoin
- Update Standard, Custom, Call Recorder and Last contact app icons (#27927) by @Bonapara
- Let server routes forward the authorization header (#27934) by @abdulrahmancodes
- Record creation form: Create another (#27937) by @thomtrp
- Complete Toast lifecycle ownership (#27938) by @bosiraphael
- feat: allow API keys to export records (#27941) by @Weiko
- Record creation form: move Edit into the Options menu (#27946) by @thomtrp
- Turn the campaigns INDEX view back into a table and add a list view on top (#27949) by @neo773
- Centralize Dropdown page focus (#27951) by @bosiraphael
- Show the member count on message list record pages (#27952) by @neo773
- Identify the upstream account before saving an app connection (#27954) by @ehconitin
- Measure table cell tooltips in the hover overlay instead of in every cell (#27956) by @charlesBochet
- Marketplace launch UX pass: consent screen, states and copy (#27958) by @martmull
- Refuse credential-less /graphql requests before validation (#27965) by @charlesBochet
- Use fastDeepEqual when loading records and speed up link detection, formatting and overflowing lists (#27967) by @charlesBochet
- Fix trigger variable paths advertised to workflow AI tools (#27968) by @thomtrp
- Redesign the developer mode switch and let it control the log console (#27969) by @Bonapara
- Virtualize record table columns horizontally (#27970) by @charlesBochet
- Add a lint rule that flags twenty-ui overrides (#27971) by @bosiraphael
- Keep finished workflow runs from being reverted by older query responses (#27972) by @thomtrp
- Let Cmd+J toggle the log console on settings pages (#27973) by @martmull
- Remove the Workflow version column from the workflow runs index (#27974) by @thomtrp
- Remember the log console source across reloads (#27975) by @martmull
- Fix app front component widget showing "No Data" after install (#27976) by @martmull
- chore: bump version to 2.48.0 (#27978) by @twenty-pr
- Validate runAgent input with the resolver validation pipe (#27979) by @prastoin
- Set application logo only once its file is stored (#27980) by @martmull
- Show linked Teams accounts in Teams chat settings (#27987) by @abdulrahmancodes
- Build twenty-shared before running twenty-oxlint-rules tests (#27988) by @charlesBochet
- Show application logo for app actors in log console (#27989) by @martmull
- Show one actionable admin banner per application configuration issue (#27991) by @martmull
- Fix record exports with CLI OAuth sessions (#27992) by @Weiko
- Fix code step editor cursor jumping to the end while typing (#27994) by @thomtrp
- [Campaigns 2/2] Upgrade existing workspaces (#27995) by @Bonapara
- Let admins remove linked Teams accounts from Teams settings (#27996) by @abdulrahmancodes
- Estimate a Teams history import from the pages that can import a transcript (#27997) by @ehconitin
- feat(usage-limit): cap an application's credits across all usage (#27998) by @etiennejouan
- Show uninstall progress from 10% instead of 0% (#28002) by @martmull
- Gate validation rules behind the record creation form flag (#28004) by @thomtrp
- Record creation form: reorder fields with drag and drop (#28005) by @thomtrp
- Clean up twenty-ui overrides that render identically (#28006) by @bosiraphael
- Read tool roles from the role permission config only (#28007) by @prastoin
- Rework plan comparison layout on mobile (#28008) by @ijreilly
- Remove the IS_INITIAL_OBJECT_VIEW_ENABLED feature flag (#28009) by @thomtrp
- Explain validation rules with an example in object settings (#28011) by @thomtrp
- Send record events to application workflows without their related records (#28013) by @thomtrp
- Restore app translation extraction in the standalone CLI (#28014) by @Weiko
- feat(cli): add twenty app generate-client (#28015) by @Weiko
- Developers settings page, MCP in AI, Logs toggle, and retire Advanced mode (#28016) by @FelixMalfait
- Hide permissions card in app install modal when no permission is requested (#28018) by @martmull
- Add app publishing to npm and private registries (#28019) by @Weiko
- Flag available updates for tarball apps in the installed apps list (#28021) by @martmull
- Show each role's owning app in the roles table (#28022) by @martmull
- Simplify SearchInput slots (#28023) by @bosiraphael
- Show draft tag on email threads regardless of visibility (#28028) by @ijreilly
- Settle app lifecycle jobs that ended while the event stream was down (#28029) by @martmull
- Refetch the footer count when a junction table changes (#28030) by @neo773
- Backfill the head row of existing morph relation fields (#28032) by @charlesBochet
- Test CLI app publishing against a local registry in CI (#28037) by @Weiko
- Fix missing Microsoft Teams app logo (#28038) by @ehconitin
- Let the call recorder set the Recording Bot field on calendar events (#28039) by @ehconitin
- Add app install to the CLI (#28041) by @Weiko
- Copy morph relation references onto heads and serve them by flag (#28050) by @charlesBochet
- Open a new event stream when the SSE connection is re-established (#28051) by @thomtrp
- Let Tabs.Panel shrink on the block axis (#28052) by @bosiraphael
- Clean up twenty-ui overrides in cards, forms and buttons (#28054) by @bosiraphael
- Head each chat message with its author in the inbox (#28055) by @FelixMalfait
- Remove the unused actorContext from workflow tools (#28056) by @thomtrp
- Refuse application tokens on core workflow writes (#28058) by @thomtrp
- Fix front scale drift (#28060) by @BOHEUS
- Center Dialog.Description like Dialog.Title (#28063) by @bosiraphael
- Hide anchored tooltips when the anchor is hidden (#28064) by @bosiraphael
- Stop Chip from clipping its start and end elements (#28065) by @bosiraphael
- Document Teams chat setup (#28067) by @abdulrahmancodes
- fix(i18n): backfill and enforce Lingui across frontend packages (#28069) by @martmull
- feat(slack): store the agent chat thread on the Slack request (#28070) by @abdulrahmancodes
- Fix icon alignment in core object tables (#28071) by @FelixMalfait
- docs: fix workflow trigger variable paths (#28072) by @thomtrp
- Reserve the standard application universal identifier for registrations (#28074) by @prastoin
- Add comment-sparingly rules to CLAUDE.md (#28075) by @prastoin
- React to AI chat messages with emojis (#28077) by @FelixMalfait
- Let Ada stay silent when a message needs no reply (#28079) by @FelixMalfait
- feat(billing): support more than two billing plans with server-declared plan switches (#28080) by @etiennejouan
- fix(ai-chat): cancel removed AI chat uploads and keep the message when send is refused (#28081) by @etiennejouan
- fix(billing): make direct subscription creation idempotent (#28084) by @etiennejouan
- feat(cli): show where app generate-client saves the client (#28087) by @Weiko
- Restrict workflow run step updates to form values on readable runs (#28095) by @thomtrp
- Select isOnlineMeeting so Teams history finds calendar meetings (#28096) by @ehconitin
- feat(cli): add a terminal progress bar to human output (#28099) by @Weiko
- feat(cli): show app install progress instead of the job id (#28100) by @Weiko
- Explain validation rule syntax errors in plain words (#28103) by @thomtrp
- Show recipients a plain page when a tracking or unsubscribe link fails (#28110) by @neo773
- Say which campaign detail is missing when a send is refused (#28111) by @neo773
- Refuse to send a campaign whose list is in the trash (#28112) by @neo773
- Verify IMAP and SMTP server certificates by default (#28115) by @charlesBochet
- Show example values as placeholders for simple fields in the record creation form (#28116) by @thomtrp
- Show example values as placeholders for composite fields in the record creation form (#28117) by @thomtrp
- Ask only for the URL and the email in record form links and emails fields (#28120) by @thomtrp
- Show a placeholder instead of No country, No currency or No calling code in empty form pickers (#28130) by @thomtrp
- Respect user open record preference when front components open records (#28132) by @ehconitin
- Drop shared mailbox mail the upstream provider marked as spam (#28134) by @neo773
- Use table-like currency and phone inputs in record forms (#28137) by @thomtrp
- Check the target application on agent deletion and skill writes (#28139) by @prastoin
- Fix record index crash on view filters on morph relation fields (#28140) by @charlesBochet
- Require STARTTLS and flag invalid mail server certificates (#28141) by @charlesBochet
- feat: show install stats on developer app owner page (#28143) by @martmull
- Check every morph target join column in empty record filters (#28144) by @charlesBochet
- Fix logo URL parsing (#28150) by @BOHEUS
- Cancel billing before removing members on workspace soft delete (#28152) by @etiennejouan
- docs: align breach notification FAQ with 72-hour DPA target (#28153) by @FelixMalfait
- Stop the New AI Provider form from shadowing built-in providers (#28155) by @etiennejouan
- Match every morph target join column in relation filters (#28159) by @charlesBochet
- Keep the currency and calling-code picker focus ring visible in forms (#28162) by @thomtrp
Full Changelog: twenty/v2.47.0...twenty/v2.48.0