Regression introduced by
https://github.com/twentyhq/twenty/pull/16244/files
Why:
- `ChipFieldDisplay` component is using a `recoilComponentState` and
`ContextStoreComponentContext` is not provided on Settings page
This fix
- does not use the componentState in the `ChipFieldDisplay` but in the
RecordIndex area where the `ContextStoreComponentContext` is provided
- this also improve the performance as recoilState access is not free
This is a temporary fix that needs to be revisited.
It seems that with the new enqueue system we are enqueuing jobs multiple
times due to race condition. We likely want to only consider job that
have been created more than x secs ago
## Problem
buildEntityMetadatas in GlobalWorkspaceOrmManager is computationally
expensive and was running on every executeInWorkspaceContext call. This
method uses
TypeORM's EntitySchemaTransformer and EntityMetadataBuilder to build
metadata for all workspace entities (30-50+ objects with many fields
each).
The resulting EntityMetadata[] is not serialisable which means it cannot
be cached in Redis because they contain:
- Circular references
- Functions/methods
- References to the DataSource instance
## Solution
Extended the workspace cache system to support local-only caching, then
created a cache provider for entityMetadatas.
## Implementation details
Updated @WorkspaceCache decorator (workspace-cache.decorator.ts)
- Added localOnly?: boolean option to skip Redis storage for
non-serializable data
Created WorkspaceEntityMetadatasCacheService
- Computes entity metadatas from DB to avoid race condition, this is
acceptable
Simplified GlobalWorkspaceOrmManager
- Now fetches entityMetadatas from cache instead of rebuilding on every
call
Updated Workspace migration runner - the only entry point where metadata
can change
- Now invalidate the new 'entityMetadata' local cache when
shouldIncrementMetadataGraphqlSchemaVersion is true (== field/object
mutations)
This PR fixes an issue where links added inside a note were not
appearing in the preview shown under Company -> Notes. The link would
only appear after opening the note, which led to inconsistent behavior.
Issue:
Blocknote represents text and links using different node types:
1. { "type": "text", "text": "Welcome to this demo!" }
2. {
"type": "link",
"content": { "type": "text", "text": "Example" },
"href": "https://example.com"
}
The existing preview function only handled plain text nodes and
completely ignored link nodes.
As a result:
- Links did not appear in the preview
- Links appeared only inside the full note view
Steps to Reproduce:
- Add a link inside a note
- Go to Company / People and view the note preview -> the link is
missing
- Open the note -> the link appears correctly
How I fixed it:
- A new recursive text extraction function (extractText) was added to
correctly read.
- Text nodes
- Link nodes (including inner content and the href)
- Nested child content
- Link previews now appear in the following format:
DisplayText (https://example.com)
Edit : closes https://github.com/twentyhq/twenty/issues/16043
---------
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
Fixes Issue: #16188
**Bug:**
Object Selection Dropdown was not working correctly when searching by
object's name.
This was happening only when `Search Records` action is selected.
Other actions(Create, Delete, Update, Upsert) were working
correclty(object search was working).
**Reason:**
`Search Records` action uses `WorkflowObjectDropdownContent` component
which only filters based on `nameSingular` field in metadata (and doesnt
search based on lable text).
All other record action uses the `Select` component which filters by the
label property (set to `labelProperty`).
**Fix:**
Updated the filtering logic of `WorkflowObjectDropdownContent` component
to match the search text with label field also.
I could't find any unit tests for the `WorkflowObjectDropdownContent`
component (or any other component in workflow module). Let me know if I
missed it and if tests need to be added for this.
**Screenshot of working object search in Search Record**
<img width="2056" height="1220" alt="image"
src="https://github.com/user-attachments/assets/678d9806-899a-470c-9e82-b9f975d65950"
/>
# Introduction
On production facing a migration error with
UpdateRoleTargetsUniqueConstraint1764329720503
```ts
Migration "UpdateRoleTargetsUniqueConstraint1764329720503" failed, error: could not create unique index "IDX_ROLE_TARGETS_UNIQUE_AGENT"
query: ROLLBACK
Error during migration run:
QueryFailedError: could not create unique index "IDX_ROLE_TARGETS_UNIQUE_AGENT"
at PostgresQueryRunner.query (/Users/paulrastoin/ws/twenty/node_modules/typeorm/driver/postgres/PostgresQueryRunner.js:219:19)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async UpdateRoleTargetsUniqueConstraint1764329720503.up (/Users/paulrastoin/ws/twenty/packages/twenty-server/dist/database/typeorm/core/migrations/common/1764329720503-update-role-targets-unique-constraint.js:15:9)
at async MigrationExecutor.executePendingMigrations (/Users/paulrastoin/ws/twenty/node_modules/typeorm/migration/MigrationExecutor.js:225:17)
at async DataSource.runMigrations (/Users/paulrastoin/ws/twenty/node_modules/typeorm/data-source/DataSource.js:265:35)
at async Object.handler (/Users/paulrastoin/ws/twenty/node_modules/typeorm/commands/MigrationRunCommand.js:68:13) {
query: 'ALTER TABLE "core"."roleTargets" ADD CONSTRAINT "IDX_ROLE_TARGETS_UNIQUE_AGENT" UNIQUE ("workspaceId", "agentId")',
parameters: undefined,
driverError: error: could not create unique index "IDX_ROLE_TARGETS_UNIQUE_AGENT"
at /Users/paulrastoin/ws/twenty/node_modules/pg/lib/client.js:526:17
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async PostgresQueryRunner.query (/Users/paulrastoin/ws/twenty/node_modules/typeorm/driver/postgres/PostgresQueryRunner.js:184:25)
at async UpdateRoleTargetsUniqueConstraint1764329720503.up (/Users/paulrastoin/ws/twenty/packages/twenty-server/dist/database/typeorm/core/migrations/common/1764329720503-update-role-targets-unique-constraint.js:15:9)
at async MigrationExecutor.executePendingMigrations (/Users/paulrastoin/ws/twenty/node_modules/typeorm/migration/MigrationExecutor.js:225:17)
at async DataSource.runMigrations (/Users/paulrastoin/ws/twenty/node_modules/typeorm/data-source/DataSource.js:265:35)
at async Object.handler (/Users/paulrastoin/ws/twenty/node_modules/typeorm/commands/MigrationRunCommand.js:68:13) {
length: 314,
severity: 'ERROR',
code: '23505',
```
As several agent has duplicated role target in database
```sql
SELECT constraint_name, COUNT(*) AS duplicate_groups, SUM(duplicate_count - 1) AS rows_to_delete
FROM (
SELECT 'IDX_ROLE_TARGET_UNIQUE_API_KEY' AS constraint_name, COUNT(*) AS duplicate_count
FROM "core"."roleTargets" rt
WHERE rt."apiKeyId" IS NOT NULL
GROUP BY rt."workspaceId", rt."apiKeyId"
HAVING COUNT(*) > 1
UNION ALL
SELECT 'IDX_ROLE_TARGET_UNIQUE_AGENT', COUNT(*)
FROM "core"."roleTargets" rt
WHERE rt."agentId" IS NOT NULL
GROUP BY rt."workspaceId", rt."agentId"
HAVING COUNT(*) > 1
UNION ALL
SELECT 'IDX_ROLE_TARGET_UNIQUE_USER_WORKSPACE', COUNT(*)
FROM "core"."roleTargets" rt
WHERE rt."userWorkspaceId" IS NOT NULL
GROUP BY rt."workspaceId", rt."userWorkspaceId"
HAVING COUNT(*) > 1
) AS all_duplicates
GROUP BY constraint_name;
```
with constraint name, duplicated_groups, row_to_delete
`IDX_ROLE_TARGET_UNIQUE_AGENT 2507 7229`
Please note that only active or suspended workspaces contains duplicated
role target
## Fix
Introduced an upgrade command that will only keep the latest inserted
role target
Swallowing migration error on typeorm atomic migration ( still required
for self host new instances etc )
```ts
[Nest] 91886 - 12/03/2025, 2:56:28 PM LOG [DeduplicateRoleTargetsCommand] Running command on workspace SOME_WORKSPACE_ID 2587/2587
flatFieldMetadataMaps,flatIndexMaps,flatObjectMetadataMaps out of 298
query: SELECT version();
[Nest] 91886 - 12/03/2025, 2:56:29 PM LOG [DeduplicateRoleTargetsCommand] Command completed!
```
## Test
Tested through an extract in local, tested both the upgrade command and
the swallowed migration
test
## Description
When switching a view's visibility from WORKSPACE to UNLISTED, the code
in `view-v2.service.ts` correctly sets `createdByUserWorkspaceId` to the
current user (to prevent the view from disappearing). However, this
property was not included in `FLAT_VIEW_EDITABLE_PROPERTIES`, which
meant:
1. The comparison logic didn't detect the change
2. No update action was created for the property
3. The value was never persisted to the database
4. The view disappeared because it became UNLISTED with no owner
This fix adds `createdByUserWorkspaceId` to the editable properties so
the change is properly detected and persisted.
Might fix https://github.com/twentyhq/twenty/issues/15955
# Introduction
Closes https://github.com/twentyhq/core-team-issues/issues/1980
In this PR we migrate the agent from v1 to v2.
## New FlatRoleTargetByAgentIdMaps
Derivated the `flatRoleTargetMaps` to be building a
`flatRoleTargetByAgentIdMaps` to ease retrieving a roleId to associate
to an agent
## Coverage
Added strong coverage on both failing and successful CRU agents
operations
---------
Co-authored-by: Weiko <corentin@twenty.com>
## What’s done
- Clicking a favorite folder on mobile now opens a clean drill-down
layer with only its contents
- Added a back button (icon + folder name) — visually 100% identical to
`NavigationDrawerBackButton`
- Sidebar no longer collapses when opening a folder
- Tree line is removed on mobile (consistent with current Twenty design)
## Intentional deviations from the mockup
1. **Back button does not replace `MultiWorkspaceDropdownButton`**
Kept `NavigationDrawerHeader` untouched — it’s responsible for the
hamburger menu and workspace name.
Added the back button as a separate block below.
→ This feels cleaner architecturally and avoids breaking other places
that use `NavigationDrawerHeader`.
2. **Vertical spacing between items is slightly tighter than in the
mockup**
Used `NavigationDrawerSubItem` — the standard component for nested items
in Twenty.
Current production spacing matches this exactly, so I preferred
consistency over pixel-perfect mockup matching.
Happy to adjust either point if the team prefers to follow the mockup
1:1.
Closes#15950
---------
Co-authored-by: Baptiste Devessier <baptiste@devessier.fr>
Set it to 180 days like Notion does.
Currently **Access Token Expires In** is set to 90 days but this setting
is ignored because the cookie is cleared after 7 days
2025-12-03 10:04:35 +01:00
Thomas TrompetteGitHubgreptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
- if >5000 workflows per hour, new ones should failed
- if >100 workflow per min, new ones should be set as not started.
Except manual trigger
- when enqueued, we check if there a not started workflows that may be
queued. If yes, we call the associated job
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
CommandMenu did not push its own focus item to the focus stack when
focused. (See NavigationDrawerInput)
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
This PR fixes a bug that created a deletedAt column in sample CSV file
generated for import, that when used afterwards for import, would create
soft deleted records, which gives the impression that the CSV import
does not work.
In this PR (1/3)
- introduce view.mainGroupByFieldMetadataId as the new reference
determining which fieldMetadataId is used in a grouped view, in order to
deprecate viewGroup.fieldMetadataId which creates inconsistencies.
view.mainGroupByFieldMetadataId is now filled at every view creation,
though not in use yet.
- Introduce a command to backfill view.mainGroupByFieldMetadataId for
existing views + delete all viewGroup.fieldMetadataId with a
fieldMetadataId that is not view.mainGroupByFieldMetadataId. (It should
concern 37 active workspaces)
- Temporarily disable the option to change a grouped view's
fieldMetadataId as for now it creates inconsistencies. This feature can
be reintroduced when we have done the full migration.
In a next PR
- (2/3) use view.mainGroupByFieldMetadataId instead of
viewGroup.fieldMetadataId. In FE we may keep viewGroup.fieldMetadataId
as a state (TBD). View groups will now be created / deleted as a side
effect of view's mainGroupByFieldMetadataId update.
- (3/3) remove viewGroup.fieldMetadataId
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
Introduce a read-only view of permissions similar to agent roles tab.
The role selector in the following image feels as if it would lead to a
new page, which is not what we want.
<img width="1281" height="813" alt="Permissions (If easier V1)"
src="https://github.com/user-attachments/assets/7b272f5a-40ef-43ad-83d8-f9e588b1cd6e"
/>
Therefore, I added a Select component for now and would love some
clarity on what's ideal.
<img width="554" height="651" alt="image"
src="https://github.com/user-attachments/assets/91575208-66b1-4ed1-86cd-f3aa528ad0dc"
/>
Also, the "Add Rule" button changes to enabled when we switch the role
from `Admin` to `Member` and clicking it redirects to
`/settings/roles/:role-id/add-object-permission`. Do we want to disable
the button completely?
One final thing: SettingsAgentRoleTab already re-uses
SettingsRolePermissions. I created MemberPermissionsTab to do the same.
I don't think we need an abstracted shared component here since both
tabs rely on the same shared child anyway. However, if we need a
refactor, I can use some direction on how the code should look.
Creating this PR as draft since I think there might be a couple
suggested changes on this.
Because of [this code I forget to
clean](https://github.com/twentyhq/twenty/pull/16217),
- __workspace created between 1.12.0 and 1.12.2 (from friday 28 nov PM >
monday 1 dec PM)__ have standard objects with empty string default value
set on related TEXT type column (but default value null on field
metadata) (ex: jobTitle on person)
- __custom objects created between 1.12.0 and 1.12.2 (from friday 28 nov
PM > monday 1 dec PM)__ have "name" TEXT field with empty string default
value set + NOT NULL constraint on column
Command cleans data and updates table structure
## Release 1.12.0
This release includes:
- Revamped Side Panel - Now opens next to content instead of above it
- Granular Email Folder Sync - Choose which Gmail labels or Outlook
folders to sync
Changelog file:
`packages/twenty-website/src/content/releases/1.12.0.mdx`
Release date: 2025-12-02