11610 Commits

Author SHA1 Message Date
Charles Bochet
8838aafd18 Merge branch 'main' into rpl-e2e 2026-04-17 19:28:26 +02:00
Weiko
a18840f3cd Fix deactivated tabs not visible in new tab action (#19811)
## Context
On custom objects, clicking "+ New Tab" on a record page layout never
exposed deactivated tabs for reactivation, even though isActive: false
tabs were correctly returned by the API. Standard objects worked fine.

## Fix
isReactivatableTab gated reactivation on tab.applicationId ===
objectMetadata.applicationId. For custom objects these two ids are
intentionally different.
This check was unnecessary after all, we simply want to check if a tab
is inactive (only non-custom entities can be de-activated) 👍

<img width="694" height="551" alt="Screenshot 2026-04-17 at 18 14 28"
src="https://github.com/user-attachments/assets/42485cb2-8be5-4a55-a311-479ed3226908"
/>
2026-04-17 17:10:14 +00:00
Thomas des Francs
6095798434 Add SVG export and refine halftone studio controls (#19813)
## Summary
- Added image-mode SVG export and clipboard copy support for the
halftone generator.
- Reworked the export panel UX into separate `Download` and `Copy`
sections with format-only buttons.
- Simplified the SVG output to reduce redundant segments while
preserving the rendered result.
- Updated related halftone canvas, state, exporter, and illustration
code to support the new flow.

## Testing
- `yarn nx typecheck twenty-website-new`
- `yarn nx build twenty-website-new`
2026-04-17 16:53:38 +00:00
Weiko
0cb50f8a9d Fix indexFieldMetadata select missing workspaceId (#19806) v1.23.1 2026-04-17 17:34:27 +02:00
github-actions[bot]
47a742fd01 i18n - translations (#19805)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-17 17:09:25 +02:00
martmull
120ced44a9 Fix app design 4 (#19803)
## Before

<img width="1512" height="584" alt="image"
src="https://github.com/user-attachments/assets/2a05d0c7-4bba-438f-9b05-4abd159530ba"
/>
<img width="1512" height="908" alt="image"
src="https://github.com/user-attachments/assets/a36da096-505d-4f25-84bc-a0feca436d53"
/>


## After

<img width="1503" height="574" alt="image"
src="https://github.com/user-attachments/assets/e039b92f-057a-4ed7-869a-a248f446eb2b"
/>
<img width="1512" height="904" alt="image"
src="https://github.com/user-attachments/assets/065767b5-8a70-4ea7-a520-5b2ccbdcffa3"
/>

---------

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
2026-04-17 14:52:41 +00:00
Weiko
3268a86f4b Skip backfill record page layouts for missing standard objects (#19799) v1.23.0 2026-04-17 13:09:11 +00:00
neo773
68746e22a0 Send Email Tool: Don't persist message on SMTP only connections (#19756)
Previously this blocked users who only had SMTP configured to send
outbound emails, this fixes it by making messageChannel and persist
layer conditional
2026-04-17 12:56:38 +00:00
Charles Bochet
4ed6fcd19e chore: move TABLE_WIDGET view type migration to 1.23 fast instance command (#19797)
## Summary

- Relocates `AddTableWidgetViewTypeFastInstanceCommand` from `1-22/` to
`1-23/` and bumps its `@RegisteredInstanceCommand` version from `1.22.0`
to `1.23.0`. The original timestamp `1775752190522` is preserved so the
command slots chronologically into the existing 1.23 sequence;
auto-discovered via `@RegisteredInstanceCommand`, no module wiring
change needed.
- Same pattern as #19792 (move
`pageLayoutWidget.conditionalAvailabilityExpression` to 1.23).
2026-04-17 12:44:35 +00:00
Weiko
e70269b9d3 Fix: aggregate Calculate not updating in dashboard Table widgets (#19796)
## Context
Picking an aggregate option (Count, Sum, Percentage Not Empty, etc.) in
a dashboard Table widget footer did nothing visually — the value never
appeared or updated

## Fix
RecordTableWidget was missing RecordIndexTableContainerEffect, which
reactively syncs currentView.viewFields[].aggregateOperation from the
Apollo cache into the viewFieldAggregateOperationState jotai atom that
the footer reads

<img width="612" height="261" alt="Screenshot 2026-04-17 at 14 17 47"
src="https://github.com/user-attachments/assets/b4409b0e-82a6-4614-bc09-653be738134a"
/>
2026-04-17 12:34:11 +00:00
github-actions[bot]
f94ee2d495 i18n - translations (#19795)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-17 14:15:46 +02:00
Paul Rastoin
bb464b2ffb Forbid other app role extension (#19783)
# Introduction
Even though this would not possible through API at the moment, from
neither API metadata or manifest ( as manifest `permissionsFlag`
declarations etc are done from within a declared role )
Prevent any app to create permissions entities over another app role
from the validation engine itself

## `isEditable`
We might wanna deprecate this column at some point from the entity it
self as now the grain would rather be `what app owns that role ?`

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-04-17 12:00:37 +00:00
Abdul Rahman
a93f23a150 Fix AI chat dropzone persisting when dragging file out without dropping (#19794)
Issue link:
https://discord.com/channels/1130383047699738754/1494248499351519232

### Before


https://github.com/user-attachments/assets/ec4ba8cc-b9e7-4b77-8b8f-b254e11edb19



### After



https://github.com/user-attachments/assets/2905536b-6a31-41e8-9f25-8768fd224b6a
2026-04-17 11:43:02 +00:00
Charles Bochet
beeb8b7406 chore: move pageLayoutWidget.conditionalAvailabilityExpression migration to 1.23 fast instance command (#19792)
## Summary

- Replaces the standalone TypeORM migration
`1775654781000-addConditionalAvailabilityExpressionToPageLayoutWidget.ts`
with a registered fast instance command under
`packages/twenty-server/src/database/commands/upgrade-version-command/1-23/`,
so the `pageLayoutWidget.conditionalAvailabilityExpression` column is
created through the unified upgrade pipeline.
- Uses `ADD COLUMN IF NOT EXISTS` / `DROP COLUMN IF EXISTS` so the new
instance command is a safe no-op for environments that already applied
the previous TypeORM migration.
- Keeps the original timestamp `1775654781000` so the command slots
chronologically into the existing 1.23 sequence; auto-discovered via
`@RegisteredInstanceCommand`, no module wiring needed.

## Context

Reported error when creating a new workspace on `main`:

> column PageLayoutWidgetEntity.conditionalAvailabilityExpression does
not exist

Aligns this column addition with the rest of the 1.23 schema changes
that already use the instance-command pattern.
2026-04-17 11:40:05 +00:00
Weiko
5cd8b7899d shouldIncludeRecordPageLayouts deprecation (#19774)
## Context
Deprecating shouldIncludeRecordPageLayouts in preparation for page
layout release.

See new workspace with standard page layout from standard app
<img width="570" height="682" alt="Screenshot 2026-04-16 at 18 35 23"
src="https://github.com/user-attachments/assets/bf7fa621-d40d-4c29-8d96-537c58b3eb40"
/>
2026-04-17 11:32:10 +00:00
Charles Bochet
76ea0f37ed Surface structured validation errors during application install (#19787)
## Summary
- Add `WorkspaceMigrationGraphqlApiExceptionInterceptor` to
`MarketplaceResolver` and `ApplicationInstallResolver` so validation
failures during app install return `METADATA_VALIDATION_FAILED` with
structured `extensions.errors` instead of generic
`INTERNAL_SERVER_ERROR`
- Update SDK `installTarballApp()` to pass the full GraphQL error object
(including extensions) through the install flow
- Add `formatInstallValidationErrors` utility to format structured
validation errors for CLI output
- Add integration test verifying structured error responses for invalid
navigation menu items and view fields

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 11:29:33 +00:00
Weiko
7aa60fd20b Revert "Fix"
This reverts commit 70603a1af6.
2026-04-17 13:15:57 +02:00
Weiko
70603a1af6 Fix 2026-04-17 13:15:04 +02:00
Marie
b31f84fbb8 fix(server): workspace member permissions and profile onboarding (#19786)
## Summary

Aligns **workspace member** editing and **onboarding** with how the
product is actually used: profile and other “settings” fields go through
**`updateWorkspaceMemberSettings`**, while **`/graphql`** record APIs
follow **object-level** permissions for the `workspaceMember` object.

## Product behaviour

### Completing “Create profile” onboarding

Users who must create a profile (empty name at sign-up) get
`ONBOARDING_CREATE_PROFILE_PENDING` set. The onboarding UI saves the
name with **`updateWorkspaceMemberSettings`**, not with a workspace
record **`updateOne`**.

**Before:** The server only cleared the pending flag on
**`workspaceMember.updateOne`**, so the flag could stay set and
onboarding appeared stuck.

**After:** Clearing the profile step runs when
**`updateWorkspaceMemberSettings`** persists an update that includes a
**name** (same rules as before: non-empty name parts). Onboarding can
advance normally after **Continue** on Create profile.

### Two ways to change workspace member data

| Path | Typical use | Who can change what |
|------|----------------|---------------------|
| **`updateWorkspaceMemberSettings`** (metadata API) | Standard member
fields the app treats as “my profile / preferences” (name,
avatar-related settings, locale, time zone, etc.) | **Always** your
**own** workspace member. Changing **another** member still requires
**Workspace members** in role settings (`WORKSPACE_MEMBERS`). Custom
fields are **not** allowed on this endpoint (unchanged). |
| **`/graphql`** record mutations on **`workspaceMember`** | Custom
fields, integrations, anything that goes through the generic record API
| **`WorkspaceMember`** is special-cased in permissions: **read** stays
**on** for everyone, but **update / create / delete** require
**`WORKSPACE_MEMBERS`**, including updating **your own** row via
`/graphql`. So a **Member** without that permission cannot fix their
name through **`updateWorkspaceMember`**; they use **Settings** /
**`updateWorkspaceMemberSettings`** instead. |

This matches **`WorkspaceRolesPermissionsCacheService`**: for the
workspace member object, `canReadObjectRecords` is always true;
`canUpdateObjectRecords` (and delete-related flags) follow
**`WORKSPACE_MEMBERS`**.

### Hooks and delete side-effects

- Removed **`workspaceMember.updateOne`** pre-query hook and
**`WorkspaceMemberPreQueryHookService`**: they duplicated the same rules
the permission cache already enforces for `/graphql`.
- **`WorkspaceMember.deleteOne`** pre-hook still tells users to remove
members via the dedicated flow; the post-hook only runs the
**`deleteUserWorkspace`** side-effect when a member row is actually
removed—**no** extra settings-permission check there, since only callers
that already passed **object** delete permission can remove the row.

## Tests

- **`workspace-members.integration-spec.ts`**: clarifies and extends
coverage so **`/graphql`** **`updateOne`** is denied for **own** record
on a **standard** name field and on a **custom** field when the role
lacks **`WORKSPACE_MEMBERS`**.

## Implementation notes

- **`OnboardingService.completeOnboardingProfileStepIfNameProvided`**
centralises the “clear profile pending if name present” logic;
**`UserResolver.updateWorkspaceMemberSettings`** calls it after save,
using the typed update payload’s **`name`** (no cast).
- **`UserWorkspaceService.updateUserWorkspaceLocaleForUserWorkspace`**:
drops a redundant **`coreEntityCacheService.invalidate`**;
**`updateWorkspaceMemberSettings`** still invalidates the user-workspace
cache after the mutation.
2026-04-17 09:58:34 +00:00
github-actions[bot]
ba1195d92e i18n - translations (#19784)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-17 09:34:28 +02:00
Abdul Rahman
fcba0ca30a Add search to add column dropdown (#19763)
https://github.com/user-attachments/assets/4a64fff0-6495-4651-934b-43f4ad0dc966
2026-04-17 07:19:07 +00:00
github-actions[bot]
d7453303b8 chore: sync AI model catalog from models.dev (#19782)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-04-17 08:32:09 +02:00
Paul Rastoin
75235f4621 Validate universalIdentifier uniqueness among application and its dependencies (#19767)
# Introduction
Gracefully validating that when creating an entity its
`universalIdentifier` is available within the all application metadata
maps context ( current app + twenty standard, currently the only managed
dependencies )
2026-04-16 16:59:12 +00:00
Devessier
d7154df876 test: add e2e for rpl 2026-04-16 18:14:14 +02:00
Paul Rastoin
bf410ae438 upgrade:status command (#19584)
## Introduction
Introducing a new command in order to determine the curent twenty
instance and workspaces status as it's not stored in database but a
derivation of each current curors


## `upgrade:status` all healthy
<img width="1376" height="1202" alt="image"
src="https://github.com/user-attachments/assets/e90d6987-07d2-4b6b-b573-105249aca325"
/>

## `upgrade:status` Nearly use cases
<img width="1442" height="1304" alt="image"
src="https://github.com/user-attachments/assets/c336cb9d-eb9d-4c7d-9392-ec1ef54a7326"
/>

## `upgrade:status --failed-only`
<img width="1442" height="940" alt="image"
src="https://github.com/user-attachments/assets/93a3dfdb-0d2f-4a01-b185-118e5cf0a078"
/>

## `upgrade:status -w aa8fdcb1-8ee1-4012-98af-44a97caa7411 -w
20202020-1c25-4d02-bf25-6aeccf7ea419 -w
20202020-1c25-4d02-bf25-6aeccf7ea412`
<img width="1486" height="928" alt="image"
src="https://github.com/user-attachments/assets/ec1b1abc-46e8-4e36-9799-ab3a4b85e410"
/>
2026-04-16 16:05:02 +00:00
Etienne
aecbc89a3f Fix slow db query issue (#19770)
https://github.com/twentyhq/twenty/pull/19586#discussion_r3074136617
2026-04-16 15:37:58 +00:00
Thomas Trompette
446a3923f2 Add workspace id in job logs (#19764)
Cannot currently investigate spikes
2026-04-16 15:28:37 +00:00
Félix Malfait
4f4f723ed0 Fix MCP discovery: path-aware well-known URL and protocol version (#19766)
## Summary

Adding `https://api.twenty.com/mcp` as an MCP server in Claude fails
with `Couldn't reach the MCP server` before OAuth can start. Two
independent bugs cause this:

1. **Missing path-aware well-known route.** The latest MCP spec
instructs clients to probe `/.well-known/oauth-protected-resource/mcp`
before `/.well-known/oauth-protected-resource`. Only the root path was
registered, so the path-aware request fell through to
`ServeStaticModule` and returned the SPA's `index.html` with HTTP 200.
Strict clients (Claude.ai) tried to parse it as JSON and gave up. Fixed
by registering both paths on the same handler.
2. **Stale protocol version.** Server advertised `2024-11-05`, which
predates Streamable HTTP. We've implemented Streamable HTTP (SSE
response format was added in #19528), so bumped to `2025-06-18`.

Reproduction before the fix:

```
$ curl -s -o /dev/null -w "%{http_code} %{content_type}\n" https://api.twenty.com/.well-known/oauth-protected-resource/mcp
200 text/html; charset=UTF-8
```

After the fix this returns `application/json` with the RFC 9728 metadata
document.

Note: this is separate from #19755 (host-aware resource URL for
multi-host deployments).

## Test plan

- [x] `npx jest oauth-discovery.controller` — 2/2 tests pass, including
one asserting both routes are registered
- [x] `npx nx lint:diff-with-main twenty-server` passes
- [ ] After deploy, `curl
https://api.twenty.com/.well-known/oauth-protected-resource/mcp` returns
JSON (not HTML)
- [ ] Adding `https://api.twenty.com/mcp` in Claude reaches the OAuth
authorization screen

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 17:32:45 +02:00
Charles Bochet
4103efcb84 fix: replace slow deep-equal with fastDeepEqual to resolve CPU bottleneck (#19771)
## Summary

- Replaced the `deep-equal` npm package with the existing
`fastDeepEqual` from `twenty-shared/utils` across 5 files in the server
and shared packages
- `deep-equal` was causing severe CPU overhead in the record update hot
path (`executeMany` → `formatTwentyOrmEventToDatabaseBatchEvent` →
`objectRecordChangedValues` → `deepEqual`, called **per field per
record**)
- `fastDeepEqual` is ~100x faster for plain JSON database records since
it skips unnecessary prototype chain inspection and edge-case handling
- Removed the now-unnecessary `LARGE_JSON_FIELDS` branching in
`objectRecordChangedValues` since all fields now use the fast
implementation
2026-04-16 17:23:50 +02:00
Félix Malfait
d3df58046c chore(server): drop api-host branch in OAuth discovery (#19768)
## Summary

Follow-up to #19755. Simplifies `OAuthDiscoveryController` by dropping
the `authorization_endpoint → frontend base URL` branch that was there
to make `api.twenty.com/mcp` paste-able in MCP clients.

We've decided not to support pasting `api.twenty.com/mcp` — users can
paste `app.twenty.com/mcp`, `<workspace>.twenty.com/mcp`, or a custom
domain, all of which serve both frontend and API. On those hosts,
`authorization_endpoint` was already pointed at the same host as
`issuer`, which is what we want.

## Change

- Remove `isApiHost` helper and the `authorizeBase` branch — use
`issuer` for `authorization_endpoint`.
- Drop now-unused `TwentyConfigService` and `DomainServerConfigService`
injections.
- Drop duplicate `DomainServerConfigModule` import from
`application-oauth.module.ts` (the module is no longer needed).

Net diff: +1 / -22 across 2 files.

## Breaking change

MCP clients configured with `https://api.twenty.com/mcp` will stop
working. They should be reconfigured with the host matching the
workspace they're connecting to (`<workspace>.twenty.com/mcp`,
`app.twenty.com/mcp`, or a custom domain).

## Test plan

- [x] `yarn jest --testPathPatterns="mcp-auth.guard"` → 2/2 passing
(unchanged)
- [x] `tsc --noEmit` clean on modified files
- [ ] Manual verification on staging: `app.twenty.com/mcp` and
`<workspace>.twenty.com/mcp` OAuth flow still works end-to-end

Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 17:01:55 +02:00
Félix Malfait
cb6953abe3 fix(server): make OAuth discovery and MCP auth metadata host-aware (#19755)
## Summary

OAuth discovery metadata (RFC 9728 protected-resource, RFC 8414
authorization-server) and the MCP `WWW-Authenticate` header were
hardcoded to `SERVER_URL`. This breaks MCP clients that paste any URL
other than `api.twenty.com/mcp` — the metadata declares `resource:
https://api.twenty.com/mcp`, which doesn't match the URL the client
connected to, so the client rejects it and the OAuth flow never starts.

Reproduced with Claude's MCP integration: pasting
`<workspace>.twenty.com/mcp`, `app.twenty.com/mcp`, or a custom domain
returned *"Couldn't reach the MCP server"* because discovery returned a
resource URL for a different host.

Related memory: MCP clients POST to the URL the user entered, not the
discovered resource URL — so every paste-able hostname has to advertise
`resource` for that same hostname.

## What the server now does

`WorkspaceDomainsService.getValidatedRequestBaseUrl(req)` resolves the
canonical base URL for the host the request came in on, validated
against the set of hosts we actually serve:

- `SERVER_URL` (e.g. `api.twenty.com`) — API host
- default base URL (e.g. `app.twenty.com`) — the `DEFAULT_SUBDOMAIN`
base
- `FRONTEND_URL` bare host
- any `<workspace>.twenty.com` subdomain (DB lookup)
- any workspace `customDomain` where `isCustomDomainEnabled = true`
- any registered `publicDomain`

An unrecognized / spoofed Host falls back to
`DomainServerConfigService.getBaseUrl()`. **We never reflect arbitrary
Host values into the response.**

Callers updated:

- `OAuthDiscoveryController.getProtectedResourceMetadata` — echoes the
validated host into `resource` and `authorization_servers`.
- `OAuthDiscoveryController.getAuthorizationServerMetadata` — uses the
validated host for `issuer` and `*_endpoint`, **except**
`authorization_endpoint`: when the request came in via `SERVER_URL`
(API-only, no `/authorize` route), we keep that one pointed at the
default frontend base URL.
- `McpAuthGuard` — sets `WWW-Authenticate: Bearer
resource_metadata=\"<validatedBase>/.well-known/oauth-protected-resource\"`
on 401s, so the MCP client's follow-up discovery fetch lands on the same
host it started on.

## Security

- Workspace identity is already bound to the JWT via per-workspace
signing secrets (`jwtWrapperService.generateAppSecret(tokenType,
workspaceId)`). Host-aware discovery does not weaken that.
- Custom domains are only accepted once `isCustomDomainEnabled = true`
(i.e. after DNS verification), so an attacker can't register a
custom-domain mapping on a workspace and have discovery reflect it
before it's been proven.
- Unknown / spoofed Hosts fall through to the default base URL.

## Drive-by

Fixed a duplicate `DomainServerConfigModule` import in
`application-oauth.module.ts` while adding `WorkspaceDomainsModule`.

## Companion infra change required for custom domains

Customer custom domains (`crm.acme.com/mcp`) also require an
ingress-level fix to exclude `/mcp`, `/oauth`, and `/.well-known` from
the `/s\$uri` rewrite applied when `X-Twenty-Public-Domain: true`.
Shipping that in a twenty-infra PR (will cross-link here).

## Test plan

- [x] 14 new tests in
`WorkspaceDomainsService.getValidatedRequestBaseUrl` covering: missing
Host, SERVER_URL, base URL, FRONTEND_URL, workspace subdomain, unknown
subdomain fallback, enabled custom domain, disabled custom domain,
public domain, completely unrecognized host, lowercase coercion,
malformed Host, single-workspace mode fallback, DB throwing → fallback
- [x] New `oauth-discovery.controller.spec.ts` covering both endpoints
across api / app / workspace-subdomain / custom-domain hosts, plus
`cli_client_id` propagation
- [x] Rewrote `mcp-auth.guard.spec.ts` to cover `WWW-Authenticate` for
all four host types (api, workspace subdomain, custom domain, spoofed
fallback)
- [x] `yarn jest
--testPathPatterns=\"workspace-domains.service|oauth-discovery.controller|mcp-auth.guard\"`
→ 41/41 passing
- [x] `tsc --noEmit` clean on all modified files
- [ ] Manual verification against staging: connect Claude to
`api.twenty.com/mcp`, `app.twenty.com/mcp`,
`<workspace>.twenty.com/mcp`, and a custom domain and confirm OAuth flow
completes on each

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 16:47:42 +02:00
github-actions[bot]
9bc803d0c7 i18n - translations (#19765)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-16 16:17:27 +02:00
Thomas Trompette
cd31d9e0de Add test tab to tool step (#19760)
So we can use those as variables.
When the function input is updated, invalidate the input using an
effect.

<img width="770" height="635" alt="Capture d’écran 2026-04-16 à 14 45
41"
src="https://github.com/user-attachments/assets/cbf0b3e4-baad-424d-8f08-06eb1028abdb"
/>
2026-04-16 14:00:21 +00:00
github-actions[bot]
c0fef0be08 i18n - translations (#19762)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-16 15:14:16 +02:00
Abdul Rahman
270069c3e3 Add search to Fields dropdown (#19750)
Issue link:
https://discord.com/channels/1130383047699738754/1489198502998315100


https://github.com/user-attachments/assets/7d0a859e-c33e-4f9e-bdb3-5867fc0dd80f
2026-04-16 12:59:01 +00:00
Paul Rastoin
2413af0ba9 [run-instance-commands] Preserve fast slow sequentiality (#19757)
# Introduction
The command was wrongly running all fast and then all slow ignoring
instance commands segment
Leading to 
```ts
1.23.0_AddGlobalObjectContextToCommandMenuItemAvailabilityTypeFastInstanceCommand_1776090711153 executed successfully
[Nest] 32679  - 04/16/2026, 1:21:07 PM     LOG [InstanceCommandRunnerService] 1.23.0_DropWorkspaceVersionColumnFastInstanceCommand_1785000000000 executed successfully
[Nest] 32679  - 04/16/2026, 1:21:07 PM     LOG [InstanceCommandRunnerService] 1.22.0_BackfillWorkspaceIdOnIndirectEntitiesSlowInstanceCommand_1775758621018 executed successfully
[Nest] 32679  - 04/16/2026, 1:21:07 PM     LOG [RunInstanceCommandsCommand] Instance commands completed
```

No prod/self host impact as 1.23 hasn't been released yet
2026-04-16 12:14:47 +00:00
Raphaël Bosi
2b5b8a8b13 Link command menu items to specific page layout (#19706)
- Add a `pageLayoutId` foreign key to `CommandMenuItem`, allowing
command menu items to be scoped to a specific page layout instead of
being globally available
- Filter command menu items by the current page layout on the frontend.
Items with a `pageLayoutId` only appear when viewing that layout, while
items without one remain globally visible
- Create an effect to track the current page layout ID
- Include a seed example: a "Show Notification" command pinned to the
Star history standalone page layout

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-04-16 12:07:36 +00:00
github-actions[bot]
7af82fb6a4 i18n - translations (#19758)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-16 13:48:47 +02:00
Félix Malfait
9beb1ca326 Support Select All for workflow manual triggers (#19734)
## Summary
- Move record fetching and payload building from the enrichment hook
into `TriggerWorkflowVersionEngineCommand`, following the same
component-based pattern as `DeleteRecordsCommand` and
`RestoreRecordsCommand`
- The enrichment hook now only stores workflow metadata (`trigger`,
`availabilityType`, `availabilityObjectMetadataId`); the component uses
`useLazyFetchAllRecords` for exclusion mode (Select All) with full
pagination
- `buildTriggerWorkflowVersionPayloads` is now a pure function accepting
`selectedRecords: ObjectRecord[]` instead of reading from the Jotai
store

Fixes the issue introduced by #19718 which blocked Select All with a
warning toast instead of implementing it.

## Test plan
- [ ] Select individual records → run workflow trigger from command menu
→ works as before
- [ ] Click Select All → run workflow trigger from command menu →
fetches all matching records and runs the workflow
- [ ] Select All with some records deselected → correctly excludes those
records
- [ ] Global workflows (no object context) → run without payload as
before
- [ ] Bulk record triggers → payload wraps records in `{namePlural:
[records]}`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 11:33:03 +00:00
Lazare Rossillon
d54092b0e2 fix: add missing LayoutRenderingProvider in SettingsApplicationCustomTab (#19679)
## Summary

- `SettingsApplicationCustomTab` renders `FrontComponentRenderer` which
calls `useFrontComponentExecutionContext` →
`useLayoutRenderingContext()`, but the settings page never provided a
`LayoutRenderingProvider`
- Every other render site (side panel, command menu, record pages) wraps
`FrontComponentRenderer` with this provider — it was just missed here
- Opening the "Custom" tab in Settings → Applications crashes with:
`LayoutRenderingContext Context not found`
- Fix: wrap with `LayoutRenderingProvider` using `DASHBOARD` layout type
and no target record, matching the pattern used in
`SidePanelFrontComponentPage`

## Test plan

- [ ] Open Settings → Applications → any app with a custom settings tab
- [ ] Click the "Custom" tab — should render the front component without
crashing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2026-04-16 10:01:28 +00:00
github-actions[bot]
60701c2cf9 i18n - translations (#19754)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-16 12:03:48 +02:00
martmull
381f3ba7d9 Fix app design 1/2 (#19735)
comply with
https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=96977-349627&m=dev

## After
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 40
37"
src="https://github.com/user-attachments/assets/6d80191a-79a9-4f0f-aa4f-0e447fff4f6d"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 40
22"
src="https://github.com/user-attachments/assets/4f763272-027e-4246-b455-7d46babf7d8c"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 39
11"
src="https://github.com/user-attachments/assets/b9b35e18-8068-447e-821d-5ec28bb5bd16"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 39
05"
src="https://github.com/user-attachments/assets/57d9318a-902f-4fd7-a2a3-5795ebe0b9dc"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 39
02"
src="https://github.com/user-attachments/assets/78a33fa8-6bdd-484e-a82d-bd0f7592a623"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 38
58"
src="https://github.com/user-attachments/assets/f7987aed-c6e1-4032-a611-86817655137d"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 38
55"
src="https://github.com/user-attachments/assets/d1c451ab-1d2d-41e4-a059-cf4303ecabe7"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 38
48"
src="https://github.com/user-attachments/assets/593cae36-2320-443f-a955-93b211a6ee3f"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 37
40"
src="https://github.com/user-attachments/assets/c9f602b1-8de3-4e82-a3a6-344594a0c153"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 37
34"
src="https://github.com/user-attachments/assets/b54ddddf-5dda-46c8-ace3-cffe6015825a"
/>

## before

<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 42
18"
src="https://github.com/user-attachments/assets/c0976a0a-0124-48ec-8e7c-78627cea7063"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 42
16"
src="https://github.com/user-attachments/assets/d2db926c-4040-411d-9091-8b60e7c519e6"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 42
13"
src="https://github.com/user-attachments/assets/2d69f2ff-f26e-4249-91a3-2cf3d261e840"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 42
07"
src="https://github.com/user-attachments/assets/1028aabc-77ac-4c51-a8c3-9a194faba87f"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 42
01"
src="https://github.com/user-attachments/assets/1caa9f5e-3eaa-433c-9d3b-e0f094f16e8e"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 41
56"
src="https://github.com/user-attachments/assets/f42b6976-3a8f-4591-9283-bda79bdb424b"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 41
53"
src="https://github.com/user-attachments/assets/93d00df8-0091-4dfa-9ac0-f6f376be5962"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 41
43"
src="https://github.com/user-attachments/assets/9deae7e5-39c1-4518-a463-6d79bc5bf132"
/>
<img width="1512" height="909" alt="Capture d’écran 2026-04-16 à 09 41
37"
src="https://github.com/user-attachments/assets/3e21b521-c47d-482c-ad41-66abfe973772"
/>
2026-04-16 09:47:44 +00:00
neo773
64470baa1e fix compute folders to update util (#19749)
This regressed with the migration work

Type checker should've caught it, but didn't because of `Partial`
changed it to `Pick` instead to avoid future cases

/closes https://github.com/twentyhq/twenty/issues/19745
2026-04-16 09:09:15 +00:00
Paul Rastoin
f5e8c05267 Add logs before and after instance slow data migration (#19753)
As it can take sometime, would result in not seeing any logs until
2026-04-16 09:08:37 +00:00
Raphaël Bosi
48c540eb6f Add event forwarding stories to the front component renderer (#19721)
Add Storybook stories and example components to test event forwarding
through the front component renderer: form events (text input, checkbox,
focus/blur, submit), keyboard events (key/code/modifiers), and host API
calls (navigate, snackbar, progress, close panel)
2026-04-16 08:55:49 +00:00
Paul Rastoin
5583254f58 Remove workspace-migrations deadcode (#19752)
Was a previous twenty version upgrade command util
2026-04-16 08:52:58 +00:00
Abdullah.
97832af778 [Website] Resolve animations breaking due to renderer context being lost. (#19747)
Resolves the following two issues. The reason we had these issues was
because the maxLimit of renderers was reached and the browser started
losing context before restoring it. Now, we make sure the context that
is lost belongs to visuals that are not currently in the viewport and
when those visuals come back into viewport, they're loaded again.

https://github.com/twentyhq/core-team-issues/issues/2372

https://github.com/twentyhq/core-team-issues/issues/2373
2026-04-16 08:50:56 +00:00
Abdul Rahman
7ce3e2b065 Fix spacing between workspace domain cards (#19742)
https://discord.com/channels/1130383047699738754/1492113564138344468
2026-04-16 08:43:54 +00:00
Abdul Rahman
a49d8386aa Fix calendar event "Not shared" content alignment and background (#19743)
Issue link:
https://discord.com/channels/1130383047699738754/1491712714848866424

<img width="1287" height="419" alt="Screenshot 2026-04-16 at 9 50 34 AM"
src="https://github.com/user-attachments/assets/ba2143df-7957-4aee-8994-80c0392b6086"
/>
2026-04-16 08:38:09 +00:00
Charles Bochet
e420ee8746 Release v1.22.0 for twenty-sdk, twenty-client-sdk, and create-twenty-app (#19751)
## Summary
- Bump `twenty-sdk` from `1.22.0-canary.6` to `1.22.0`
- Bump `twenty-client-sdk` from `1.22.0-canary.6` to `1.22.0`
- Bump `create-twenty-app` from `1.22.0-canary.6` to `1.22.0`
2026-04-16 08:29:50 +00:00