Commit Graph
3528 Commits
Author SHA1 Message Date
Paul RastoinandGitHub 46cf551281 Invalidate legacy cache after flats (#17126)
# Introduction

Some legacy caches are based on the flat ones
So we need to seq invalidate before invalidating others as it could
result in inter dep cache invalidation race condition
2026-01-13 16:07:27 +00:00
4a3cc0aeb8 i18n - translations (#17125)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-13 16:38:18 +01:00
martmullandGitHub d55b83375d Allow app to extend object (#17116)
- exports `extendObject` utils from `twenty-sdk`
- define `*.object-extension.ts` filename pattern to extend and object
- handle object-extension configs in manifest
2026-01-13 15:07:14 +00:00
Paul RastoinandGitHub f1be7129cb Allow isUnique mutation on standard field (#17120)
# Introduction
As we've just
[identified](https://github.com/twentyhq/twenty/pull/16981) the standard
field metadata in production we can not enable the is unique comparison
even for standard entities
2026-01-13 13:28:50 +00:00
db87da162c i18n - translations (#17119)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-13 11:21:29 +01:00
b0d6571469 Improve Japanese translations (#16979)
The current Japanese translations are severely lacking. My company
(based in Tokyo) uses Japanese as its main language. I've gone through
and corrected/standardized everything. This is good enough to merge as a
starting point.

Includes `lingui compile` for the changes.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Major localization refresh focused on Japanese.
> 
> - Rewrites and standardizes `ja-JP` message strings (clearer phrasing,
consistent terminology, corrected placeholders/punctuation)
> - Regenerates compiled Lingui locale bundles; updates `ja-JP.ts` and
`ko-KR.ts` outputs
> - No runtime logic changes; scope limited to generated i18n resources
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3365dcdac6. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2026-01-13 10:28:45 +01:00
Abdullah.andGitHub 2c8d3f02e1 feat: upgrade to Storybook version 10 (#17110)
Upgraded to Storybook 10. We still use `@storybook/test-runner` for
testing since it appears it'd require more work to move from Jest to
Vitest than I initially anticipated, but I completed this PR to fix
`storybook:serve:dev` - it takes time to load, but it works the way it
used to with Storybook 8.


https://github.com/user-attachments/assets/7afc32c6-4bcf-4b37-b83b-8d00d28dda15
2026-01-13 08:18:07 +00:00
Paul RastoinandGitHub df108ea040 Identify standard objects (#17091)
# Introduction
Followup https://github.com/twentyhq/twenty/pull/16981

1/ Migration, applicationId and universalIdentifier are required on
entity ( save point migration + upgrade command fallback pattern )
2/ Backfill using previous standard ids
2026-01-12 18:06:13 +00:00
Lucas BordeauandGitHub 04a370e043 Implemented SSE subscription mechanism on the frontend (#17017)
This PR is a follow-up of https://github.com/twentyhq/twenty/pull/16966
and implements a new mechanism to handle SSE events.

It creates only one event stream per browser tab, then use mutations to
tell the backend which query to listen to, without re-mounting the event
stream connexion.

Then each event that comes from this unique subscription is then
dispatched in a new JavaScript CustomEvent, per queryId, on which
specific hooks add an event listener.

This PR introduces the generic tooling as well as the handling of update
events on table.
2026-01-12 18:58:46 +01:00
1c2fda30bd i18n - translations (#17106)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-12 18:58:01 +01:00
c795b8c52a RLS FE implementation (#17062)
## Summary
This PR introduces row-level security (RLS) permissions for roles in the
frontend, allowing fine-grained access control at the record level.
Users can now define permission rules that determine which specific
records a role can access based on dynamic conditions and filters.
## What's Changed
Implemented UI for configuring record-level permissions on object
permissions screens
Added support for defining permission predicates using filter conditions
(similar to advanced filters)
Introduced variable picker for dynamic permission rules (e.g., "me"
context for user-specific access)
Built predicate conversion layer to sync UI state with backend
permission structure
Extended GraphQL schema with mutations for upserting row-level
permission predicates
Fixed handling of orphaned RLS groups to prevent data inconsistencies
Added enterprise key validation for RLS features
The implementation enables scenarios like "users can only see their own
records" or "users can access records associated with their team."

<img width="687" height="702" alt="Screenshot 2026-01-09 at 23 07 02"
src="https://github.com/user-attachments/assets/33fe736e-6cbf-40bd-b2eb-c8a90c8d21bc"
/>

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-12 17:39:17 +00:00
493f0575ea i18n - translations (#17097)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-12 14:29:26 +01:00
Raphaël BosiandGitHub 655f1eef5f [DASHBOARDS] Allow dashboards to be restored (#17042)
This PR introduces a few changes:
- Add three actions: see deleted dashboards, destroy dashboard and
restore dashboard
- Remove the soft delete and restore on all the page layout entities
- Cascade the destruction of a dashboard to a page layout

Video QA:


https://github.com/user-attachments/assets/ab993b11-dd9c-4e88-880c-92691a521cc2
2026-01-12 12:59:17 +00:00
MarieandGitHub 3ada8e5168 [Extensibility] Support relation fields (#17056)
Closes https://github.com/twentyhq/core-team-issues/issues/2043
2026-01-12 12:54:30 +00:00
Paul RastoinandGitHub 91b788ee09 [REQUIRES_FIELDS_CACHE_FLUSH]Fix field entity to flat field transpiler (#17096)
Following https://github.com/twentyhq/twenty/pull/16981

UniversalIdentifier is now required in the entity so no need to fallback
it
2026-01-12 12:49:07 +00:00
nitinandGitHub 342ae995d9 Add error boundary on widget renderer and minor widget seed fix (#17058)
closes https://github.com/twentyhq/twenty/issues/16896 and
https://github.com/twentyhq/core-team-issues/issues/2050

should error be Invalid Configuration or something else?
2026-01-12 12:02:58 +00:00
238e6d5cda Common api - chores (#17051)
Remove refacto-common TODO

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-12 11:37:29 +00:00
Paul RastoinandGitHub a6f371a42a Identify standard field do deploy until IS_WORKSPACE_CREATION_V2_ENABLED is enabled in prod (#16981)
# Introduction

fixes https://github.com/twentyhq/twenty/issues/16905

Do not merge until `IS_WORKSPACE_CREATION_V2_ENABLED` has been activated
by default, and so sync metadata has been deprecated by doing so. As the
sync metadata will attempt to insert `null` `applicationId` and
`universalIdentifier` values while creating a workspace

In this PR we're introducing a new `SyncableEntityRequired` which
enforces the non nullable `applicationId` and `universalIdentifier` on
extending entity

In this PR we also migrate the field metadata entity to extend the
required

## Identification upgrade command
This command will search for workspace field metadata entities that
aren't associated to an applicationId, dispatch them to either the
workspace-custom `applicationId` or the twenty-standard `applicationId`.
For the standard entities it will also set their universal identifier
based on the `STANDARD_OBJECTS` const hashmap

## Typeorm migration
As the non nullable `applicationId` and `universalIdentifier`migration
won't pass in the first we've been using the save point and upgrade
command migration fallback pattern

## Tests
Tested the command on a prod extract locally

Both `twenty-eng` and `twenty-for-twenty` have unexpected standard
objects
Please note that we will deprecate the `isCustom` and `standardId` col
later in the future

### Twenty-eng
```ts
[Nest] 98971  - 01/01/2026, 3:18:00 PM     LOG [IdentifyStandardEntitiesCommand] Successfully validated 600/600 field metadata update(s) for workspace 9870323e-22c3-4d14-9b7f-5bdc84f7d6ee (309 custom, 291 standard)
[Nest] 98971  - 01/01/2026, 3:18:00 PM    WARN [IdentifyStandardEntitiesCommand] Found 35 warning(s) while processing field metadata for workspace 9870323e-22c3-4d14-9b7f-5bdc84f7d6ee. These fields will become custom.
```

### Twenty for twenty

### Just created workspace
2026-01-12 09:59:01 +00:00
46e5420d20 dashboard workspace standard seeds (#16962)
# Introduction

In this pull request we're introducing new standard page layout, tabs
and widget ( 1 page layout, 1 tab and 8 widgets ) and also a new
opportunity field

Also now prefilling new records, 6 opportunities and a dashboard.

## Standard declaration
### New workspace creation
Relies on existing standard declaration builder

### Backfill command
We've been hacking through the standard builder in order to extract only
the standard page layout entities, updated their entity dependencies to
match the workspace ids so the validation passes


## Remark
- Refactored the `PageLayoutWidget` configuration type to be dynamically
typed through a generic discriminated union

---------

Co-authored-by: prastoin <paul@twenty.com>
2026-01-12 09:34:15 +00:00
Félix MalfaitandGitHub 57363c2127 Fix orderBy columns missing from SELECT in DISTINCT subquery (#17079)
## Description

Fixes a bug where queries with relation field + scalar field ordering
would fail with:
```
column distinctAlias.person_position does not exist
```

## Root Cause

When a GraphQL query orders by columns that are **not in the selected
fields**, TypeORM's DISTINCT subquery fails because it expects those
columns in the inner SELECT with alias format (e.g., `person_position`).

The issue only manifests when:
1. A filter is applied (triggers DISTINCT path in TypeORM)
2. OrderBy includes columns NOT in the GraphQL selection
3. Example: query selects only `id`, but orders by `position`

## The Fix

`addRelationOrderColumnsToBuilder` now accepts `columnsToSelect` and
adds orderBy columns via `addSelect()` only if they're **NOT** already
in the selected columns:

- **Relation orderBy columns**: Always added (never in columnsToSelect)
- **Main entity orderBy columns**: Added only when not already selected

This ensures all orderBy columns are present in TypeORM's inner SELECT
for the DISTINCT subquery.

## Test Plan

Added integration test for the exact failing scenario:
- Filter with `neq` (triggers DISTINCT path)
- Multiple orderBy: relation field + scalar field  
- Minimal field selection (only `id`, not `position`)

## Related

Regression introduced in #17021 which added nested sort support.
2026-01-11 14:19:05 +01:00
20f62e05f5 fix(search): add support for searching by additional emails, phones, and secondary links (#17034)
## Summary
- Add `additionalEmails` (EMAILS type) to tsvector search expression
- Add `additionalPhones` (PHONES type) to tsvector search expression  
- Add `secondaryLinks` (LINKS type) to tsvector search expression

This enables searching for people/companies by their secondary contact
information, not just primary values.

## Test plan
- [x] Unit tests for all three composite field types (16 tests passing)
- [x] Integration tests for searching by secondary email, work email,
partial domain
- [x] Integration tests for searching by additional phone numbers
- [x] Integration test for searching by secondary link URL
- [x] Lint passes

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-10 15:24:46 +00:00
Thomas TrompetteandGitHub 3acc87a620 [SSE] Add backend for SSE subscriptions (#17022)
- moved a few gql types to twenty shared to re-use in server
- added a new endpoint, onEventSubscription that expect a streamId to
create a connection
- two new endpoints to store queries in Redis
- updated the existing batch channel to directly use object record type
2026-01-10 14:44:02 +00:00
neo773andGitHub 87fb25c703 IMAP edge cases (#17065)
Fixes IMAP edge case. We had a maximum call stack reached crash if the
array was very large for some folders. Plus some minor perf improvement.


https://twenty-v7.sentry.io/issues/6997180505/events/652c69da1be944aab1c87ac2e6a06c30/
2026-01-10 14:26:07 +00:00
Félix MalfaitandGitHub a8331dc43e feat: add case-insensitive sorting for text fields (#17023)
## Context

Text fields were being sorted case-sensitively on the backend (e.g.,
'Apple', 'apple', 'Banana' would sort as 'Apple', 'Banana', 'apple').
This resulted in unexpected sorting behavior that differed between the
frontend Apollo cache sorting and backend database sorting.

## Changes

### Backend (packages/twenty-server)

- **`graphql-query-order.parser.ts`**:
- Added `shouldUseCaseInsensitiveOrder()` helper that returns `true` for
TEXT, SELECT, and MULTI_SELECT fields
- Added `buildOrderByColumnExpression()` method that wraps column
expressions with `LOWER()` for case-insensitive sorting
- Updated `parse()` and `parseObjectRecordOrderByForScalarField()` to
use the new helpers
- Updated `parseObjectRecordOrderByForRelationField()` to apply LOWER()
to nested text fields

- **`parse-composite-field-for-order.util.ts`**:
- Added `shouldUseCaseInsensitiveOrder()` helper for composite subfields
- Updated composite field parsing to apply `LOWER()` to subfields of
type TEXT (e.g., `name.firstName`, `name.lastName`)

### Frontend (packages/twenty-front)

- **`sort.ts`**:
- Updated `sortAsc()` to use case-insensitive comparison
(`toLowerCase()`) for string values
- `sortDesc()` automatically benefits from this since it delegates to
`sortAsc()`
  - Ensures Apollo cache sorting matches backend behavior

## Example

Before:
```sql
ORDER BY "person"."name" ASC
```
Result: ['Apple', 'Banana', 'apple', 'cherry']

After:
```sql
ORDER BY LOWER("person"."name") ASC
```
Result: ['apple', 'Apple', 'Banana', 'cherry']

## Testing

- Manual testing of sorting on People and Companies views
- Verified frontend cache sorting matches backend results
2026-01-10 14:05:56 +01:00
Félix MalfaitandGitHub 1a5675d63e feat: add sorting on relation fields (Many-to-One) (#17021)
## Summary

This PR enables sorting records by fields of related objects. For
example, sorting **People by their Company's name**.

### Before
Only scalar and composite fields could be sorted. Relation fields showed
in the sort dropdown but produced errors.

### After
Many-to-One relation fields can now be sorted using the related object's
**label identifier field** (e.g., Company's `name`).

---

## Changes

### Frontend
- Added `RELATION` to sortable field types (restricted to `MANY_TO_ONE`
relations)
- New `getOrderByForRelationField()` generates nested orderBy structures
using the related object's label identifier
- Updated `turnSortsIntoOrderBy()` to handle relation fields by looking
up related object metadata

### Backend
- Extended `GraphqlQueryOrderFieldParser.parse()` to detect nested
relation ordering like `{ company: { name: 'AscNullsLast' } }`
- Returns `ParseOrderByResult` containing both `orderBy` conditions and
`relationJoins` info
- Added LEFT JOINs for relation ordering in `applyOrderToBuilder()`
- Added `addRelationOrderColumnsToBuilder()` for TypeORM DISTINCT
compatibility

### Tests
- Added unit tests for `filterSortableFieldMetadataItems`,
`getOrderByForRelationField`, and `turnSortsIntoOrderBy`
- Added integration tests covering ascending/descending order and
composite label identifiers

---

## TypeORM Bug Workaround

We encountered a significant TypeORM limitation when implementing this
feature. When using `getMany()` with `ORDER BY` on joined relation
columns, TypeORM generates a DISTINCT subquery that has specific
requirements:

### Issue 1: Alias Parsing
TypeORM's `orderBy()` method fails with **"alias not found"** when using
quoted SQL identifiers like `"company"."name"`. TypeORM internally
expects unquoted property paths (e.g., `company.name`) for its alias
resolution mechanism.

### Issue 2: setFindOptions Clears addSelect
`setFindOptions({ select })` **clears any previously added `addSelect()`
columns**. This caused `"column distinctAlias.company_name does not
exist"` errors because the relation columns needed for ORDER BY were
being removed.

### Solution
We split the logic into two methods:
1. `applyOrderToBuilder()` - adds JOINs and ORDER BY (before
`setFindOptions`)
2. `addRelationOrderColumnsToBuilder()` - adds relation columns for
SELECT (AFTER `setFindOptions`)

This ensures the relation columns are present in the final SQL query's
SELECT clause with the proper underscore aliases (`company_name`) that
TypeORM's DISTINCT subquery expects.

**Related TypeORM issue**:
https://github.com/typeorm/typeorm/issues/9921

---

## Screenshots/Demo

_Add screenshots if applicable_
2026-01-10 11:02:16 +01:00
9b6eb8b80a fix onboarding for messaging (#16729)
Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-09 20:17:04 +00:00
EtienneandGitHub f3d89ca9b9 Fix cleaning command (#17040)
Previous behavior:

Used billingSubscription.updatedAt (when the subscription record was
last modified)
Problem: updatedAt changes for ANY update, not just status changes,
making it unreliable for tracking when payment problems started

Current behavior:

Uses currentPeriodStart when subscription status is Unpaid or Canceled
Why it works: WORKSPACE_INACTIVE_DAYS_BEFORE_SOFT_DELETION is shorter
than the minimum billing interval (1 month). Then if a workspace is
unpaid for the entire current billing period, it will always exceed the
deletion threshold before the next period starts

Ideal fix:
Track workspace.suspendedAt explicitly, giving you the exact timestamp
of when payment problems began, regardless of billing periods.
2026-01-09 18:11:41 +00:00
Abdul RahmanGitHubcubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
151731c05d If else node followup changes (#16974)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-09 17:20:58 +00:00
neo773andGitHub a0b2aa207f Fix messaging 404 handling (#17041)
`MessageImportExceptionHandlerService.handleSyncCursorErrorException()`
was calling `messageChannelSyncStatusService.markAsFailed()`
instead of

`messageChannelSyncStatusService.resetAndMarkAsMessagesListFetchPending()`

Also adds a new command `MessagingTriggerMessageListFetchCommand` for
faster local development speed
2026-01-09 16:35:12 +00:00
52e859e5a7 i18n - translations (#17048)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-09 15:38:08 +01:00
d7b7e9def1 Cascade delete Task targets when tasks deleted - logic + migration command (#17019)
Co-authored-by: prastoin <paul@twenty.com>
2026-01-09 14:10:40 +00:00
neo773andGitHub a5eae50c66 Migrate MicrosoftAPIRefreshAccessTokenService to @azure/msal-node (#16954) 2026-01-08 17:18:35 +00:00
85a7f6548e i18n - translations (#17025)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-08 17:27:35 +01:00
Paul RastoinandGitHub 942d2fef83 Remove sync-metadata and IS_WORKSPACE_CREATION_V2_ENABLED feature flag (#16997)
# Introduction
Followup of
https://github.com/twentyhq/twenty/pull/17001#pullrequestreview-3638508738
close https://github.com/twentyhq/core-team-issues/issues/1910

We've completely decom the `sync-metadata` in production. We're now then
removing its implementation in favor of the v2.

## TODO:
- [x] Remove sync-metadata implem and commands
- [x] Remove workspace decorators 
- [x] Type each deprecated field to deprecated on their workspaceEntity
- [x] Remove the `workspace-sync-metadata` folder entirely
- [x] remove workspace migration
- [x] workspace migration removal migration
- [x] remove the `v2` references from workspace manager file names
- [x] remove the `v2` references from workspace manager modules
- [ ] Double check impact on translation file path updates


## Note
- Removed the gate logic
- Remains some service v2 naming, serverless needs to be migrated on v2
fully
- Removed workspaceMigration service app health consumption, making it
always returning up ( no more down ) cc @FelixMalfait ( quite obsolete
health check now, will require complete refactor once we introduce inter
app dependency etc )
2026-01-08 15:45:12 +00:00
Paul RastoinandGitHub 28e79de7b0 Fix workspace application fk command re-run (#17018)
# Introduction
The command is not idempotent, try to create an already existing FK
fails
- Always dropping the FK before recreating it in order to prevent this
- Removed the `remoteTable` and `remoteServer` from the command

We still have the `hasRunOnce` static var that will avoid re running it
if a workspace successfully passed the migration

Note: This is shared between both the upgrade command and the typeorm
migration

## Test
locally
```ts
atedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object person (20202020-e674-48e5-a542-72570eee7213) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object pet (custom) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object surveyResult (custom) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object rocket (custom) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] All objects already have updatedBy field for workspace 20202020-1c25-4d02-bf25-6aeccf7ea419
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [AddWorkspaceForeignKeysMigrationCommand] Successfully run AddWorkspaceForeignKeysMigrationCommand
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [UpgradeCommand] Upgrade for workspace 20202020-1c25-4d02-bf25-6aeccf7ea419 completed.
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [UpgradeCommand] Running command on workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db 2/2
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [UpgradeCommand] Upgrading workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db from=1.14.0 to=1.15.0 2/2
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [MigratePageLayoutWidgetConfigurationCommand] Starting migration of page layout widget configurations for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [MigratePageLayoutWidgetConfigurationCommand] Found 0 widget(s) needing migration out of 16 total
query: SELECT COUNT(1) AS "cnt" FROM "workspace_3ixj3i1a5avy16ptijtb3lae3"."note" "note" WHERE ( (("note"."position" = $1)) ) AND ( "note"."deletedAt" IS NULL ) -- PARAMETERS: ["NaN"]
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [FixNanPositionValuesInNotesCommand] Found 0 note(s) with NaN position values in workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [FixNanPositionValuesInNotesCommand] No NaN position values to fix
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Starting backfill of updatedBy field for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object note (20202020-0b00-45cd-b6f6-6cd806fc6804) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object task (20202020-1ba1-48ba-bc83-ef7e5990ed10) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object dashboard (20202020-3840-4b6d-9425-0c5188b05ca8) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object workflowRun (20202020-4e28-4e95-a9d7-6c00874f843c) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object workflow (20202020-62be-406c-b9ca-8caa50d51392) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object opportunity (20202020-9549-49dd-b2b2-883999db8938) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object company (20202020-b374-4779-a561-80086cb2e17f) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object attachment (20202020-bd3d-4c60-8dca-571c71d4447a) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object person (20202020-e674-48e5-a542-72570eee7213) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] Object surveyResult (custom) already has updatedBy field, skipping
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [BackfillUpdatedByFieldCommand] All objects already have updatedBy field for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [AddWorkspaceForeignKeysMigrationCommand] Skipping has already been run once AddWorkspaceForeignKeysMigrationCommand
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [UpgradeCommand] Upgrade for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db completed.
[Nest] 17395  - 01/08/2026, 3:04:18 PM     LOG [UpgradeCommand] Command completed!
```
2026-01-08 14:12:57 +00:00
3e08f295d5 i18n - translations (#17007)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-08 10:50:39 +01:00
WeikoandGitHub 66b2882ac4 BREAKING CHANGE: Removing remote integration feature (#17001)
## Context
The feature has not been maintained for more than a year and was never
officially launched.
This PR removes its code due to the upcoming refactoring of the
sync-metadata that will break its logic if not handled properly and it
would be too costly for the time being.

TODO:
- remove isRemote from object/field metadata
2026-01-08 09:14:51 +00:00
Raphaël BosiandGitHub 2e0eeda52e [DASHBOARDS] Fix dashboard duplication createdBy (#16999)
Fixes https://github.com/twentyhq/core-team-issues/issues/2032

## Before


https://github.com/user-attachments/assets/5804d3e7-1c03-4eb9-9203-64656438f5d1


## After


https://github.com/user-attachments/assets/9f96458c-d2a5-481a-b6b2-4d88f0daa98a
2026-01-08 09:13:43 +00:00
Raphaël BosiandGitHub 7af98a9c15 Update updatedat field on dashboards after edition (#16964)
Closes https://github.com/twentyhq/core-team-issues/issues/1896
2026-01-07 17:14:24 +00:00
nitinandGitHub a19ed92429 fix: composite field matching in relation field orderBy with groupBy (#16992)
- Fix groupBy field matching for composite fields nested within relation
fields
- Add `nestedSubFieldName` comparison when the nested field is a
composite type (CURRENCY, FULL_NAME, ADDRESS, etc.)
2026-01-07 16:13:08 +00:00
e83e616fde fix: qs's arrayLimit bypass in its bracket notation allows DoS via memory exhaustion (#16886)
Resolves [Dependabot Alert
354](https://github.com/twentyhq/twenty/security/dependabot/354) and
[Dependabot Alert
355](https://github.com/twentyhq/twenty/security/dependabot/355).

Upgraded express by one minor version. Removed redundant type definition
in root `package.json` since we already have it in twenty-server's
`package.json`.

Upgraded body-parser patch version in serverless package.json.

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-01-07 15:58:12 +00:00
Thomas TrompetteandGitHub 6410157c5c Provide executed step output instead of result (#16991)
For huge workflows, after 20 steps, we stop the job and re-trigger a new
one.
But some of those workflows actually never stop.
See https://github.com/twentyhq/private-issues/issues/401 

Here is a first issue. We resuming the workflow, we were providing the
result instead of the output
2026-01-07 15:50:14 +00:00
Charles BochetandGitHub 9acf6ce1ad Add otel collector to reserved subdomains (#16988)
Ordered the RESERVED_SUBDOMAINS list by alphabetical order and added
'otel-collector'
2026-01-07 15:11:34 +00:00
370609a2e2 i18n - translations (#16989)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-01-07 16:21:49 +01:00
Raphaël BosiandGitHub 4faed25624 [PAGE LAYOUTS] Add widgets validation (#16635)
- Add widget validation
- Remove 'None' option for primary axis group by
- Fix error message parsing by passing the operation type in
`useMetadataErrorHandler`
2026-01-07 15:00:13 +00:00
Paul RastoinandGitHub 4ea4572924 Workspace creation prefill fix (#16983)
# Introduction
Fixing prefill in v2 workspace creation code flow
2026-01-07 13:51:21 +00:00
Abdul RahmanandGitHub 10de7acef3 If else node tests (#16916) 2026-01-07 10:37:37 +00:00
e4f8d804d5 fix(16819): Add NoteDeleteOnePostQueryHook for soft removing note targets (#16826)
Fixes [#16819](https://github.com/twentyhq/twenty/issues/16819)

Added a post-query hook (NoteDeleteOnePostQueryHook) that automatically
soft-deletes all associated noteTarget records when a note is deleted.

## Key changes:

Created `note-delete-one.post-query.hook.ts`
Uses `GlobalWorkspaceOrmManager` to access workspace entities correctly
Executes in the proper workspace context to ensure data isolation
Soft-deletes noteTarget records to maintain referential consistency

## Testing
1. Company notes
Create a Company
Create and attach a Note to the Company
Navigate to Company → Notes page (should display the note)
Delete the Note
Navigate to Company → Notes page (should no longer crash)
Restore the Note (should appear again)
Delete and destroy the Note permanently
Navigate to Company → Notes page (should still work, just empty)

2. Opportunity notes
Create an Opportunity
Create and attach a Note to the Opportunity
Navigate to Opportunity → Notes page (should display the note)
Delete the Note
Navigate to Opportunity → Notes page (should no longer crash)
Restore the Note (should appear again)
Delete and destroy the Note permanently
Navigate to Opportunity → Notes page (should still work, just empty)

### Expected behavior:

Company Notes page remains functional at all stages
No console errors
Deleted notes properly excluded from the view
Other notes on the same Company remain accessible
Additional Notes
This fix ensures data consistency by maintaining the relationship
between notes and their targets throughout the deletion lifecycle.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2026-01-07 08:30:08 +00:00
Félix MalfaitandGitHub 5f4b6e7ea4 Set default SMTP value to true (#16967)
As per title. Will make it easier for self-hosters. @Weiko fyi
2026-01-06 18:25:33 +00:00
neo773andGitHub 971ddc0bb4 fix calendar save events transaction (#16763) 2026-01-06 17:56:03 +00:00