Commit Graph
10264 Commits
Author SHA1 Message Date
e2b9bc935f Add mentions feature to objects in notes (#16373)
Issue #15755 

### Context
As shown in the issue, users should be able to @ objects and have it be
linked to their associated page.

### Changes Made
- Updated the BlockNote schema to include the newly created
MentionInlineContent that displays an object using a RecordChip
- Added the UI for the menu that appears to select the requested object
(similar to this example:
https://www.blocknotejs.org/examples/ui-components/suggestion-menus-slash-menu-component)
- Added a hook to retrieve the data for the UI
- Added the @ trigger to the block editor

### Result 

https://github.com/user-attachments/assets/87dae6a2-ad7a-4642-80b2-8b1751feae24

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-13 13:12:37 +00:00
nitinandGitHub b7c1d47273 chore(nx): remove leftover Nx wrapper artifacts (#17916)
#17147 removed the root ./nx script, but wrapper-mode artifacts were
still present (installation in
[nx.json](https://github.com/twentyhq/twenty/blob/main/nx.json) and
tracked
[nxw.js](https://github.com/twentyhq/twenty/blob/main/.nx/nxw.js),
leaving an inconsistent setup.

This PR completes that cleanup by:

- removing installation from nx.json
- deleting tracked nxw.js
- ignoring nxw.js to prevent accidental re-introduction

Validated that Nx still works via yarn nx / npx nx.
2026-02-13 13:04:43 +00:00
befbcef824 fix: prevent tab synchronization between different records (#17559)
Fixes issue where tabs were synchronized when opening two records of the
same type in show page and side panel.

The root cause was that tab instance IDs were only based on
`pageLayoutId`, causing all records using the same page layout to share
the same tab state.

This change includes the record ID in the tab instance ID, making tabs
unique per record while maintaining backward compatibility for cases
where no record ID is available.

Fixes #17522

---------

Co-authored-by: Eruis <github@eruis.example>
2026-02-13 13:04:07 +00:00
Baptiste DevessierandGitHub 83b800a077 Drag and drop fields of Fields widgets (#17910)
https://github.com/user-attachments/assets/97fad3f3-8654-4216-b58c-b7411119c8ce
2026-02-13 11:41:25 +00:00
CopilotGitHubcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>DevessierBaptiste Devessier
d08c098065 Hide delete button for record page layout widgets (#17892)
## Before


https://github.com/user-attachments/assets/ea04e8cc-a445-498d-b0d0-d3230a9eeec8

## After


https://github.com/user-attachments/assets/c88aead2-2d3a-42ec-8829-7595a4faa116

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Devessier <29370468+Devessier@users.noreply.github.com>
Co-authored-by: Baptiste Devessier <baptiste@devessier.fr>
2026-02-13 11:19:06 +00:00
Paul RastoinandGitHub d88fa0cb2b Migrate create syncable entity cursor rule to skills (#17912)
# Introduction
Splitting the create syncable entity rule into dedicated scoped skills
in order to favorise multi agent pattern with more granular context

### Multi-Agent Workflow

For parallel development:
1. **Agent 1** (Foundation): Complete Step 1 first - unblocks everyone
2. **Agent 2** (Cache): Can start immediately after Step 1
3. **Agent 3** (Builder): Can work in parallel with Agent 4 after Step 1
4. **Agent 4** (Runner): Can work in parallel with Agent 3 after Step 1
5. **Agent 5** (Integration): Assembles everything after Steps 2-4
2026-02-13 11:18:31 +00:00
216a7331f8 Speed up twenty-emails build by replacing vite-plugin-dts with tsgo (#17857)
## Summary

- Removed `vite-plugin-dts` (which used `tsc` internally) from the Vite
build and replaced DTS generation with `tsgo` as a sequential post-build
step — **~0.7s vs 1-10s**.
- Disabled `reportCompressedSize` to skip gzip computation for 64 output
files.
- Converted the build target to an explicit `nx:run-commands` executor
with sequential `vite build` → `tsgo` commands.

The `twenty-emails:build` step goes from ~22s to ~7s under load. 

## Test plan

- [x] `nx build twenty-emails` produces both JS (64 files) and DTS (74
files) correctly
- [x] `dist/index.d.ts` exports match the source `src/index.ts`
- [x] Full `nx build twenty-server` succeeds end-to-end
- [ ] CI build passes


Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-13 10:39:26 +00:00
975c64bf3d i18n - translations (#17911)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-13 11:20:56 +01:00
Paul RastoinandGitHub b34f7bcb33 Refactor metadata events to contain scalarEntity (#17908)
# Introduction
Avoid sending flat entity that contains server specific properties such
as foreignKey aggregators and universal properties by transpiling from
flat entity to scalar flat entity

A scalar flat entity is the exact match with the entities columns

Following https://github.com/twentyhq/twenty/pull/17622
2026-02-13 10:01:54 +00:00
14e8c869be i18n - translations (#17905)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-13 10:54:25 +01:00
Félix MalfaitGitHubCursorcubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
21c51ec251 Improve AI agent chat, tool display, and workflow agent management (#17876)
## Summary

- **Fix token renewal endpoint**: Use `/metadata` instead of `/graphql`
for token renewal in agent chat, fixing auth issues
- **Improve tool display**: Add `load_skills` support, show formatted
tool names (underscores → spaces) with finish/loading states, display
tool icons during loading, and support custom loading messages from tool
input
- **Refactor workflow agent management**: Replace direct
`AgentRepository` access with `AgentService` for create/delete/find
operations in workflow steps, improving encapsulation and consistency
- **Simplify Apollo client usage**: Remove explicit Apollo client
override in `useGetToolIndex`, add `AgentChatProvider` to
`AppRouterProviders`
- **Fix load-skill tool**: Change parameter type from `string` to `json`
for proper schema parsing
- **Update agent-chat-streaming**: Use `AgentService` for agent
resolution and tool registration instead of direct repository queries

## Test plan

- [ ] Verify AI agent chat works end-to-end (send message, receive
response)
- [ ] Verify tool steps display correctly with icons and proper messages
during loading and after completion
- [ ] Verify workflow AI agent step creation and deletion works
correctly
- [ ] Verify workflow version cloning preserves agent configuration
- [ ] Verify token renewal works when tokens expire during agent chat


Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-02-13 09:27:38 +00:00
MarieandGitHub 5c3c2e08a6 Some fixes (#17904) 2026-02-13 09:23:14 +00:00
fdb5d2fbcd Feat 17408 : Add remove option for object permissions rule (#17601)
This PR aims to fix: #17408 

Main modification includes adding a new column for dropdown in the
object permission rule table (containing options for editing and
removal). Removal logic is implemented using existing pattern with hook
```useResetObjectPermission``` (relies on existing hooks
```useUpsertFieldPermissionInDraftRole``` and
```useUpsertObjectPermissionInDraftRole```).

Feel free to suggest any necessary changes. Functionality (unrestricted
access is allowed when permission removal is applied) is already tested.

Demo video:
https://drive.google.com/file/d/1M4RYHw-JEhDdJksKkL3MY_VyXAV3aS9I/view?usp=sharing

---------

Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2026-02-13 09:16:36 +00:00
EtienneandGitHub 5c2c588885 Files - Migrate attachments in activities (#17808)
As attachment files have migrated from fullPath to file files field,
need to migrate richText logic to fit to new attachment file handling +
data migration
2026-02-13 09:11:23 +00:00
MarieandGitHub 90a30263ac [Apps] Content + permission tabs for marketplace and installed apps (#17888)
In this PR
- Content tab for marketplace apps and installed apps: complies with
[figma](https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=34845-126856);
addition of field section showing fields added to standard objects;
initiative: arrow opens a sub-table of fields rows. (suggested because
1/ for marketplace apps we cannot redirect to the actual object page in
settings since the object does not exist yet in the workspace 2/ since
we dont have an quick "go back to application page" option, it can be
annoying to be redirected to a different setting page when we just want
to look at the content of the app objects)
- Permission tab for marketplace apps and installed apps
- left to do - settings tab (in another PR)

There are breaking changes but it's behind a feature flag not exposed
(access to marketplace) so not problematic


marketplace apps

https://github.com/user-attachments/assets/4c660101-50fc-47ce-b90a-8d6f17db5e74

installed apps

https://github.com/user-attachments/assets/c9229ee1-e75f-4cad-8766-758b2c5b37b4
2026-02-12 17:38:53 +00:00
13c2234856 feat: emit metadata events for schema changes with actor context for webhooks (#17622)
## Summary

This PR adds **metadata eventing**: when schema metadata
(objectMetadata, fieldMetadata, view, viewField, etc.) is created,
updated, or deleted, we now emit events that can trigger webhooks and
future audit logs. It also adds **actor context** (`userId`,
`workspaceMemberId`) to those events so subscribers can attribute
changes to a user or API key.

## What changed

### 1. Metadata eventing (first commit)

- **MetadataEventEmitter**  
New service that emits batch events after successful workspace
migrations. Event names follow `metadata.{entity}.{action}` (e.g.
`metadata.objectMetadata.created`, `metadata.fieldMetadata.updated`).
- **MetadataEventsToDbListener**  
Listens for metadata events and enqueues webhook delivery via
`CallWebhookJobsForMetadataJob`.
- **Event types** (twenty-shared)  
`MetadataEventAction`, `MetadataEventBatch`, and record event types for
create/update/delete.
- **WorkspaceMigrationValidateBuildAndRunService**  
Calls the metadata event emitter after running migrations so all
metadata changes (from any module) emit events from a single place.
- **Create events**  
Sourced from the create action payload (`flatEntity` /
`flatFieldMetadatas`) because `fromToAllFlatEntityMaps` does not provide
a before/after diff for creates. Update/delete events still use the
fromToAllFlatEntityMaps comparison.

### 2. Actor context (second commit)

- **MetadataEventEmitter**  
Accepts optional `actorContext` (`userId`, `workspaceMemberId`) and
includes it on emitted batch events.
- **WorkspaceMigrationValidateBuildAndRunService**  
Passes `actorContext` from the request into the metadata event emitter.
- **Metadata resolvers & services**  
All metadata modules resolve `@AuthUser({ allowUndefined: true })` and
`@AuthUserWorkspaceId()` and pass `userId` and `workspaceMemberId`
through to the migration/event pipeline. Both are optional so
API-key–authenticated requests (no user) still emit events without a
user identity.
  
Shared some questions on Discord about the PR.

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: prastoin <paul@twenty.com>
2026-02-12 17:14:25 +00:00
Paul RastoinandGitHub f6b7ab2251 Scalar and universal flat entity transpilers (#17891)
# Introduction

## Use `flatEntityTranspilers.toScalarFlatEntity` in create action
handler

**Changes:**
- Modified
`BaseWorkspaceMigrationRunnerActionHandlerService.insertFlatEntitiesInRepository()`
to transform flat entities using `toScalarFlatEntity()` before database
insertion

**What it does:**
Strips out TypeORM relation objects and metadata-only properties,
ensuring only scalar values (primitives, IDs, dates) are inserted into
the database.

**Benefits:**
- **Type Safety:** Prevents accidental insertion of nested objects that
TypeORM can't persist
- **Consistency:** All 17+ create action handlers automatically benefit
from proper data transformation
- **Single Source of Truth:** Centralized logic for what constitutes a
database-insertable entity
- **Prevents Errors:** Uses entity configuration schema to ensure only
valid properties are included

## Usage
```ts
  protected async insertFlatEntitiesInRepository({
    flatEntities,
    queryRunner,
  }: {
    queryRunner: QueryRunner;
    flatEntities: MetadataFlatEntity<TMetadataName>[];
  }) {
    const metadataEntity =
      ALL_METADATA_ENTITY_BY_METADATA_NAME[this.metadataName];
    const repository = queryRunner.manager.getRepository(metadataEntity);
    const scalarFlatEntities = flatEntities.map((flatEntity) =>
      flatEntityTranspilers.toScalarFlatEntity({
        flatEntity,
        metadataName: this.metadataName,
      }),
    );

    await repository.insert(scalarFlatEntities);
  }
```

## Upcoming refactor
About to completely split the
`packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/interfaces/workspace-migration-runner-action-handler-service.interface.ts`
into three dedicated boilerplate one for each action type `create`
`delete` `update` will provide a better interfacing and typing + will
allow not requiring the user to provide the metadata execute handler as
required
2026-02-12 17:06:55 +00:00
martmullandGitHub 8ffc554c9a Fix twenty sdk build (#17902)
as title
2026-02-12 17:04:07 +00:00
Charles BochetandGitHub d5a8cc2085 Migrate more to Jotai (#17903)
Here we go again
2026-02-12 18:13:31 +01:00
WeikoandGitHub 3075707bf8 Prefil fields widgets to standard app (#17897)
## Context
Prefill the FIELDS widget configuration in standard page layouts during
workspace creation, linking each widget to a dedicated view with
positioned fields organized into sections (via view field groups)

We wanted something very declarative (by manually setting position and
visibility of each field per standard object).
In this PR I've generated all the compute- utils via AI (😨) for
position/visibility, we'll probably want to confirm with the product
which ordering/visibility we want for each standard object but I feel
like this can be merged as it is since it's behind a feature flag and
this will unblock the work on the frontend
2026-02-12 16:54:30 +00:00
e6d3dc07e2 Fix EMFILE: too many open files, watch on macOS (#17901)
## Summary

Fixes `EMFILE: too many open files, watch` crash that most of the team
is hitting on macOS when running `yarn start` or `npx nx start
twenty-server`.

Adds `rimraf dist` before `nest start --watch` in the `start` and
`start:debug` targets, so the watcher starts with a clean output
directory.

## Root cause

The NestJS SWC compiler (`@nestjs/cli@11`) creates **three overlapping
chokidar watchers** when `nest start --watch` runs:

| Watcher | Watches | Purpose | Handles |
|---|---|---|---|
| SWC CLI (`@swc/cli`) | `src/` | Detects file changes → recompiles |
~1,730 |
| NestJS `watchFilesInSrcDir` | `src/` | Workaround: SWC misses new
files | shared with above |
| NestJS `watchFilesInOutDir` | **`dist/`** | Detects compiled `.js` →
restarts server | **~3,548** |

`@nestjs/cli@11` ships with **chokidar v4**, which dropped macOS
`fsevents` support and uses `fs.watch()` instead — creating **one file
descriptor per directory**. Chokidar v3 used a single `fsevents` kernel
subscription per directory tree.

Total: **~5,000+ `fs.watch()` handles**, far exceeding the default macOS
`ulimit -n` of ~2,560.

### Why it broke now

PR #17851 (`15fc850212`) changed the `start` target from `dependsOn:
["build"]` to `dependsOn: ["^build"]`, removing the `rimraf dist && nest
build` pre-step. Without that cleanup, `dist/` accumulated stale
directories from code reorganizations (e.g. `application-layer/` →
`application/` rename), growing to ~3,548 directories vs ~1,730 in a
clean build.

## What this PR does

Adds `rimraf dist &&` before `nest start --watch` in the `start` and
`start:debug` commands. This ensures `dist/` starts empty and only
contains directories matching the current `src/` structure (~1,730),
keeping watcher count in the ~3,400 range.

We still get the startup speed improvement from #17851 (no redundant
full SWC build), since `rimraf dist` is ~instant while the removed `nest
build` step took 30-60s.

## Future considerations

As the codebase grows, even a clean `dist/` will eventually approach the
macOS default `ulimit -n` (~2,560). Options to consider if that happens:

1. **Yarn resolution to force chokidar 3.6.0** — restores `fsevents`,
reducing watcher count from ~5,000 to ~3-5. This is what Vite 7 does
internally. Simple and effective, but pins to an older major version.

2. **Patch `@nestjs/cli`** to skip the `dist/` watcher — the
`watchFilesInOutDir` watcher accounts for ~65% of all handles and only
exists because NestJS doesn't have a direct hook into SWC's
compilation-complete event. Could be removed via `yarn patch`.

3. **Replace `nest start --watch` entirely** — use `node
--watch-path=src` (Node 22+) with `@swc-node/register` for on-the-fly
compilation. Uses a single native watcher regardless of directory count.
Requires rethinking asset copying (`watchAssets` in `nest-cli.json`).

4. **Wait for upstream fix** — NestJS CLI should either re-add
`fsevents` support or use Node's recursive `fs.watch()` option
(available since Node 20) instead of per-directory watchers.

## Test plan

- [ ] Run `npx nx start twenty-server` on macOS — server starts without
EMFILE error
- [ ] Run `npx nx start:debug twenty-server` — debug mode starts without
EMFILE error
- [ ] Edit a `.ts` file while server is running — hot reload still works
- [ ] Run `yarn start` (frontend + backend + worker) — no crashes

Made with [Cursor](https://cursor.com)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 16:08:35 +00:00
Charles BochetandGitHub 310d13fd17 Migrate twenty ui to jotai (#17900)
## Remove Recoil from twenty-ui

Completely removes the `recoil` dependency from `twenty-ui` by
converting all atoms, hooks, and providers to Jotai equivalents.

### twenty-ui
- `createState` now returns a Jotai `PrimitiveAtom` instead of a Recoil
atom
- `iconsState`, `IconsProvider`, `useIcons` converted to Jotai
(`useSetAtom`, `useAtomValue`)
- `RecoilRootDecorator` now uses Jotai `Provider` (name kept for compat)
- Deleted unused `invalidAvatarUrlsState` (Avatar already uses
`invalidAvatarUrlsAtomV2`)
- Removed `recoil` from `package.json`

### twenty-front
- Created local Recoil `createState` at
`@/ui/utilities/state/utils/createState` for ~112 state files still on
Recoil
- Updated all imports accordingly
- Removed `iconsState` from Recoil snapshot preservation in `useAuth`
(lives in Jotai store now)
2026-02-12 16:43:34 +01:00
Paul RastoinandGitHub 09e48addb2 Fix index field comparison (#17896)
# Introduction
Related https://github.com/twentyhq/core-team-issues/issues/2227

On a field name update side effect leading to an index field mutation it
wouldn't get caught by the builder leading to an index field desync

We should land on a standard pattern regarding the field index either
jsonb or syncableEntity so this would not occur anymore as it would have
been strictly typed
2026-02-12 14:59:33 +00:00
Charles BochetandGitHub d2f8352cb8 Start Jotai Migration (#17893)
## Recoil → Jotai progressive migration: infrastructure +
ChipFieldDisplay

### Benchmark

In the beginning, there was no hope:
<img width="1180" height="948" alt="image"
src="https://github.com/user-attachments/assets/f8635991-52e6-4958-8240-6ba7214132b2"
/>

Then the hope was reborn
<img width="2070" height="948" alt="image"
src="https://github.com/user-attachments/assets/be1182b9-1c8d-4fdc-ab4c-1484ad74449d"
/>



### Approach

We introduce a **V2 state management layer** backed by Jotai that
mirrors the existing Recoil API, enabling component-by-component
migration without a big-bang rewrite.

#### V2 API (Jotai-backed, Recoil-ergonomic)

- `createStateV2` / `createFamilyStateV2` — drop-in replacements for
`createState` / `createFamilyState`, returning wrapper types over Jotai
atoms
- `useRecoilValueV2`, `useRecoilStateV2`, `useFamilyRecoilValueV2`, etc.
— thin wrappers around Jotai's `useAtomValue` / `useAtom` / `useSetAtom`
- A shared `jotaiStore` (via `createStore()`) passed to a
`<JotaiProvider>` wrapping `<RecoilRoot>`, also accessible imperatively
for dual-writes

#### Dual-write bridge for progressive migration

For state shared between migrated and non-migrated components, we use
**dual-write**: writers update both the Recoil atom and the Jotai V2
atom (via `jotaiStore.set()`). This avoids sync components or extra
subscriptions.

Write sites updated: `useUpsertRecordsInStore`, `useSetRecordTableData`,
`ListenRecordUpdatesEffect`, `RecordShowEffect`,
`useLoadRecordIndexStates`, `useUpdateObjectViewOptions`.

#### First migration: ChipFieldDisplay render path

- `useChipFieldDisplay` → reads `recordStoreFamilyStateV2` via
`useFamilyRecoilValueV2` (was `useRecoilValue(recordStoreFamilyState)`)
- `RecordChip` → reads `recordIndexOpenRecordInStateV2` via
`useRecoilValueV2` (was `useRecoilValue(recordIndexOpenRecordInState)`)
- `Avatar` (twenty-ui) and event handlers (`useOpenRecordInCommandMenu`)
left on Recoil — not on the render path / in a different package

#### Pattern for migrating additional state

1. Create V2 atom: `createStateV2` or `createFamilyStateV2`
2. Add `jotaiStore.set(v2Atom, value)` at each write site
3. Switch readers to `useRecoilValueV2(v2Atom)`
4. Once all readers are migrated, remove the Recoil atom and dual-writes

#### Why not jotai-recoil-adapter?

Evaluated
[jotai-recoil-adapter](https://github.com/clockelliptic/jotai-recoil-adapter)
— not production-ready (21 open issues, no React 19, forces providerless
mode, missing types). We built a purpose-built thin layer instead.
2026-02-12 16:05:38 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Abdullah.
08b962b0d2 Bump @vitest/browser-playwright from 4.0.17 to 4.0.18 (#17884)
Bumps
[@vitest/browser-playwright](https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright)
from 4.0.17 to 4.0.18.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases"><code>@​vitest/browser-playwright</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.0.18</h2>
<h3>   🚀 Experimental Features</h3>
<ul>
<li><strong>experimental</strong>: Add <code>onModuleRunner</code> hook
to <code>worker.init</code>  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9286">vitest-dev/vitest#9286</a>
<a href="https://github.com/vitest-dev/vitest/commit/ea837de7d"><!-- raw
HTML omitted -->(ea837)<!-- raw HTML omitted --></a></li>
</ul>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Use <code>meta.url</code> in <code>createRequire</code>  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9441">vitest-dev/vitest#9441</a>
<a href="https://github.com/vitest-dev/vitest/commit/e057281ca"><!-- raw
HTML omitted -->(e0572)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>: Hide injected data-testid attributes  - 
by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9503">vitest-dev/vitest#9503</a>
<a href="https://github.com/vitest-dev/vitest/commit/f89899cd8"><!-- raw
HTML omitted -->(f8989)<!-- raw HTML omitted --></a></li>
<li><strong>ui</strong>: Process artifact attachments when generating
HTML reporter  -  by <a
href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9472">vitest-dev/vitest#9472</a>
<a href="https://github.com/vitest-dev/vitest/commit/225435647"><!-- raw
HTML omitted -->(22543)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.0.17...v4.0.18">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitest-dev/vitest/commit/4d3e3c61b9b237447699deab9aca0eb9d6039978"><code>4d3e3c6</code></a>
chore: release v4.0.18</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.0.18/packages/browser-playwright">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@vitest/browser-playwright&package-manager=npm_and_yarn&previous-version=4.0.17&new-version=4.0.18)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abdullah. <125115953+mabdullahabaid@users.noreply.github.com>
2026-02-12 13:35:22 +00:00
Thomas TrompetteandGitHub 748e614f6c Workflow bug fixes (#17886)
Fixes https://github.com/twentyhq/private-issues/issues/418 
Currency filtering was not properly managed. Since this is a select, we
were doing 'USD' == [USD]. Replacing by contains as for other select
<img width="952" height="552" alt="Capture d’écran 2026-02-12 à 11 08
42"
src="https://github.com/user-attachments/assets/6945f376-c62b-44a3-9d85-dfcb82f5c478"
/>

Fixes https://github.com/twentyhq/twenty/issues/17611
If-else branches not executed has to be marked as skipped. Otherwise,
the iterator will never start the next iteration. It will wait for some
not started nodes.
<img width="673" height="559" alt="Capture d’écran 2026-02-12 à 10 56
45"
src="https://github.com/user-attachments/assets/2b5396d7-a546-43df-a689-39f2686855ec"
/>
2026-02-12 13:27:36 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Abdullah.
2e80391e85 Bump react-loading-skeleton from 3.4.0 to 3.5.0 (#17883)
Bumps
[react-loading-skeleton](https://github.com/dvtng/react-loading-skeleton)
from 3.4.0 to 3.5.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dvtng/react-loading-skeleton/releases">react-loading-skeleton's
releases</a>.</em></p>
<blockquote>
<h2>v3.5.0</h2>
<h3>Features</h3>
<ul>
<li>Add optional <code>customHighlightBackground</code> prop. (<a
href="https://redirect.github.com/dvtng/react-loading-skeleton/issues/233">#233</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/dvtng/react-loading-skeleton/blob/master/CHANGELOG.md">react-loading-skeleton's
changelog</a>.</em></p>
<blockquote>
<h2>3.5.0</h2>
<h3>Features</h3>
<ul>
<li>Add optional <code>customHighlightBackground</code> prop. (<a
href="https://redirect.github.com/dvtng/react-loading-skeleton/issues/233">#233</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/dvtng/react-loading-skeleton/commit/f8b040dade9cfaad7e3e6fbc50243d79f508f1ca"><code>f8b040d</code></a>
Merge pull request <a
href="https://redirect.github.com/dvtng/react-loading-skeleton/issues/233">#233</a>
from dvtng/srmagura/highlight-width</li>
<li><a
href="https://github.com/dvtng/react-loading-skeleton/commit/c0973458b88b1f17cca93dcbf4b7c3ffa029d1c9"><code>c097345</code></a>
Update changelog</li>
<li><a
href="https://github.com/dvtng/react-loading-skeleton/commit/d9f88d9eec4142f5c655f793c6926562ae42f203"><code>d9f88d9</code></a>
update README</li>
<li><a
href="https://github.com/dvtng/react-loading-skeleton/commit/b1b27e8a2a053bd3f476e2814bd0949d00b682ea"><code>b1b27e8</code></a>
Custom highlight background</li>
<li><a
href="https://github.com/dvtng/react-loading-skeleton/commit/d8c1492840c273609b0dac8cbe9cc601ca8bad3c"><code>d8c1492</code></a>
fix: Improved the type of styleOptionsToCssProperties (<a
href="https://redirect.github.com/dvtng/react-loading-skeleton/issues/222">#222</a>)</li>
<li>See full diff in <a
href="https://github.com/dvtng/react-loading-skeleton/compare/v3.4.0...v3.5.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=react-loading-skeleton&package-manager=npm_and_yarn&previous-version=3.4.0&new-version=3.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abdullah. <125115953+mabdullahabaid@users.noreply.github.com>
2026-02-12 12:39:32 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Abdullah
bef70d2217 Bump @types/bytes from 3.1.4 to 3.1.5 (#17882)
Bumps
[@types/bytes](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/bytes)
from 3.1.4 to 3.1.5.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/bytes">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/bytes&package-manager=npm_and_yarn&previous-version=3.1.4&new-version=3.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abdullah <125115953+mabdullahabaid@users.noreply.github.com>
2026-02-12 12:01:18 +00:00
Raphaël BosiandGitHub cb7d0b83a8 [FRONT COMPONENTS] Twenty UI elements generation (#17866)
## PR description

This PR:
- Creates a TypeScript-based extractor that discovers all exported
twenty-ui components by scanning barrel files, extracting
props/slots/events via ts-morph type analysis, and generating the remote
DOM bindings automatically.

- Adds a new ESLint rule which enforces all *Props types in twenty-ui
components to be exported, which is required for the extractor to
discover component prop types. Existing twenty-ui components are updated
to comply with this rule.

- Extends the remote DOM generation to support slots, per-component
events, forwardRef wrappers, and richer property types (array, object,
function)

## Edge cases to fix in another PR

- Icons cannot be rendered inside buttons
- IconButtons throw an error when mounted
- MenuItems are not displayed correctly
- MenuItemNavigate throws on click

## Video Demo


https://github.com/user-attachments/assets/c2ed67cf-6a15-4896-9fec-e83fac0e862b
2026-02-12 12:48:16 +01:00
nitinandGitHub c48ccbca99 Fix widget and front component queries hitting wrong GraphQL endpoint (#17889) 2026-02-12 12:38:06 +01:00
EtienneandGitHub eb52976e91 File v2 - Backfill mimeType and size - command (#17875) 2026-02-12 10:49:10 +00:00
6d1c7c483f i18n - translations (#17887)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-12 11:48:55 +01:00
martmullandGitHub a4ed043d43 Logic function refactorization (#17861)
As title
2026-02-12 11:40:49 +01:00
Charles BochetandGitHub b456f79167 Reduce leak between gql schema (#17878)
## Reduce type leakage between GraphQL schemas

### Why

Twenty runs two separate GraphQL schemas: **core** and **metadata**.
NestJS's `@nestjs/graphql` uses a global `TypeMetadataStorage` that
accumulates all decorated types across all modules. When each schema is
built, every registered type leaks into both schemas regardless of which
module it belongs to.

This means the core schema's generated TypeScript
(`generated/graphql.ts`) contained ~2,700 lines of types that only
belong to the metadata schema (and vice versa). This creates confusion
about type ownership, inflates generated code, and makes it harder to
reason about which API surface each schema actually exposes.

### How

**1. Patch `@nestjs/graphql` to support schema-scoped type resolution**

- **(Already done)** Added a `resolverSchemaScope` option to
`GqlModuleOptions`, allowing each schema to declare a scope (e.g.
`'metadata'`)
- `ResolversExplorerService` now filters resolvers by a
`RESOLVER_SCHEMA_SCOPE` metadata key, so each schema only sees its own
resolvers
- `GraphQLSchemaFactory` now performs a **reachability walk**
(`computeReachableTypes`) starting from scoped resolver return types and
arguments, only including types that are transitively referenced —
handling unions, interfaces, and prototype chains
- Type definition storage and orphaned reference registry are cleared
between schema builds to prevent cross-contamination

**2. Register `ClientConfig` as orphaned type in metadata schema**

Since `ClientConfig` is needed in the metadata schema but not directly
returned by a resolver, it's explicitly declared via
`buildSchemaOptions.orphanedTypes`.

**3. Regenerate frontend types and fix imports**

- `generated/graphql.ts` shrank by ~2,700 lines (types moved to where
they belong)
- `generated-metadata/graphql.ts` gained types like `ClientConfig` that
were previously missing
- ~500 frontend files updated to import from the correct generated file
2026-02-12 10:58:52 +01:00
fe1ec6fd04 i18n - translations (#17881)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-12 04:37:39 +01:00
Abdul RahmanGitHubCopilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>Devessier
3fb2352c78 Navbar customization followup (#17848)
Addresses review comments from the [first navbar customization
PR](https://github.com/twentyhq/twenty/pull/17728)

---------

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Devessier <baptiste@devessier.fr>
2026-02-12 02:35:43 +00:00
91bfd45dc5 i18n - translations (#17877)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-11 22:08:58 +01:00
6aca1dd013 Introducing view field group syncable entity (#17867)
## Context
Introduces a new viewFieldGroup entity that allows grouping view fields
into sections (e.g. "General", "Additional", "Other") within a view.

The page layout fields widget needs a way to organize fields into
sections. Today, views have no concept of field grouping. This PR
introduces the viewFieldGroup entity which sits between a view and its
viewFields, enabling section-based organization.

<img width="401" height="724" alt="Layout - V2 (customize visibility)"
src="https://github.com/user-attachments/assets/6376e2ab-44db-42bf-9d2c-758f56f6b548"
/>

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-02-11 22:02:58 +01:00
Thomas TrompetteandGitHub ed66fbd71b Fix event stream does not exists error (#17873)
[Event stream does not
exists](https://twenty-v7.sentry.io/issues/7238297246/events/441b3c0465cf475a8349c7dec40cae2a/?environment=prod&environment=prod-eu&project=4507072499810304&query=is%3Aunresolved%20%21issue.type%3A%5Bperformance_consecutive_db_queries%2Cperformance_consecutive_http%2Cperformance_file_io_main_thread%2Cperformance_db_main_thread%2Cperformance_n_plus_one_db_queries%2Cperformance_n_plus_one_api_calls%2Cperformance_p95_endpoint_regression%2Cperformance_slow_db_query%2Cperformance_render_blocking_asset_span%2Cperformance_uncompressed_assets%2Cperformance_http_overhead%2Cperformance_large_http_payload%5D%20timesSeen%3A%3E10&referrer=previous-event&sort=date)

Error happens when we are trying to add a query to a non-existing event
stream. In some cases, this is legit. Stream has expired and needs to be
re-created. Then we try to add the query again.

But it should happen only once per tab, and not often. We have a lot of
errors in sentry for each users.

Potential root cause: a race condition between the event stream creation
and the addition of queries:
- event stream id is created in frontend state + creation query is sent
- event stream id is in state so query can be added
- addQuery happens before the stream is actually created in redis. So an
error is returned
- the error makes the event stream re-generated by frontend 
- => the flow starts again until the event stream is actually created
BEFORE the first query is added

Fix: a new state saying if event stream is ready
- event stream id is created in frontend state BUT ready state is falsy
so query is not added yet
- on stream creation on backend side, an initial event is sent, so the
frontend knows the stream is ready
- addQuery can be triggered safely
2026-02-11 20:24:03 +01:00
Charles BochetandGitHub 9bc63a01c9 Generate GQL schema based on applicationId (#17860)
## Add application-scoped GraphQL schema generation

When an application token is used to authenticate, the `/graphql` schema
is now dynamically filtered to only include entities belonging to that
application (plus the Twenty Standard Application). This enables
third-party applications and the SDK to introspect a schema that is
relevant to their scope, rather than seeing the full workspace schema
with all custom objects.

### Changes

- **New `generateApplicationToken` mutation** on the `/metadata`
endpoint, allowing callers to exchange an API key for an
application-scoped JWT token
- **Schema filtering by application** in `WorkspaceSchemaFactory` — when
`request.application` is present (from an application token), flat
entity maps are filtered by `[appId, standardAppId]` before schema
generation
- **Per-app caching** — both the Yoga in-memory cache and Redis cache
now include the `appId` in their keys to avoid serving wrong schemas
- **Consolidated `getSubFlatEntityMapsByApplicationIdsOrThrow`** —
unified the single-ID and multi-ID filtering utilities into one
- **Integration tests** covering token generation (admin + API key auth)
and schema introspection filtering (standard app token excludes custom
objects)

Schema generated on seeds with applicationToken (see that pets is
missing)
<img width="782" height="994" alt="image"
src="https://github.com/user-attachments/assets/82510031-0965-435d-bc26-77c9f5d74e1f"
/>
2026-02-11 20:21:58 +01:00
15fc850212 Remove redundant self-build from Nx targets that compile on the fly (#17851)
## Summary

- Changed 6 Nx targets (`start`, `start:debug`, `typeorm`, `ts-node`,
`database:migrate`, `database:migrate:revert`) from `dependsOn:
["build"]` to `dependsOn: ["^build"]` to eliminate a redundant full SWC
compilation step (~30-60s per invocation).
- These targets all use `nest start --watch`, `ts-node`, or TypeORM's
CLI (which runs under ts-node), so they already compile TypeScript
themselves. The `build` dependency was causing `rimraf dist && nest
build` to run first, only for the target's own command to recompile
everything again.
- Fixed `start:debug` to call `nest start --watch --debug` directly
instead of routing through `nx start --debug`, which would trigger yet
another build cycle.

Note: targets that run pre-compiled code from `dist/` (like
`database:reset`) intentionally keep `dependsOn: ["build"]`.

## Test plan

- [ ] Run `npx nx start twenty-server` and verify the server starts with
only one SWC compilation pass instead of two
- [ ] Run `npx nx start:debug twenty-server` and verify the debugger
attaches correctly
- [ ] Run `npx nx run twenty-server:database:migrate` and verify
migrations run correctly
- [ ] Run `npx nx run twenty-server:database:reset twenty-server` and
verify it still builds before running (unchanged)


Made with [Cursor](https://cursor.com)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-11 17:38:22 +00:00
e6d5df751b i18n - translations (#17874)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-11 18:25:44 +01:00
5b4fed1afe Fix redirect to deleted workspace subdomain after workspace deletion (#17865)
## Summary
- After deleting a workspace, the app was incorrectly redirecting to the
deleted workspace's subdomain (e.g. `myworkspace.ourapp.com/sign-in-up`)
because `signOut()` only performs a client-side React Router navigation
which stays on the current domain.
- Added an explicit `redirectToDefaultDomain()` call after sign out in
the workspace deletion flow, which does a hard browser redirect to the
base domain (e.g. `app.ourapp.com`).

## Test plan
- [ ] Delete a workspace in a multi-workspace environment
- [ ] Verify the browser redirects to the base domain (`app.ourapp.com`)
instead of staying on the deleted workspace's subdomain
- [ ] Verify normal sign-out (without workspace deletion) still works as
expected

Made with [Cursor](https://cursor.com)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-11 18:25:27 +01:00
e757a1418d Fix hardcoded colors in 2FA verification screen for dark mode (#17868)
## Summary
- The dash separator and blinking caret in the sign-in 2FA OTP input had
hardcoded `black` and `white` background colors, making them invisible
in dark mode (black on black / white on white).
- Replaced with theme-aware colors (`theme.font.color.light` for the
dash, `theme.font.color.primary` for the caret) to match the existing
settings 2FA component.

## Test plan
- [ ] Open the 2FA verification screen in dark mode and verify the dash
between digit groups is visible
- [ ] Verify the blinking caret is visible in dark mode
- [ ] Confirm both still look correct in light mode

Made with [Cursor](https://cursor.com)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-11 18:23:42 +01:00
EtienneandGitHub 2f298307f9 Handle 413 with user friendly message (#17870)
Add friendly message for 413 errors. Currently, 413 errors originate
from the nginx server.
2026-02-11 17:03:22 +00:00
WeikoandGitHub c15536f9f8 Fix page layout seeding for record page layouts (#17871)
## Context
Fix broken record page layout seeding. This was not detected by the CI
because it doesn't have the env variable yet.

Following the same mechanism as labelIdentifier in object for circular
dependency resolution
2026-02-11 16:56:21 +00:00
Paul RastoinandGitHub b2f7c745f8 Solo transaction application synchronization service refactor (#17864)
# Introduction
Refactoring the application sync service to be making a single validate
build and run transaction instead of calling all the services n times
thanks to the universal workspace migration refactor that allow doing so

## What's next
Migrating all below entities to by syncableEntities so they can be
universalised too ( right now they're still calling the services n times
and won't be returned in the workspace migration )
-
[objectPermission](https://github.com/twentyhq/core-team-issues/issues/2223)
-
[fieldPermission](https://github.com/twentyhq/core-team-issues/issues/2224)
-
[permissionFlag](https://github.com/twentyhq/core-team-issues/issues/2225)
2026-02-11 16:30:01 +00:00
0ee63a0525 i18n - translations (#17872)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-11 17:35:20 +01:00
18880f0385 i18n - translations (#17869)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-02-11 17:05:37 +01:00
Abdul RahmanGitHubCopilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>Devessier
0902579fbe Feat: Navbar customization (#17728)
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Devessier <baptiste@devessier.fr>
2026-02-11 15:33:51 +00:00