12670 Commits

Author SHA1 Message Date
Raphaël Bosi
bd4161a905 Show app logo on workflow logic function nodes (#21482)
Workflow `LOGIC_FUNCTION` action nodes (functions provided by an
installed app) previously rendered a generic ƒ icon in the diagram. They
now display the owning app's logo instead.

The node's logic function id is resolved to its `applicationId` and
rendered via the existing `AppChip`. When no app can be resolved (e.g.
the logic function isn't loaded yet, or has no application), it falls
back to the original ƒ icon, so nodes never look broken. Inline `CODE`
actions are unchanged.

## Before
<img width="692" height="670" alt="CleanShot 2026-06-12 at 15 27 22@2x"
src="https://github.com/user-attachments/assets/4d7c17ce-dbe3-45e6-9d44-41e363b2e4a5"
/>

## After

<img width="592" height="628" alt="CleanShot 2026-06-12 at 15 26 22@2x"
src="https://github.com/user-attachments/assets/d55c308f-3cde-4153-8d5d-ec948bebc823"
/>


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21482?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-12 13:36:30 +00:00
Raphaël Bosi
c4453923f0 Update CI: Argos visual regression for twenty-front storybook (#21454)
## What

Adds Argos visual regression for `twenty-front`, reusing the storybook
CI already builds and the existing sharded test matrix. Stories in the
`modules` and `pages` scopes are captured as PNGs during
`front-sb-test`, merged into one artifact, and pixel-diffed against
`main` on the self-hosted Argos with results posted as a PR comment —
same pipeline as `twenty-ui` (#21210 / #21262).

## How

- **Capture**: `@argos-ci/storybook` vitest plugin, same setup as
`twenty-ui`. Skipped for `performance` stories (nondeterministic
profiling reports). Freezes framer-motion to avoid flaky diffs (#21412).
- **Sharding**: each modules/pages shard uploads a partial artifact; a
new `front-sb-screenshots` job merges them into
`argos-screenshots-twenty-front` (`overwrite: true` so re-runs work).
- **Baselines**: `CI Front` now runs on `push: main` — Argos resolves
base builds by exact merge-base commit, so every main commit needs a
build (#21217/#21222 pattern). Main pushes get a per-SHA concurrency
group so back-to-back merges can't cancel queued runs and leave baseline
gaps; the `performance` scope is dropped on push.
- **Dispatch**: `visual-regression-dispatch.yaml` watches `CI Front` →
`project=twenty-front`.

## Rollout

-  Prod Argos project `twenty-front` created (id 68) +
`ARGOS_TOKEN_FRONT` secret set
-  Merge the twentyhq/ci-privileged companion PR **before** this one
- First PR builds show as *orphan* until the first main push creates a
baseline
  (expected, same as the twenty-ui rollout)
2026-06-12 13:36:16 +00:00
github-actions[bot]
ab7c760872 i18n - docs translations (#21493)
Created by Github action

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21493?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->

Co-authored-by: github-actions <github-actions@twenty.com>
2026-06-12 15:39:14 +02:00
Raphaël Bosi
e3cfbbffb5 Bill People Data Labs enrichments in Twenty credits (#21481)
Adds per-enrichment billing to the People Data Labs app. Each
**matched** record charges the workspace in Twenty credits via
`chargeCredits` (`twenty-sdk/billing`), following the same pattern as
the exa app.

- Person match: **336,000 micro-credits** ($0.336 — PDL list price $0.28
+ 20% margin)
- Company match: **120,000 micro-credits** ($0.12 — PDL list price $0.10
+ 20% margin)

> **Note:** the 20% margin is a first draft, not final — it's a single
constant (`src/constants/billing-margin-multiplier.ts`) and easy to
adjust once we settle on pricing.

PDL only consumes a credit on a successful match, so `not_found`,
errors, and skipped records are free. The charge is emitted once per PDL
batch call (≤100 records) with `operationType: CODE_EXECUTION`,
`quantity` = match count, and `resourceContext` `pdl/person` /
`pdl/company`, at the moment PDL responds — a match whose record write
later fails is still billed since the PDL cost was already incurred.
Billing failures are non-fatal and never break an enrichment.

Prices and margin live as constants in `src/constants/` for easy
retuning. No SDK bump needed (`twenty-sdk@2.10.1` already ships
`./billing`).
2026-06-12 13:13:17 +00:00
martmull
fa9aeea408 Add dev:generate-client command to sdk (#21489)
## after

`yarn twenty dev:generate-client`

<img width="1149" height="246" alt="image"
src="https://github.com/user-attachments/assets/1edcba03-2647-4bc8-8188-7ad69362ac52"
/>


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21489?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
twenty/v2.12.0
2026-06-12 12:58:20 +00:00
Raphaël Bosi
56e1d886d8 Add CI workflow for people data labs app (#21487)
Adds a dedicated CI workflow for the People Data Labs app that runs
lint, typecheck, and unit tests only when files under
`packages/twenty-apps/internal/people-data-labs/` change.

The app is a standalone yarn project (its own lockfile, pinned published
SDKs), so it isn't covered by the existing package CI workflows. The
workflow gates on the app folder via the reusable `changed-files.yaml`,
installs dependencies inside the app directory, and runs `yarn lint`,
`yarn typecheck`, and `yarn test`. A status-check job aggregates results
and stays green on skips, so it's safe to mark as a required check.


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21487?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-12 12:55:47 +00:00
Charles Bochet
7b6b624041 fix(server): bypass stale workspace cache when resolving currentUser during onboarding (#21461)
## Context

On twenty-main (multi-replica), signing up and naming a workspace lands
on a black screen at `/create/profile`; a manual refresh fixes it. From
the network trace: the post-activation `currentUser` response carries
`onboardingStatus: PROFILE_CREATION` (fresh) together with a non-ACTIVE
`currentWorkspace` and `workspaceMember: null` (stale).

## Root cause

`activateWorkspace` invalidates the core entity cache only on the
instance that served the mutation. When the follow-up `currentUser`
query is routed to a sibling instance, the auth context carries a
memoized pre-activation workspace snapshot. A stale transient workspace
cascades:

- `workspaceMember`/`workspaceMembers` resolve to null/empty
(`loadWorkspaceMember` skips non-active workspaces), permissions fall
back to defaults
- the client's metadata store never loads (`MinimalMetadataLoadEffect`
skips non-active workspaces), so `MinimalMetadataGater` shows the
loading skeleton forever on `/create/profile`

#20322 fixed the same staleness for `onboardingStatus` by reading the
workspace fresh from the database in the resolver — which is why the
status is fresh while the workspace object isn't, and why the client
navigates to a page it can't render.

#21480 bounds the staleness window to the designed 10s (absolute
memoizer TTL), but signup lives entirely inside that window: the client
reads `currentUser` ~1s after `activateWorkspace` and never refetches
while stuck.

## Fix

Apply the #20322 approach at the workspace status resolution layer:
`UserService.refreshWorkspaceIfPendingOrOngoingCreation` re-reads the
workspace from the database when the auth-context copy is in a transient
activation status (`PENDING_CREATION`/`ONGOING_CREATION`). Used in:

- `UserResolver.currentUser` — fresh `currentWorkspace` and permissions
- `UserService.loadWorkspaceMember` / `loadWorkspaceMembers` — covers
the `workspaceMember`/`workspaceMembers` resolve fields

No-op for active workspaces; the extra database read only happens for
workspaces mid-creation.

## Test plan

- Full `user.service.spec.ts` suite passes; lint and format clean.
- After deploy to twenty-main: sign up, name the workspace, verify
`/create/profile` renders the profile form with a populated
`workspaceMember` and ACTIVE `currentWorkspace` without refreshing.
2026-06-12 12:13:38 +00:00
Matt Van Horn
cb653e4ecc feat: inline image thumbnails and legacy-label fallback for FILES field chips (#21294)
## Summary

Custom FILES field chips now show an inline image thumbnail for image
attachments and fall back to the legacy label when an attachment
predates filename storage. This covers two of the UX complaints n2ojim
collected in #20942: image files were indistinguishable from other
attachments, and older attachments rendered with an empty chip label.
The 10-file cap from the same issue already shipped in #20950; the
gallery/grid layout and hover-delete affordances are deliberately left
for follow-ups per the maintainer's cost notes on the thread.

## Why this matters

#20942 is founder-tagged UX feedback on the new custom FILES field: once
a record carries more than a couple of attachments, users scan chips
visually, and a thumbnail answers "which one is the screenshot" without
opening anything. The fallback keeps old records readable instead of
showing blank chips. Changes stay inside `FileChip.tsx` and follow the
existing file-display patterns; Storybook stories cover both behaviors.

## Testing

Added 9 Storybook stories: image attachment (thumbnail), non-image (icon
unchanged), missing filename (legacy fallback label), long names, and
combinations. Targeted typecheck of the changed files surfaced no
errors; the monorepo's CI lint/build covers the rest.

Refs #20942

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2026-06-12 14:04:06 +02:00
Weiko
214dc70b67 Fix missing WasIntroducedInUpgrade for overridable view entity (#21483)
<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21483?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-12 11:33:31 +00:00
Charles Bochet
08a36aa68f fix(server): restore absolute TTL in PromiseMemoizer (#21480)
## Context

`PromiseMemoizer` sits in front of the staged lookup (local cache →
Redis hash validation → Redis data → DB recompute) of both
`CoreEntityCacheService` and `WorkspaceCacheService` (10s TTL each). The
Redis hash check is the **only** cross-instance invalidation mechanism —
there is no pub/sub — and it runs only when the memo entry expires.

The TTL is currently **sliding**: every read refreshes `lastUsed`, and
eviction compares against time-since-last-read. So any entry read more
often than every 10s on a given instance never revalidates, and that
instance serves stale data for as long as traffic continues. Affected
data: auth-context entities (workspace, user, userWorkspace), API key
revocations, role/permission maps, RLS predicates, feature flags, and
all metadata maps.

Observed manifestation: after `activateWorkspace`, a sibling instance
kept serving a `PENDING_CREATION` workspace snapshot (kept alive
indefinitely by the client's own polling), stranding signup on a
permanent loading skeleton at `/create/profile` (#21461). Same staleness
class as #20322 and the CI flakes investigated in #21435.

## Why it was sliding

#11444 (April 2025) deliberately changed the TTL from absolute to
sliding because the memoizer's then-consumer was the TypeORM datasource
storage: absolute expiry was destroying datasources that were actively
in use (`onDelete` → `destroy()`), causing worker `Connection
terminated` errors. That consumer no longer exists — datasources moved
to `GlobalWorkspaceOrmManager`, and neither remaining consumer passes
`onDelete` or holds resources needing keep-alive.

## Fix

Restore absolute expiry: `expiresAt` is set at write time and never
refreshed on read. Every instance now re-enters the staged lookup (and
thus the Redis hash validation) at least once per TTL, restoring the
designed ≤10s cross-instance staleness ceiling. Concurrent dedup
(`pending` map) and `onDelete` plumbing are unchanged.

## Test plan

- New regression test: reads at half-TTL intervals must not extend an
entry's lifetime (fails on the sliding implementation, passes now).
- Full `promise-memoizer.storage.spec.ts` and
`workspace-cache.service.spec.ts` suites pass (25 tests); lint and
format clean.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21480?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-12 11:30:49 +00:00
Marie
e334551da9 (Fix) Upsert no longer rewrites position on existing records (#21375)
## Fix: upsert no longer rewrites `position` on existing records

### Problem
`createX(..., upsert: true)` resets the `position` of records that
resolve to an **update**, even when the payload doesn't include a
`position`.

The create-many/upsert runner backfills `position` (to `"first"`) in
`computeArgs` over the **whole batch**, before records are split into
insert vs update. So existing rows get a freshly recomputed `position`
written on every upsert. For callers that re-upsert their full dataset
on a schedule (e.g. a daily sync), this rewrites `position` for every
record on each run and drifts the values steadily negative — and it
floods audit/event logs with position churn.

The dedicated `updateOne`/`updateMany` runners already pass
`shouldBackfillPositionIfUndefined: false`; the upsert path did not.

### Fix
Only backfill `position` for records that are actually inserted:
- `computeArgs` now passes `shouldBackfillPositionIfUndefined:
!args.upsert` in both the create-many and create-one runners, so
undefined positions are left untouched on upsert.
- `performUpsertOperation` backfills `"first"` positions for
`recordsToInsert` only, **after** categorization, via
`RecordPositionService`.

Explicit `position` values (`"first"`, `"last"`, or a number) in the
payload are still honored. Plain (non-upsert) create behavior is
unchanged.

### Behavior
| Scenario | Before | After |
|---|---|---|
| Upsert updates existing row, no `position` sent | `position` rewritten
| `position` untouched |
| Upsert inserts new row, no `position` sent | gets `"first"` | gets
`"first"` (unchanged) |
| Explicit `position` on upsert | applied | applied |
| Plain create | unchanged | unchanged |
2026-06-12 08:50:09 +00:00
Raphaël Bosi
a0e3c43234 People data labs app: remove navigation menu items (#21478)
Removes the People Data Labs app navigation menu — the "People Data
Labs" folder and its two view entries (Enriched People, Enriched
Companies) — from the sidebar, along with the now-unused navigation menu
item identifiers.

The "Enriched (PDL)" view definitions are kept and remain available on
the Person and Company objects; they just no longer appear as a folder
in the navigation menu.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21478?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-12 08:24:06 +00:00
Etienne
fefd9d7704 feat(workflow) - Add validation layer (#21422)
Add workflow validation framework and consolidate output schema
types/search logic into twenty-shared

This PR introduces a comprehensive workflow validation system that
catches configuration errors at build-time, and consolidates the
fragmented output-schema type definitions and variable-search logic from
the front-end into twenty-shared

**Workflow validation** — A new system that checks workflows for errors
before activation: graph connectivity (unreachable steps, dangling
references), step parameter schemas (via Zod), variable references
(typos, wrong step order), and workspace metadata (non-existent
objects). Returns structured errors/warnings with "did you mean?"
suggestions. Runs automatically after create_complete_workflow and
update_workflow_version_step, and is also available as a standalone
validate_workflow tool.

**Output schema consolidation** — Moves all output schema types and the
variable-search logic from scattered front-end files into twenty-shared,
replacing ~800 lines of duplicated per-schema-type code with a single
unified searchVariableInOutputSchema dispatcher.


To do : 
- validation on CODE and AGENT step

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 08:23:03 +00:00
Raphaël Bosi
2538239e05 People data labs: update app logo (#21479)
Replaces the People Data Labs internal app icon with the new logo.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21479?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-12 10:26:11 +02:00
Rashad Karanouh
adbd78767e feat(partners): lock admin-managed + ownership fields on Partner role (#21471)
## What

Tightens the **Partner** self-service role's field-level permissions so
a partner can edit its own profile but not admin/ops-controlled or
ownership fields. All locks are `canUpdateFieldValue: false` on the
Partner object.

**Admin-managed scalar fields (7):** `slug`, `validationStage`,
`reviewed`, `ranking`, `partnerTier`, `applicationNotes`, `lastMatchAt`

**Ownership relation FKs (2):** `partnerUser`, `company`

## Why

- The 7 scalar fields are admin/ops-controlled (validation, ranking,
tiering, internal notes) — a partner must not be able to self-promote or
alter ops data.
- `partnerUser` is the **RLS pivot**: the row-level predicate scopes a
partner to records where `partnerUser IS <their workspace member>`. If a
partner could clear or repoint it, they'd drop their own record out of
scope (an orphan only admins can see). It is already locked on
Opportunity; this brings Partner in line.
- `company` is read-only at the object level for partners, so its FK
link must not be repointable from the Partner side either.

The remaining Partner relations (`opportunities`, `persons`,
`partnerContents`) need no lock — they are already protected by
inverse-side field locks or object-level read-only / no-access rules.

## Scope

- One source file: `src/roles/partner.role.ts` (9 field-permission
entries).
- No schema changes — additive permission tightening; upgrades cleanly
via `deploy` + `install`.
- Version: patch bump `0.5.0 → 0.5.1`.
2026-06-12 07:24:15 +00:00
github-actions[bot]
e6d730cd75 chore: sync AI model catalog from models.dev (#21476)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

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

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

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21476?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-06-12 09:31:00 +02:00
Félix Malfait
69a7e614ff fix: restore isCustom gate in metadata label resolvers (#21432)
## Context

#21228 removed the stored `isCustom` column and, with it, the `isCustom`
early-return in `resolveObjectMetadataStandardOverride` /
`resolveFieldMetadataStandardOverride`, on the assumption that falling
through the `standardOverrides` checks was equivalent.

It isn't: custom object/field labels now reach the Lingui lookup. A
custom label that collides with a standard catalog string (e.g. a custom
field labeled "Status") gets translated for non-English locales against
the user's intent, and every other custom label pays a hash + catalog
miss — and, in production, an "Uncompiled message detected" warning
(#21415) — on each metadata resolution.

## Fix

Restore the gate. `isCustom` is no longer stored, so call sites that
build the resolver input from flat entities (dataloader,
minimal-metadata, view controller, command-menu-item navigation context)
derive it via `belongsToTwentyStandardApp`; GraphQL resolvers keep
passing DTOs, which already carry the derived value.

## Testing

- Unit tests for both resolvers, including a new regression test: a
custom label matching a standard catalog entry is returned verbatim,
Lingui never called.

---------

Co-authored-by: Weiko <corentin@twenty.com>
2026-06-11 16:10:53 +00:00
Weiko
cfb9772179 feat(server): convert view to overridable entity (#21436)
## Context

Every entity created as a side effect of object creation must support
the overridable pattern (`isActive` + `overrides` + override routing)
before we can re-own side effects to their true application. Starting
with View.

viewField, viewFieldGroup, pageLayoutTab and pageLayoutWidget already
extend `OverridableEntity`. This PR brings `view` to the same pattern.

## What this does

- `ViewEntity` now extends `OverridableEntity<ViewOverrides>` (adds
`isActive` boolean + `overrides` jsonb). All editable view properties
are overridable; the 3 fieldMetadata foreign keys are converted to/from
universal identifiers like viewField's `viewFieldGroupId`.
- **Update**: mutations on a view not owned by the caller (e.g. standard
views like "All Companies") are written into `overrides` instead of
mutating the row. Reads merge overrides in
the DTO.
- **Delete/destroy**: views not owned by the caller are deactivated
(`isActive = false`) instead of deleted.
~~- **INDEX invariant**: `key = INDEX` views can only be created via
object-creation side effect. The API now rejects creating, deleting or
destroying INDEX views (object-deletion cascade is unaffected). This was
not really needed for this migration but was flagged during
implementation.~~
- **Front**: views with `isActive = false` are filtered out of the views
selector.
- Fast instance command adds the two columns
(`2-12-instance-command-fast-...-view-overridable-entity.ts`).

## Notes

- Custom (caller-owned) views behave exactly as before: direct updates,
soft delete.
- View-group side effects (kanban groups) are computed on the
override-merged view so overridden `mainGroupByFieldMetadataId` works.
2026-06-11 16:00:52 +00:00
DeviSriSaiCharan
947a4d5253 Fix: prevent unexpected navigation when destroying record from side panel (#21391)
Fixes: #21243 

# Issue
When a user is on a specific record's page (for example, looking at a
Person) and opens a related record (like a Note) in the right-side
panel, clicking "Permanently Delete" on that Note would abruptly
redirect the user to the main "Notes" list. This breaks the user's
workflow, as they typically want to remain on the parent Person page
after deleting a sub-record.

# Root Cause
Inside the `DestroyRecordsCommand` and `DeleteRecordsCommand`
components, the application was programmed to unconditionally trigger a
`navigateApp` redirect to the deleted object's index page upon
successful deletion. The code did not account for whether the deletion
was triggered from the main index page or from inside a contextual side
panel.

# How we fixed it
I introduced a new `isInSidePanel` flag into the
`HeadlessCommandContextApi`.
The command menu now detects if the delete action originated from inside
a side panel and passes this flag down the execution chain. If `true`,
the `DestroyRecordsCommand` simply closes the panel
(`closeSidePanelMenu()`) and keeps the user exactly where they were.

## After that fix, I encountered another issue (UI not updating
automatically)
Because the app now correctly kept the user on the Person page, a new
bug surfaced: the "Note" chip inside the relation table did not
disappear immediately. The user had to manually refresh the page to see
the deletion.

This happened because:
1. The Apollo optimistic cache occasionally failed to trace deeply
nested morph-relationships back to the parent.
2. A standard local React `useState` fallback was insufficient. The
table component aggressively unmounts and remounts relation cells
whenever a user hovers over them to display interactive controls, which
would wipe the local React state clean and cause the "ghost chip" to
reappear.

##How I fixed that issue (and optimized it)
I built an event-driven fallback using global Jotai state to permanently
hide the chips:

1. **Precision ID Broadcasting**: I updated the `useDestroyManyRecords`
and `useIncrementalDestroyManyRecords` hooks to extract and broadcast
only the *confirmed* destroyed IDs directly from the Apollo mutation
response, preventing false-positive UI removals if the backend performed
a partial delete.
2. **Batch Optimizations**: During bulk deletions, events are now
broadcasted per-batch rather than accumulating thousands of IDs in
memory until the end, keeping the UI instantly responsive and memory
bounded.
3. **Per-Cell State Scoping (`atomFamily`)**: Instead of a leaky global
array, we used Jotai's `atomFamily` to dynamically generate a unique
Noticeboard for every specific table cell (`${recordId}-${fieldName}`).
This ensures the hidden-state survives mouse-hover unmounts while
remaining cleanly isolated.
4. **Defensive Filtering**: The `RelationFromManyFieldDisplay` component
was updated to defensively guard against `undefined` array entries and
strictly match deleted IDs only against valid foreign keys (ending in
`'Id'`), preventing false-positive removals if a UUID happened to be
pasted into a description field.
5. **SSE Resilience**: We hardened the Server-Sent Event (SSE) listeners
with optional chaining and null-filtering to ensure malformed backend
payloads do not crash the real-time event pipeline.


# Screen Recording


https://github.com/user-attachments/assets/19fc8a3f-ba28-43c2-b1f3-a91127cdad97

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
2026-06-11 15:40:56 +00:00
Charles Bochet
deb956f4fe security: bump wait-on 7.2.0 -> 9.0.10 to drop vulnerable joi (Dependabot alert 1437) (#21457)
## Context

Two open Dependabot alerts; this PR fixes one with a parent bump (no
resolutions), the other is dismissed with analysis (see below).

## joi RangeError DoS (alert 1437, fixed in joi 18.2.1)

`joi@17.13.3`'s only parent is `wait-on@7.2.0` (twenty-sdk
devDependency, used purely as a CLI: `yarn start`'s `wait-on tcp:3000`
and CI's `wait-on http://localhost:3000/healthz --timeout --interval`).
Bumping **wait-on 7.2.0 → 9.0.10** (which depends on `joi ^18.2.1`)
evicts joi 17 from the lockfile entirely — no forced ranges.

Verified: twenty-sdk builds; wait-on 9 smoke-tested with both invocation
shapes used in the repo (`tcp:PORT`, `http://… --timeout --interval`).

## @cyntler/react-doc-viewer TXTRenderer "XSS" (alert 1436) — dismissed
as inaccurate

CVE-2026-30691 claims arbitrary JS execution via a crafted .txt because
TXTRenderer "casts raw data as a ReactNode". Verified against the
installed 1.17.1 dist: the renderer is `children:
currentDocument?.fileData` where the txt fileLoader produces `fileData`
via `FileReader.readAsText` — i.e. **always a string rendered as a React
child, which React HTML-escapes**. There is no
`dangerouslySetInnerHTML`/eval in the path (the only
`dangerouslySetInnerHTML` occurrence in the bundle is styled-components'
prop whitelist regex). String children cannot execute script in React;
the advisory's premise is wrong, and consistently upstream has published
no fix. Alert dismissed as *inaccurate* with this analysis.

Longer-term, `@cyntler/react-doc-viewer` remains a liability (stale
since 2025-09, already needs an ajv resolution) — replacing it with
first-party preview renderers is tracked separately.
2026-06-11 17:42:34 +02:00
Rich Roberts
41cdd83367 fix(ai): correct RICH_TEXT and MORPH_RELATION record filter operators (#21106)
## Problem

The AI find-records tool generates filter schemas via
`generateFieldFilterZodSchema`. `RICH_TEXT` currently shares the `TEXT`
case, so the agent is told it can use scalar text operators
(`like`/`ilike`/`startsWith`/`endsWith`/`eq`/…) directly on a rich-text
field.

But `RICH_TEXT` is a **composite** type (`markdown` + `blocknote`
sub-fields, see `rich-text.composite-type.ts`). Applying a scalar
operator to the composite root throws at query time:

```
ERROR [FindRecordsService] Failed to find records: Object person doesn't have any "ilike" field.
ERROR [FindRecordsService] Failed to find records: Sub field "ilike" not found for composite type: RICH_TEXT
```

`FindRecordsService` catches and returns `success: false`, so the agent
retries mid-turn — burning latency/tokens — and can **never** search
rich-text body content (note bodies, `about`, etc.).

## Fix

Give `RICH_TEXT` its own case in the filter-schema generator that
exposes the `markdown` and `blocknote` sub-fields, each carrying the
text operators — mirroring the existing composite patterns for `EMAILS`
(`primaryEmail`), `PHONES` (`primaryPhoneNumber`), `LINKS`
(`primaryLinkUrl`), `FULL_NAME`, and `ADDRESS`.

So the agent now emits:

```jsonc
{ "noteBody": { "markdown": { "ilike": "%onboarding%" } } }   // valid composite sub-field filter
```

instead of:

```jsonc
{ "noteBody": { "ilike": "%onboarding%" } }                   // throws on composite root
```

This both **stops the throw** and **makes rich-text content actually
searchable** (the original intent). `TEXT` keeps its existing root-level
scalar operators unchanged.

## Test

Added `__tests__/field-filters.zod-schema.spec.ts`:
- `RICH_TEXT` routes pattern operators onto `markdown` / `blocknote`
- root-level scalar operators on `RICH_TEXT` are no longer accepted
- `TEXT` root-level operators unchanged

## Notes

- No DB/schema migration; render/tool-schema layer only.
- Reproduced against `twentycrm/twenty:latest`; the faulting code is
unchanged on `main` as of this PR.

---------

Co-authored-by: Rich Roberts <rich.roberts@talentpipe.ai>
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2026-06-11 17:13:26 +02:00
Charles Bochet
503c689f37 security: upgrade typeorm to 0.3.26 (CVE-2025-60542) (#21456)
## Context

Retry of the typeorm upgrade that was pulled out of #21448 after CI
showed "intermittently lossy metadata sync". **The investigation
exonerated typeorm**: the postcard/seed failures were a pre-existing bug
in `@ptc-org/nestjs-query-typeorm`'s batched relation paging (global
LIMIT across parents) that scan-order luck had been hiding — reproduced
byte-for-byte on typeorm **0.3.20** against a frozen repro DB. That bug
is fixed in #21455, which this PR is stacked on (base branch =
`charles/fix-nestjs-query-batch-relation-paging`; will retarget to main
when it merges).

## Changes

- typeorm `0.3.20` → `0.3.26`
([CVE-2025-60542](https://github.com/advisories/GHSA-q2pj-6v73-8rgj),
MEDIUM). The CVE lives in TypeORM's MySQL path
(`sqlstring`/`stringifyObjects`); Postgres-only Twenty never exercises
it — this is scanner hygiene + staying current.
- The local yarn patch (`PickKeysByType` + `DeleteResult.generatedMaps`)
applies **verbatim** to 0.3.26 (verified against the pristine tarball) —
renamed to `typeorm+0.3.26.patch`.
- `WorkspaceRepository.query` restricted override adapted to the generic
`query<T = any>()` base signature introduced in 0.3.24 (one-line change,
still throws `RAW_SQL_NOT_ALLOWED`).
- 0.3.26 ships `uuid ^11` natively → the scoped `typeorm/uuid`
resolution from #21441 and its `//resolutions` comment clause (including
the now-disproven "lossy sync" warning) are removed.

## Why we're confident this time

The original failure signature was fully understood, not just retried:
- On a frozen failing DB, **all fieldMetadata rows + workspace columns
were intact** — only the batched metadata API read was truncated (`LIMIT
501` over 558 rows, no ORDER BY).
- Same DB, typeorm 0.3.20: identical truncation, identical SQL → not a
typeorm regression.
- With #21455 applied: postcard install/uninstall stress loop **12/12
green on typeorm 0.3.26** (previously failed within 1–2 iterations), API
returns 558/558 fields.

## Verification

- `npx nx typecheck twenty-server` — clean
- Full `twenty-server` unit suite — green (5651 passed)
- `group-by-resolver` integration suite — 19/19 on a fresh 0.3.26-seeded
test DB
- Postcard app-sync stress loop — 12/12 on this exact stack
- Lockfile: typeorm 0.3.26 + new `sql-highlight` dep, `esbuild`/uuid
entries untouched
2026-06-11 16:41:22 +02:00
Charles Bochet
d75685b8dc fix(metadata): nestjs-query batched relation queries truncate results across parents (#21455)
## TL;DR

The metadata API silently drops relation rows whenever a batched
relation query exceeds the requested page size. A dev-seeded workspace
already has **558 fieldMetadata rows across 31 objects**, so
`objects(paging:{first:50}) { fields(paging:{first:500}) }` executes:

```sql
SELECT DISTINCT ... FROM core."fieldMetadata" fields
WHERE workspaceId = $1 AND objectMetadataId IN (...31 ids...)
LIMIT 501 OFFSET 0   -- no ORDER BY
```

…and returns exactly **501 of 558** fields — ~57 rows dropped, and
*which object loses which field is scan-order-dependent*. This is what
made `example-app-postcard` CI flap with "PostCard object missing field
X" (different X per run).

## Root cause

`@ptc-org/nestjs-query-typeorm`'s `batchQueryRelations` (the DataLoader
batch path behind every `@CursorConnection`) applies the **per-parent**
page size as a **single global LIMIT** on the batched query, then groups
rows per parent in memory. Any batch whose combined relation rows exceed
`first + 1` truncates arbitrary parents. This affects production
metadata reads, not just CI — any workspace with enough fields/objects
loses rows in `objects.fields`-style connections.

## Fix

Yarn patch on `@ptc-org/nestjs-query-typeorm@9.4.0` (same vehicle as the
existing `nestjs-query-graphql` patch):
- `RelationQueryBuilder.batchSelect`: only apply LIMIT/OFFSET when the
batch has a **single parent**; multi-parent batches stay **bounded**
with `parents × (offset + limit)` — the upper bound a correct per-parent
pager can ever need, so it cannot wrongly truncate while still guarding
against unbounded fetches on high-cardinality relations;
- `batchQueryRelations`: enforce paging **per parent** by slicing after
`mapRelations` (preserves the `first + 1` hasNextPage probe semantics).

## Verification

- On a frozen repro DB (postcard installed, 558 fields): unpatched
returns 501 fields with `postCard` missing `deliveredAt`; patched
returns **558/558** with the full `postCard` field set. Reproduced
identically on typeorm 0.3.20 and 0.3.26 — pre-existing bug, **not** a
typeorm regression (this unblocks the typeorm upgrade that was reverted
from #21448).
- Postcard install/uninstall stress loop: unpatched fails within 1–2
iterations; patched **12/12 green**.
- `npx nx typecheck twenty-server` clean, full `twenty-server` unit
suite green (5651 passed).

## Related

#21435 chases the **same CI symptom** (postcard randomly missing a
freshly synced field) at a different layer — a workspace-cache write
racing invalidation. The two are complementary: the repro behind this PR
survives a **cold server restart + `redis-cli FLUSHALL`** with all rows
intact in Postgres, which no cache race can explain — the truncation
happens on the DB read itself (`LIMIT 501` over 558 matching rows,
captured via `log_statement=all`). Both fixes are likely needed for the
postcard job to be fully reliable.

## Notes

Worth upstreaming to `@ptc-org/nestjs-query` eventually; the proper
upstream fix is per-parent windowed pagination (`ROW_NUMBER() OVER
(PARTITION BY parentId)`), but the in-memory per-parent slice is correct
and proportionate at metadata-API scale.
2026-06-11 16:39:14 +02:00
martmull
d0884bd708 Fix missing datetime filter type (#21451)
Currently datetime fields are only typed to be filtered by string

Add a proper typing to match gql filters

## Before
<img width="750" height="492" alt="image"
src="https://github.com/user-attachments/assets/ff3a5423-3bb0-4295-84c9-e404489354f6"
/>

## After
<img width="537" height="511" alt="image"
src="https://github.com/user-attachments/assets/d8c8219f-b7de-41b0-96cb-5adbfda7a91d"
/>
2026-06-11 13:47:08 +00:00
Thomas Trompette
0ac4f237c0 fix(server): stop redundant lambda rebuilds causing build-lock acquisition failures (#21442)
## Context

`Lambda invocation failed for function '<id>' during build: Failed to
acquire lock for key: lambda-build:<id>` fires ~1000 times/day in
production.

## Root cause

`LambdaExecutorManagerService.buildExecutor` re-checks `canSkip` inside
the `lambda-build:<functionId>` lock, but the re-check reuses the
`flatApplication` snapshot captured when the request started. `canSkip`
depends on `!flatApplication.isSdkLayerStale`, so:

1. An app sync/install regenerates the SDK client and sets
`isSdkLayerStale = true`
2. All in-flight executions of the function fail `canSkip` and queue on
the lock
3. The first holder rebuilds and `markSdkLayerFresh` clears the flag in
DB + workspace cache
4. Queued waiters can't see that fix — their in-memory snapshot still
says stale — so **each waiter redoes the full rebuild serially**
(download SDK archive, delete + republish layer, update function config,
wait for update)
5. The lock is held back-to-back for minutes; everyone deeper in the
queue exhausts the 120s retry budget and throws

The local driver already handles this correctly
(`LocalLayerManagerService` refreshes the flat application from the
workspace cache inside its lock); the lambda driver missed it.

## Fix

- Refresh `flatApplication` from the workspace cache inside the lock
before re-checking `canSkip`, so waiters skip in ~100ms once the first
holder finishes
- Degrade gracefully on lock-acquisition timeout: re-check build status
with fresh data and proceed with the invocation if the executor is
already usable, instead of failing the run (introduces a typed
`CacheLockAcquisitionError` so only that case is caught)

## Test plan

- [x] `cache-lock.service.spec.ts` passes
- [x] `lint:diff-with-main` + typecheck pass
- [ ] Monitor `Failed to acquire lock for key: lambda-build:*` error
rate in production after deploy
2026-06-11 13:26:38 +00:00
github-actions[bot]
796f763bb7 i18n - website translations (#21453)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-06-11 15:35:27 +02:00
Charles Bochet
184c4948d6 security: strip Node dev headers from images + lingui 5.9.5 (drops vulnerable esbuild) (#21448)
## Context

AWS Inspector flags the `prod-twenty` image (built from current main)
with 16 findings, and Dependabot alert 174 flags esbuild. This PR fixes
the OpenSSL scanner findings and the esbuild CVE. The typeorm bump
(CVE-2025-60542) was **pulled out of this PR** — see "typeorm status"
below.

## Changes

### Strip `/usr/local/include/node` from runtime stages
(`twenty-server`, `twenty-app-dev`)
15 OpenSSL CVEs (June 9 advisory, incl. CRITICAL CVE-2026-34182) are all
detected via **Node's bundled OpenSSL dev headers**: 3 GENERIC
`openssl/openssl` 3.5.6 detections per CVE at
`/usr/local/include/node/openssl/archs/linux-x86_64/{asm,asm_avx2,no-asm}/include/openssl/opensslv.h`.
The headers are only needed by node-gyp and native addons are compiled
in the build stages — nothing compiles at runtime. Dropping them clears
all 45 detection instances and permanently ends this class of finding
(third occurrence: 3.5.5 → 3.5.6 → 3.5.7). None of these CVEs are
reachable through Node (no CMS/PKCS#7 API, `pfx` is operator-supplied,
Node's QUIC uses ngtcp2, ASN.1 issues need ~2GB inputs).

**Follow-up (~June 17, 2026):** the `node` binary itself still
statically links OpenSSL 3.5.6 — invisible to the scanner after this PR
and unreachable in practice, but the real fix is bumping the pinned
`node:24-alpine` digest once the [announced June 17 Node.js security
releases](https://nodejs.org/en/blog/vulnerability/june-2026-security-releases)
ship a 24.x linking OpenSSL ≥ 3.5.7 (verify via
`deps/openssl/openssl/VERSION.dat` on the release tag — 24.16.0 is still
on 3.5.6). A dated TODO sits next to the cleanup in the Dockerfile.

### esbuild dev-server CORS CVE (Dependabot alert 174,
GHSA-67mh-4wv8-2f99)
`@lingui/cli@5.1.2` (pins `esbuild ^0.21.5`) was the last parent
resolving a vulnerable esbuild (≤ 0.24.2 lets any website send requests
to the dev server and read responses). Instead of a resolution override,
this bumps the lockstepped **lingui suite 5.1.2 → 5.9.5** (within-major;
lingui adopted `esbuild ^0.25.1` in 5.4.1), which:

- removes `esbuild@0.21.5` and all its platform packages from the
lockfile with no forced ranges;
- drops the `@lingui/core` lockstep resolution (its comment marked it
droppable on the next coordinated lingui bump — the tree now resolves a
single `@lingui/core@5.9.5`);
- `@lingui/swc-plugin` stays at `^5.11.0` (peers on `@lingui/core: 5`;
its 6.x line targets lingui 6).

**lingui 5.9.5 behavioral fallout handled here:**
- Translation functions now **throw without an active locale** (5.1.2
fell back silently). The global `i18n` singleton that backs server-side
`` t`…` `` calls only had a messages compiler set, never an activated
locale → activate the source locale in `I18nService.loadTranslations()`,
mirrored in the server jest setup (unit tests bypass Nest bootstrap).
- `msg`/`t` placeholders are now strictly typed (reject
`null`/`undefined`/`unknown`) → one server call site and 16 twenty-front
files adapted with minimal nullish-coalescing fixes that preserve
rendering.
- `.po`/compiled-catalog churn from the new extractor/compiler
(reference reordering, sorted keys — verified content-identical on
unchanged `.po` inputs) is intentionally not committed: the scheduled
i18n workflows regenerate those.

## typeorm status (pulled out)

typeorm 0.3.20 → 0.3.26 was originally in this PR but **made workspace
metadata sync intermittently lossy**: `example-app-postcard` failed
twice with a *different* field missing from the synced PostCard object
each run, and one integration shard's `DataSeedWorkspaceCommand` died
with "Could not find flat entity with universal identifier …" — versus
zero such failures on recent main. Local runs (db reset + seed, group-by
integration suite 19/19) pass, so it is a nondeterministic
CI-load-sensitive regression that needs dedicated debugging (typeorm
changed LIMIT/OFFSET 0 semantics, lazy count for `getManyAndCount`,
upsert WHERE construction, and topological-sort internals in that
range). The resolutions comment documents this as the blocker;
CVE-2025-60542 is MySQL-driver-only (`sqlstring`), so Postgres-only
Twenty is not exposed in the meantime.

## Verification

- `npx nx typecheck twenty-server` / `twenty-front` — clean (no cache)
- `npx nx test twenty-server` — full suite green
- `lingui:extract` + `lingui:compile` — clean for twenty-server /
twenty-emails / twenty-front
- `oxfmt --check` — clean for both packages
- Lockfile diff: lingui 5.9.5 entries, `esbuild@0.21.5` +
`@esbuild/*@0.21.5` platform packages removed, no typeorm changes
2026-06-11 15:11:29 +02:00
Etienne
303c415dd1 fix(ai) - add logs + remove dashboard building (#21440)
- add logs for thread finishing without agent message
- add logs to monitor toolCall token usage
- remove dashboard building via AI (before fixing it)
- fix Anthropic compute
2026-06-11 12:45:25 +00:00
Etienne
a6fcbf58e4 fix(billing) - enable upgrade if invoice already paid (#21450)
Had an issue concerning a user with credits, then invoice automatically
paid. Upgrade failed
2026-06-11 12:45:01 +00:00
Raphaël Bosi
7da6f25aaf Replace random remote images in stories to stop flaky Argos diffs (#21447)
### Problem
`TabButton` and `AvatarOrIcon` stories (in both `twenty-ui` and
`twenty-ui-deprecated`) used random remote image URLs —
`picsum.photos/192/192` and `i.pravatar.cc/300`. Each Argos run fetched
a different image, producing false-positive pixel diffs.

This is the image counterpart to #21412, which froze framer-motion
animations for the same reason.

### Fix
Replace all 6 random URLs with `AVATAR_URL_MOCK` — a fixed base64 data
URI already used across avatar stories. It's deterministic and
network-free, so screenshots are now stable across runs.

- `twenty-ui` / `twenty-ui-deprecated` → `TabButton.stories.tsx` (×2
each)
- `twenty-ui` / `twenty-ui-deprecated` → `AvatarOrIcon.stories.tsx` (×1
each)

Note: this changes the rendered image content, so it adds new baselines
(one-time Argos approval, not flakiness).
2026-06-11 11:41:01 +00:00
Rashad Karanouh
f7463886a6 feat(partners): partner role row-level security (RLS) with scoped edits (#21386)
## Summary
Adds an external **Partner** self-service role that sees and edits only
its own
records via row-level security (RLS), so a validated partner can sign in
and manage
just the deals they're matched on.

## What's included
- **`partnerUser` relation** on Partner, Person, Company, Opportunity (+
inverse
  relations on Workspace Member) — the login member a record belongs to.
- **RLS predicates** scoping each of those objects to "partnerUser IS
the current
workspace member", plus a self-scope on Workspace Member so member-typed
relations
resolve without exposing the internal team roster. Applied out-of-band
via
  `yarn rls:configure` (the app manifest cannot ship RLS predicates).
- **Assign / unassign cascade** (`on-opportunity-partner-assigned` logic
function):
assigning a Partner to an Opportunity stamps `partnerUser` onto the
Opportunity +
its Company + People; removing the Partner clears it (and cascades to
the
  Company/People when no other deal of that member still uses them).
- **Partner role permissions**
  - Partner profile: full read/update.
- Opportunity: read all; **update `stage` and `amount` only** (every
other
    user-facing field locked).
  - Company / Person: read-only.
  - Workspace Member: read-only, RLS-scoped to self.
- **`partnerUser` column** added to the Validated Partners view so the
login member
  can be assigned inline.

## Install / upgrade note
After install or reinstall, run `yarn rls:configure` (`:prod` variant
for prod) to
(re)apply the RLS predicates and verify the field-permission locks.
Manifest sync
handles object/field permissions; predicates are applied by this script.

## Platform gaps found (for the eng team)
1. **Manifest sync doesn't invalidate the roles-permissions Redis
cache.** Permission
changes deployed via `yarn twenty dev --once` persist to the DB but
aren't reflected
   in the cached snapshot used for enforcement until

`engine:workspace:metadata:permissions:roles-permissions:<workspaceId>:{data,hash}`
   is flushed. Relevant on any real workspace when permissions change.
2. **Locking a server-injected field silently breaks all updates.** The
`*.updateOne`
pre-query hook writes `updatedBy` into every update, so
`canUpdateFieldValue:false`
on `updatedBy` makes the permission check reject *every* record update
with
`PERMISSION_DENIED`. Field-permission lock lists must exclude
server-managed/injected
fields (`updatedBy`; and `position`, co-written with `stage` on kanban
drag).

## Version
Minor bump → `0.5.0` (new role, new fields, new behaviour;
backwards-compatible).

## Testing
- Verified locally as a partner user: edits own profile; edits
Opportunity stage +
amount; Company/Person read-only; sees only matched deals; unassigning a
partner
  removes the deal (and its company/people) from the partner's view.
- `yarn rls:configure` passes (5 predicates upserted; 24 Opportunity
fields locked,
  stage + amount editable).
- Lint clean.
2026-06-11 11:37:35 +00:00
Charles Bochet
166f7ee0d2 chore(deps): prune yarn resolutions down to load-bearing entries (#21446)
## Context

Audit of all 28 `resolutions` entries in the root package.json against
yarn.lock dependency graphs and the npm registry, to remove every entry
that is no longer forcing anything a normal resolution wouldn't do —
resolutions are hard to maintain and silently freeze versions.

Net result: **28 → 22 entries**, two small dependency bumps replace
pins, and every remaining entry now has its blocker + removal condition
documented in `//resolutions`.

## Removed — dead weight (re-resolution lands on the same safe versions)

| Entry | Why it was dead |
|---|---|
| `type-fest: 4.10.1` | Stale 2024 dedup pin that semver-overrode ~16 of
19 declared ranges (forced `^0.13`/`^0.20`/`^0.21` consumers up four
majors, `^5.x` consumers down one). Types-only; each parent now resolves
its own compatible copy. |
| `typescript: 5.9.3` | No-op: every range (`^5.9.3`, `5.9.3`, `~5.9.2`)
resolves to 5.9.3 naturally. Only the electron-forge scaffolding
template regains its own nested `~5.4.5` (never builds this repo). |
| `node-gyp: ^12.4.0` | All requesters are Yarn-injected `node-gyp:
latest` = 12.4.0 today. The tar-6-era node-gyp versions it evicted have
no requesting parent left. |
| `cacache: ^20.0.0` | All four parents (arborist, metavuln-calculator,
make-fetch-happen 15, pacote 21) already declare `^20`. Guarded by the
kept `make-fetch-happen: ^15` resolution. |
| `pacote/tar: ^7.5.16` | The original target (pacote 11/15 via zapier)
is gone; the only pacote left is 21.5.0 which declares `tar ^7.4.3`
natively. |

## Removed — replaced by a parent upgrade

- **`nodemailer: 8.0.10`** → `imapflow` 1.2.1 → **1.3.6** (ships patched
nodemailer 8.0.10 exact; 1.4.0 is blocked by the 3-day npm age gate).
twenty-server's own `^8.0.5` range was already safe.
- **`node-ical/uuid: 11.1.1`** → `node-ical` ^0.20.1 → **^0.21.0**,
which drops uuid (and axios) entirely. The uuid removal happened at
0.21.0 — not in the 0.26 rrule-temporal type overhaul that #21441
flagged as the blocker.

## Narrowed — `qs: 6.15.2` global → two scoped entries

Only three lockfile entries actually request vulnerable qs ranges:
`express@4.22.0` (pinned by `@mintlify/previewing`), `express@4.22.1` +
`@cypress/request@3.0.10` (pinned by verdaccio 6.7.2, latest). Replaced
the global pin with `express/qs` + `@cypress/request/qs`, so the 12+
healthy parents (express 4.22.2/5.x, body-parser, stripe, …) are no
longer frozen and will pick up future qs releases naturally.

## Re-pinned — `graphql-redis-subscriptions/ioredis`

Changed `^5.6.0` → exact `5.10.1` and documented why: this must equal
the exact ioredis version pinned by twenty-server and bullmq. Without
it, graphql-redis-subscriptions' `^5.3.2` resolves to a second ioredis
copy and `RedisPubSub`'s publisher/subscriber types reject the server's
client (caught by twenty-server typecheck during this work — bump it in
lockstep with the ioredis pin).

## Kept (all load-bearing, now documented inline)

graphql (singleton below msw's `^16.12.0`), @lingui/core (suite
lockstep), @types/qs (6.9.17 typing-break holdback), @opentelemetry/api
(NoopMeterProvider singleton, #20231), chokidar v3 (NestJS CLI fsevents,
#20316), tmp (zapier-platform-cli pins 0.2.5), make-fetch-happen + the
two @electron tar entries (blocked on electron-forge adopting
@electron/rebuild 4), @angular-devkit/core (blocked on a fixed
@nestjs/cli > 11.0.23), yeoman-environment, webpack-dev-server,
next/postcss (fix only in next 16.3.0 canaries), the remaining uuid
pins, and react-doc-viewer/ajv.

## Follow-ups (separate PRs)

- `typeorm` 0.3.20 → 0.3.30: re-roll the 46-line patch; clears the
`typeorm/uuid` resolution **and** the open high-severity
GHSA-q2pj-6v73-8rgj (SQL injection in `repository.save/update`, fixed in
0.3.26).
- googleapis 105 → ≥152 migration clears `googleapis-common/uuid`.

## Verification

- `yarn install` clean; lockfile contains **no** vulnerable qs
(≤6.15.1)/tar 6/uuid <11/nodemailer <8.0.4/postcss 8.4.31/tmp <0.2.6
entries
- `npx nx typecheck twenty-server` ✓ and `npx nx typecheck twenty-front`
✓
- CalDAV + IMAP unit tests (node-ical/imapflow consumers): 9 suites, 121
tests ✓
- `yarn npm audit --all`: only pre-existing typeorm finding remains (see
follow-up)
2026-06-11 13:41:03 +02:00
Charles Bochet
1ccede2309 security: scoped ajv 8.20.0 resolution for react-doc-viewer (Dependabot alert 481) (#21445)
Closes the **final** open Dependabot alert — ajv
[481](https://github.com/twentyhq/twenty/security/dependabot/481) — with
a scoped resolution.

### Why a resolution (no parent path)
`ajv >= 7.0.0 < 8.18.0` is pulled **only** by
`@cyntler/react-doc-viewer`, which pins `ajv ^7.2.4`. Its **latest
(1.17.1) still pins `^7`** — there is no react-doc-viewer version on ajv
8 (no 1.18/2.0) — so it can't be closed by upgrading the parent.

### Why it's completely safe
`@cyntler/react-doc-viewer` **never imports ajv** — zero references in
its dist; ajv is a declared-but-unused dependency. So forcing it to ajv
8 has **no functional impact**, and the ajv 7→8 breaking-change concern
is moot. Scoped to `@cyntler/react-doc-viewer/ajv` so it touches nothing
else.

### Verification
- `yarn install --immutable` ✓; every ajv now resolves to **8.18.0 /
8.20.0** (safe) or `6.12.x` (outside the advisory range) — no vulnerable
ajv remains.

Documented in the top-level `//resolutions` note with a removal trigger.
**This was the last open alert.**
2026-06-11 12:37:45 +02:00
Charles Bochet
462dd3b0e9 security: uuid CVE — bump bullmq/msal/blocknote + scoped resolutions for the rest (Dependabot alert 1289) (#21441)
Closes the uuid Dependabot alert —
[1289](https://github.com/twentyhq/twenty/security/dependabot/1289) — by
**upgrading the parents that bump cleanly** and **scope-resolving only
the ones that genuinely can't**.

`uuid < 11.1.1` (buffer-bounds check in v3/v5/v6) is pulled by ~9
transitives.

### Bumped (parent upgrade — drops uuid<11, no behavior change;
typecheck verified)
- **bullmq** 5.40.0 → 5.78.0 — also aligned **ioredis** 5.6.0 → 5.10.1
(bullmq pins it) and fixed the renamed `Job.returnValue→returnvalue` /
`stackTrace→stacktrace` (now `string[]|null`) in
`admin-panel-queue.service.ts`.
- **@azure/msal-node** ^3.8.4 → ^5.2.3 (5.2.4 was age-gate-quarantined).
- **@blocknote/** ×5 ^0.47.3 → ^0.51.4.

### Scope-resolved to uuid 11.1.1 (no clean bump exists)
- **sockjs** (latest; pinned by webpack-dev-server) and
**@ptc-org/nestjs-query-typeorm** (9.4.0 *is* latest, pins `^10`) — no
version drops uuid.
- **typeorm** — a `patch:` dep / ORM core, too risky to bump.
- **node-ical** 0.26 (type-model overhaul → caldav-parser rewrite) and
**googleapis** 173 (Gmail/OAuth, 105→173) — large breaking migrations;
**deferred to dedicated PRs**.
- **@cypress/request** — transitive (cypress isn't a direct dep).

Resolutions are **per-package** and preserve the intentional **uuid
13.x** (twenty-sdk / create-twenty-app).

### Verification
- `twenty-server` typecheck ✓ (0 errors), `twenty-front` typecheck ✓ (0
errors).
- `yarn install --immutable` ✓; every uuid resolves to **11.1.1** or
**13.0.2**.
- bullmq/msal/typeorm runtime exercised by the **server integration
tests**; @blocknote by the **storybook tests** in CI.
2026-06-11 12:26:26 +02:00
Charles Bochet
6af06c1062 security: postcss CVE via styled-components bump + next/postcss resolution (Dependabot alert 1061) (#21438)
Closes the postcss Dependabot alert —
[1061](https://github.com/twentyhq/twenty/security/dependabot/1061) — by
**bumping one parent** and using a **scoped resolution** only where
there's no other path.

postcss `< 8.5.10` (XSS via unescaped `</style>` in stringify output)
was bundled by two parents:

### styled-components → bumped (no resolution)
`styled-components 6.4.2` (in-range for our `^6.1.0`; we were on a stale
6.3.12) **dropped its postcss dependency entirely**, so a plain `yarn
up` removes the 8.4.49 copy — no override. (styled-components is only
used in one component-renderer Storybook showcase; product UI is on
Linaria.) Re-built `twenty-front-component-renderer` to confirm the
bump.

### next → scoped resolution (no parent path)
`next` pins postcss `8.4.31` **exact on every stable release** —
next@latest (16.2.9) still pins it; the fix (8.5.10) exists only in the
**16.3.0 canary** (unreleased). So `next/postcss: 8.5.15` is the only
mechanism, scoped to next and documented in the top-level
`//resolutions` note with a removal trigger.

### Verification
- Every postcss now resolves `>= 8.5.14` (safe); `yarn install
--immutable` ✓.
- postcss is build-time and **CI doesn't build twenty-website on regular
PRs**, so verified locally: **twenty-website** (Next production build) ✓
and **twenty-front-component-renderer** ✓.
2026-06-11 11:19:50 +02:00
Raphaël Bosi
6756ea628d Add People Data Labs enrichment logic functions (#21254)
## Add People Data Labs enrichment logic functions

Implements the **enrichment logic functions** that call the PDL API and
map responses onto standard + `pdl*` fields.

- **Logic functions** — shared core powers bulk workflow actions
(`enrich-person` / `enrich-company`) and single-record AI tools. Each
guards a TTL, matches via identifier, fills standard fields only when
empty, always writes `pdl*` fields, and normalizes SELECT values against
field options.
- **Data model** — PDL employer now links via the **standard `company`
relation** (find-or-create, fill-only-if-empty); removed the dedicated
`pdlCurrentCompany` relation, six `pdlJobCompany*` scalars, and the
`pdl*` indexes.

**Not functional yet:** the post-install workflow seeding
(`seed-enrichment-workflow.ts`) is left in place but blocked — it needs
workflow-builder mutations that the CRUD-only app SDK schema doesn't
expose.

**Deferred:** metering/billing and auto-enrichment triggers.



https://github.com/user-attachments/assets/a570a484-ae79-4c57-a274-e068fdab78e4



https://github.com/user-attachments/assets/6edfb5e1-cada-4892-87e0-b485eb359692
2026-06-11 09:06:20 +00:00
github-actions[bot]
28ab160b48 i18n - website translations (#21439)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-06-11 11:02:43 +02:00
Raphaël Bosi
d596c26f46 Migrate twenty UI (#21407)
## Migrate all `twenty-ui-deprecated` components into `twenty-ui`

Ports all **192 components** and **70 stories** into the new `twenty-ui`
package with full public-API parity (export diff: 0 missing / 0 extra
across all 13 modules; story titles byte-identical for the Argos
cross-package diff).

- **Styling:** Linaria → SCSS Modules, `var(--t-*)` tokens, `data-*`
state. Canonical pattern in `Button.module.scss`.
- **Behavior:** Base UI where mapped (Checkbox, Radio, Modal→Dialog,
Tooltip drops `react-tooltip`, JSON tree→Collapsible); framer kept only
where animation is the public contract.
- **Fixed an inert axe gate** in `.storybook/vitest.setup.ts` (a11y
addon annotations were never registered). Now live; 119 stories carry
`a11y: 'todo'` overrides pending a fix pass.
2026-06-11 11:02:28 +02:00
Abdullah.
c05c34aaec [Website] Convert remaining images to WebP and compress some current ones. (#21404)
As title. Also deleted some unused assets that are no longer required.
2026-06-11 08:47:44 +00:00
Charles Bochet
2da28cb03e security: upgrade express 4.22.2 + qs 6.15.2 resolution for dev-tool holdouts (Dependabot alert 1305) (#21434)
Closes the qs Dependabot alert —
[1305](https://github.com/twentyhq/twenty/security/dependabot/1305) — by
**upgrading express where possible** and using a **documented qs
resolution** only for the irreducible dev-only holdouts.

### What's vulnerable
`qs 6.14.x` (the `qs.stringify` DoS) is pulled by `express 4.22.1` /
`body-parser 1.x`. The fix is `qs 6.15.2`, and there's **no backport to
the 6.14 line**.

### Upgrade what we can (no resolution)
`express 4.22.2` / `body-parser 1.20.5` moved to the patched `qs
~6.15.1`. So this PR bumps the app + in-range tooling to **express
4.22.2**:
- twenty-server's stale direct pin `4.22.1 → 4.22.2` (its runtime HTTP
is already express 5.2.1 via `@nestjs/platform-express`; this just
patches the redundant direct dep — typecheck passes),
- nx / electron-forge / webpack-dev-server / companion follow via `yarn
up -R express body-parser`.

### Resolution only for the two holdouts
Two **dev-only** tools pin express *exactly* with no patched release on
a line we can use, so they still drag in `qs 6.14.2`:
- **verdaccio** `4.22.1` — express 5 only landed in the **v7 beta**
([verdaccio#5680](https://github.com/verdaccio/verdaccio/issues/5680),
[#2479](https://github.com/verdaccio/verdaccio/issues/2479)), **not**
backported to the 6.x line we use.
- **@mintlify/previewing** `4.22.0` — closed-source, latest still pins
4.22.0, no movement.

A `qs: 6.15.2` resolution covers those, documented with a top-level
`//resolutions` note and a removal trigger.

### Verification
- `yarn install --immutable` ✓; every `qs` resolves to `6.15.2`; express
app/tooling on `4.22.2` (only verdaccio/mintlify remain on old express,
neutralized by the resolution).
- `twenty-server` typecheck ✓ (90 files import express types;
4.22.1→4.22.2 is a patch).
- Non-exploitable in prod regardless (express/body-parser use
`qs.parse`, not the vulnerable `stringify`).
2026-06-11 10:46:04 +02:00
machinagod
233a6f9fb1 fix(server): register Lingui message compiler to stop "Uncompiled message detected" log flood (#21416)
## Summary

Fixes #21415.

Server-side `` t`…` `` macro calls (e.g. `FlatEntityMapsException`)
resolve against Lingui's global `i18n` singleton, which `I18nService`
never loads a catalog into and never registers a messages compiler on.
With no `_messageCompiler` set, every such lookup logs `Uncompiled
message detected!` and falls back to the raw string — flooding server
logs (enough to hit hosting log rate limits) and disabling ICU
interpolation on those messages. The warning is emitted unconditionally
by `@lingui/core` (not `NODE_ENV`-gated).

## Changes

Register `compileMessage` via `setMessagesCompiler` in
`I18nService.loadTranslations()`:
- on the global `i18n` singleton (used by the `t` macro), and
- on each per-locale instance.

`@lingui/message-utils` is already a transitive **runtime** dependency
of `@lingui/core` (`@lingui/core@5.1.2 → @lingui/message-utils@^5.1.2`),
so no new dependency is added.

## Testing

Deployed on a real instance: before, the server emitted hundreds of
`Uncompiled message detected` lines/sec (saturating the log rate limit);
after, steady-state shows `0`, and the worker (which shares the code
path) likewise shows `0`. App behaviour is unchanged — messages already
rendered via fallback; this silences the warning and enables ICU on the
affected messages.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2026-06-11 10:05:24 +02:00
nitin
20c83e1f86 fix(kanban): preserve scroll on board re-init + propagate same-column reorders via SSE (#20637)
closes
https://discord.com/channels/1130383047699738754/1504130730840821860


https://github.com/user-attachments/assets/d5833031-01c6-4e46-b699-c29c42435a53





## Summary

Fixes two related issues with the kanban (board view) collaboration
experience:

1. **Scroll-to-top on every data change** —
`triggerRecordBoardInitialQuery` always scrolled the board to the top,
even when re-initializing for a single-record data change (SSE echo of
your own mutation, a collaborator's update). Scroll reset only makes
sense when the dataset itself changes (filter / sort / group).
2. **Same-column reorders by other users did not propagate** — the
server's diff function stripped `FieldMetadataType.POSITION`, so
position-only updates produced empty `updatedFields` and short-circuited
event emission entirely. SSE clients never received them.

## What's in here

- **Frontend** — `useTriggerRecordBoardInitialQuery` now exposes a
`triggerRecordBoardInitialQueryWithoutScrollReset` variant; data-driven
re-inits in `RecordBoardDataChangedEffect` use it, while genuine filter
/ sort / group changes keep the scroll-resetting
`triggerRecordBoardInitialQuery`. `getRecordBoardEffectsForUpdateInputs`
classifies each update as `trigger-initial-query` / `reposition-records`
/ `none`. For position- or group-only changes we skip the re-query and
reposition records in place in the store
(`useRepositionRecordsOnBoard`), which avoids the flicker and preserves
scroll.
- **Server** — removes `POSITION` from `objectRecordChangedValues`'
strip list, so position-only updates emit a non-empty diff and flow
through SSE. Position is now treated as a field like any other across
all event consumers (SSE, webhooks, workflows, logic functions); a
trigger with an explicit field filter still excludes it.
2026-06-11 07:26:51 +00:00
Charles Bochet
9100fb1e9f security: scoped resolution for webpack-dev-server 5.2.4 (Dependabot alerts 1237/691/692) (#21420)
Closes 3 webpack-dev-server Dependabot alerts —
[1237](https://github.com/twentyhq/twenty/security/dependabot/1237),
[691](https://github.com/twentyhq/twenty/security/dependabot/691),
[692](https://github.com/twentyhq/twenty/security/dependabot/692) — with
a **scoped** resolution:
`@electron-forge/plugin-webpack/webpack-dev-server: 5.2.4`.

(These numbers are Dependabot **alert** IDs, not issue/PR numbers —
written without `#` to avoid cross-linking unrelated issues, per review
feedback.)

### Why a resolution (the one place it's unavoidable)
webpack-dev-server is pulled **only** by
`@electron-forge/plugin-webpack` (twenty-companion's build tooling), and
**no electron-forge release uses webpack-dev-server 5** — not even
`8.0.0-alpha.9` still pins `^4`. There is no parent-upgrade path, so a
resolution is the only mechanism.

### Scoped, not global
Per review feedback, the resolution targets
`@electron-forge/plugin-webpack/webpack-dev-server` rather than a global
override — it only forces v5 under electron-forge (the sole consumer),
limiting blast radius. Verified the scoped syntax is honored: removing
it reverts the lockfile to `webpack-dev-server@npm:^4.0.0`; with it, the
lock pins `webpack-dev-server@npm:5.2.4` and `yarn install --immutable`
passes.

### Why it's safe (constructor did NOT change v4→v5)
`@electron-forge/plugin-webpack@7` calls `new
WebpackDevServer(this.devServerOptions(), compiler)`.
webpack-dev-server's constructor is `constructor(options, compiler)` in
**both v4 and v5** (verified in `lib/Server.js:331` and
`types/lib/Server.d.ts:1179`). The `(compiler, options)` → `(options,
compiler)` swap happened at **v3 → v4**, not v4 → v5. The plugin passes
only options unchanged in v5 (`hot`, `devMiddleware.writeToDisk`,
`historyApiFallback`, `port`, `setupExitSignals`, `static`, `headers`)
and uses none of the hooks v5 removed.

### Scope / verification
- `yarn install --immutable` ✓; webpack-dev-server resolves to 5.2.4
only (was 4.15.2), no vulnerable copy remains.
- Only exercised by `electron-forge start` (dev HMR); production
`make`/`package` builds don't use it, and **twenty-companion has no CI
workflow**, so this can't affect CI.
- Residual manual check (not CI-covered): `yarn start:electron` in
twenty-companion still boots the dev server.
2026-06-11 09:38:16 +02:00
Félix Malfait
9d7f0c405f fix(twenty-front): new layout fast-follows — command menu, field options & logs (#21429)
Fast-follows for the new layout — the remaining open sub-issues of
twentyhq/core-team-issues#2478.

## Changes

- **Command menu items should not have extra right padding**
(twentyhq/core-team-issues#2500)
`SidePanelList` set `width: calc(100% - spacing[4])` on top of its own
8px left/right padding. Under the global `box-sizing: border-box`, that
extra `-16px` shrinks the list and, because it's left-aligned, dumps the
whole gap on the right. Switched to `width: 100%` so item highlights
inset 8px symmetrically. This is shared by every side-panel list — they
all had the same right-only gutter, so they're all corrected the same
way.

- **Field options should not be cropped and should keep row gaps**
(twentyhq/core-team-issues#2503)
The option row used a fixed `height: spacing[6]`, so under border-box
the `6px` vertical padding was absorbed and consecutive rows sat flush.
Changed `height` → `min-height` so the padding separates the rows again.

- **Logs table with filters should use Background secondary**
(twentyhq/core-team-issues#2505)
The Logs filter card and the upgrade card defaulted to a transparent
background, showing the white page through. Passed
`backgroundColor={themeCssVariables.background.secondary}`, matching
`SettingsTableCard`. The results table stays on the primary surface, per
the Figma reference.

- **Command menu back chevron** (twentyhq/core-team-issues#2504)
`SidePanelTopBar` showed a back chevron whenever the nav stack had more
than one entry. A command-menu page is the root of a fresh command-menu
session, so it now only shows the chevron when it was opened from
another command-menu page. Every other side-panel page keeps standard
history-based back navigation, so workflow / page-layout / record stacks
are unaffected.

## Verification
- oxlint (`--type-aware`, full `src/`): 0 errors
- oxfmt: clean
- tsgo typecheck: no errors in the changed files (the one reported error
is pre-existing in `RestPlayground.tsx`, which this PR does not touch)
- Verified live at apple.localhost:
- #2500 — command menu item highlight insets measured 8px left / 8px
right (was 8 / 24)
- #2503 — option rows render at 38px tall with ~14px gaps, text no
longer cropped
- #2505 — filter + upgrade cards compute to background-secondary;
results table stays on primary
- #2504 — direct command menu shows the close-X with no chevron; pages
opened from the command menu still show the chevron

## Open question for review (#2504)
The issue also describes the page-header three-dots toggle: *"the three
dots icon button should remain visible if the side panel is on a page
that is not a child of the command menu (AI chat, or a page opened
directly)."* Today that toggle morphs to an X for any non-command-menu
side-panel page (e.g. Ask AI). Honoring that touches the shared
`SidePanelToggleButton`, and there's a related decision: search / Ask AI
opened from the command menu currently reset the nav stack rather than
push, so they don't get a "back to command menu" chevron. I left those
out here since they're a behavior change to a shared control with a
product call attached — happy to follow up once you confirm the intended
toggle behavior.

Closes twentyhq/core-team-issues#2500
Closes twentyhq/core-team-issues#2503
Closes twentyhq/core-team-issues#2505
Refs twentyhq/core-team-issues#2504
Refs twentyhq/core-team-issues#2478
2026-06-11 08:58:23 +02:00
dependabot[bot]
f55a45f4e0 chore(deps-dev): bump storybook from 10.2.13 to 10.4.3 (#21428)
Bumps
[storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/core)
from 10.2.13 to 10.4.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/releases">storybook's
releases</a>.</em></p>
<blockquote>
<h2>v10.4.3</h2>
<h2>10.4.3</h2>
<ul>
<li>Addon Docs: Fix Primary and Controls blocks not rendering in custom
MDX pages - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34496">#34496</a>,
thanks <a
href="https://github.com/NYCU-Chung"><code>@​NYCU-Chung</code></a>!</li>
<li>Core: Respect !dev tag on MDX docs in sidebar - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35031">#35031</a>,
thanks <a
href="https://github.com/JReinhold"><code>@​JReinhold</code></a>!</li>
<li>React: Add support for resolving subcomponents attached as
properties of a parent component - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34967">#34967</a>,
thanks <a
href="https://github.com/yatishgoel"><code>@​yatishgoel</code></a>!</li>
<li>UI: Prevent docs page scroll reset on HMR re-render - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35021">#35021</a>,
thanks <a
href="https://github.com/LongTangGithub"><code>@​LongTangGithub</code></a>!</li>
</ul>
<h2>v10.4.2</h2>
<h2>10.4.2</h2>
<ul>
<li>Bug: Fix Windows command resolution for non-Node package managers -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/33534">#33534</a>,
thanks <a
href="https://github.com/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!</li>
<li>Build: Upgrade type-fest to latest version 5.6.0 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34791">#34791</a>,
thanks <a
href="https://github.com/tobiasdiez"><code>@​tobiasdiez</code></a>!</li>
<li>CSF: Fix parsing of string literal export names - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34901">#34901</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Publish: Add npm provenance attestations - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34936">#34936</a>,
thanks <a
href="https://github.com/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!</li>
</ul>
<h2>v10.4.1</h2>
<h2>10.4.1</h2>
<ul>
<li>Angular: Detect model() signal outputs (type inference + compodoc
autodocs + runtime binding) - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34833">#34833</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Build: Upgrade type-fest to latest version 5.6.0 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34791">#34791</a>,
thanks <a
href="https://github.com/tobiasdiez"><code>@​tobiasdiez</code></a>!</li>
<li>CLI: Run `npx expo install --fix` after init for Expo projects - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34803">#34803</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>CLI: Support `peerDependencies` in framework detection for component
libraries - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34516">#34516</a>,
thanks <a
href="https://github.com/zhyd1997"><code>@​zhyd1997</code></a>!</li>
<li>Next.js: Add useLinkStatus mock to next/link export mock - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34593">#34593</a>,
thanks <a
href="https://github.com/philwolstenholme"><code>@​philwolstenholme</code></a>!</li>
<li>Vue3: Specify a specific version for non-dev dependency - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34794">#34794</a>,
thanks <a
href="https://github.com/ScopeyNZ"><code>@​ScopeyNZ</code></a>!</li>
</ul>
<h2>v10.4.0</h2>
<h2>10.4.0</h2>
<blockquote>
<p><em>AI-assisted setup, change-aware review, and stronger framework
support</em></p>
</blockquote>
<p>Storybook 10.4 contains hundreds of fixes and improvements
including:</p>
<ul>
<li>🤖 Agentic Setup: New CLI workflow for AI-assisted Storybook setup
and onboarding</li>
<li>🔍 Change review: Sidebar filtering to highlight new, modified, and
related stories based on git changes</li>
<li>🧭 Sidebar review tools: Status filtering, URL-persisted filters, and
clearer review signals in the sidebar</li>
<li>⚛️ TanStack React: New `@storybook/tanstack-react` framework with
routing and server function support</li>
<li>🧩 React MCP: Faster, more accurate component docgen powered by the
TypeScript Language Server</li>
<li>📱 React Native: Zero config RN project initialization</li>
<li>🤝 Sharing: Easily publish and share your local Storybook with
teammates, powered by Chromatic</li>
</ul>
<!-- raw HTML omitted -->
<ul>
<li>A11y: Add aria-live announcements via
<code>@​react-aria/live-announcer</code> - <a
href="https://redirect.github.com/storybookjs/storybook/pull/33970">#33970</a>,
thanks <a
href="https://github.com/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!</li>
<li>A11y: Improve boolean control contrast in forced colors mode - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34204">#34204</a>,
thanks <a
href="https://github.com/anchmelev"><code>@​anchmelev</code></a>!</li>
<li>Actions: Fix state mutation and keep newest actions when limit
reached - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34286">#34286</a>,
thanks <a
href="https://github.com/Sidnioulz"><code>@​Sidnioulz</code></a>!</li>
<li>Addon-Docs: Add Reset story button to re-render stories in docs - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34086">#34086</a>,
thanks <a
href="https://github.com/6810779s"><code>@​6810779s</code></a>!</li>
<li>Addon-Docs: Avoid rerendering static Source blocks - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34206">#34206</a>,
thanks <a
href="https://github.com/anchmelev"><code>@​anchmelev</code></a>!</li>
<li>Addon-Vitest: Use Vitest's provide-API for injecting values - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34518">#34518</a>,
thanks <a
href="https://github.com/JReinhold"><code>@​JReinhold</code></a>!</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md">storybook's
changelog</a>.</em></p>
<blockquote>
<h2>10.4.3</h2>
<ul>
<li>Addon Docs: Fix Primary and Controls blocks not rendering in custom
MDX pages - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34496">#34496</a>,
thanks <a
href="https://github.com/NYCU-Chung"><code>@​NYCU-Chung</code></a>!</li>
<li>Core: Respect !dev tag on MDX docs in sidebar - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35031">#35031</a>,
thanks <a
href="https://github.com/JReinhold"><code>@​JReinhold</code></a>!</li>
<li>React: Add support for resolving subcomponents attached as
properties of a parent component - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34967">#34967</a>,
thanks <a
href="https://github.com/yatishgoel"><code>@​yatishgoel</code></a>!</li>
<li>UI: Prevent docs page scroll reset on HMR re-render - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35021">#35021</a>,
thanks <a
href="https://github.com/LongTangGithub"><code>@​LongTangGithub</code></a>!</li>
</ul>
<h2>10.4.2</h2>
<ul>
<li>Bug: Fix Windows command resolution for non-Node package managers -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/33534">#33534</a>,
thanks <a
href="https://github.com/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!</li>
<li>Build: Upgrade type-fest to latest version 5.6.0 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34791">#34791</a>,
thanks <a
href="https://github.com/tobiasdiez"><code>@​tobiasdiez</code></a>!</li>
<li>CSF: Fix parsing of string literal export names - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34901">#34901</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Publish: Add npm provenance attestations - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34936">#34936</a>,
thanks <a
href="https://github.com/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!</li>
</ul>
<h2>10.4.1</h2>
<ul>
<li>Angular: Detect model() signal outputs (type inference + compodoc
autodocs + runtime binding) - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34833">#34833</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Build: Upgrade type-fest to latest version 5.6.0 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34791">#34791</a>,
thanks <a
href="https://github.com/tobiasdiez"><code>@​tobiasdiez</code></a>!</li>
<li>CLI: Run <code>npx expo install --fix</code> after init for Expo
projects - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34803">#34803</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>CLI: Support <code>peerDependencies</code> in framework detection
for component libraries - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34516">#34516</a>,
thanks <a
href="https://github.com/zhyd1997"><code>@​zhyd1997</code></a>!</li>
<li>Next.js: Add useLinkStatus mock to next/link export mock - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34593">#34593</a>,
thanks <a
href="https://github.com/philwolstenholme"><code>@​philwolstenholme</code></a>!</li>
<li>Vue3: Specify a specific version for non-dev dependency - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34794">#34794</a>,
thanks <a
href="https://github.com/ScopeyNZ"><code>@​ScopeyNZ</code></a>!</li>
</ul>
<h2>10.4.0</h2>
<blockquote>
<p><em>AI-assisted setup, change-aware review, and stronger framework
support</em></p>
</blockquote>
<p>Storybook 10.4 contains hundreds of fixes and improvements
including:</p>
<ul>
<li>🤖 Agentic Setup: New CLI workflow for AI-assisted Storybook setup
and onboarding</li>
<li>🔍 Change review: Sidebar filtering to highlight new, modified, and
related stories based on git changes</li>
<li>🧭 Sidebar review tools: Status filtering, URL-persisted filters, and
clearer review signals in the sidebar</li>
<li>⚛️ TanStack React: New <code>@storybook/tanstack-react</code>
framework with routing and server function support</li>
<li>🧩 React MCP: Faster, more accurate component docgen powered by the
TypeScript Language Server</li>
<li>📱 React Native: Zero config RN project initialization</li>
<li>🤝 Sharing: Easily publish and share your local Storybook with
teammates, powered by Chromatic</li>
</ul>
<!-- raw HTML omitted -->
<ul>
<li>A11y: Add aria-live announcements via
<code>@​react-aria/live-announcer</code> - <a
href="https://redirect.github.com/storybookjs/storybook/pull/33970">#33970</a>,
thanks <a
href="https://github.com/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!</li>
<li>A11y: Improve boolean control contrast in forced colors mode - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34204">#34204</a>,
thanks <a
href="https://github.com/anchmelev"><code>@​anchmelev</code></a>!</li>
<li>Actions: Fix state mutation and keep newest actions when limit
reached - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34286">#34286</a>,
thanks <a
href="https://github.com/Sidnioulz"><code>@​Sidnioulz</code></a>!</li>
<li>Addon-Docs: Add Reset story button to re-render stories in docs - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34086">#34086</a>,
thanks <a
href="https://github.com/6810779s"><code>@​6810779s</code></a>!</li>
<li>Addon-Docs: Avoid rerendering static Source blocks - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34206">#34206</a>,
thanks <a
href="https://github.com/anchmelev"><code>@​anchmelev</code></a>!</li>
<li>Addon-Vitest: Use Vitest's provide-API for injecting values - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34518">#34518</a>,
thanks <a
href="https://github.com/JReinhold"><code>@​JReinhold</code></a>!</li>
<li>Agentic Setup: Add --extensive for an extra prompt - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34730">#34730</a>,
thanks <a
href="https://github.com/Sidnioulz"><code>@​Sidnioulz</code></a>!</li>
<li>Agentic Setup: Allow failed stories to persist - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34717">#34717</a>,
thanks <a
href="https://github.com/Sidnioulz"><code>@​Sidnioulz</code></a>!</li>
<li>Agentic Setup: Keep sample content if users want onboarding - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34704">#34704</a>,
thanks <a
href="https://github.com/Sidnioulz"><code>@​Sidnioulz</code></a>!</li>
<li>Agentic Setup: Rework ai-init-opt-in logic - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34739">#34739</a>,
thanks <a
href="https://github.com/Sidnioulz"><code>@​Sidnioulz</code></a>!</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="624e6187fd"><code>624e618</code></a>
Bump version from &quot;10.4.2&quot; to &quot;10.4.3&quot; [skip
ci]</li>
<li><a
href="c898822822"><code>c898822</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/34496">#34496</a>
from NYCU-Chung/fix/docs-blocks-custom-mdx</li>
<li><a
href="c920fd08c7"><code>c920fd0</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/35021">#35021</a>
from LongTangGithub/fix/docs-hmr-scroll-to-top</li>
<li><a
href="1750494e9f"><code>1750494</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/35031">#35031</a>
from storybookjs/jeppe/fix-mdx-no-dev-tag</li>
<li><a
href="298dea20c6"><code>298dea2</code></a>
Bump version from &quot;10.4.1&quot; to &quot;10.4.2&quot; [skip
ci]</li>
<li><a
href="40c81c8187"><code>40c81c8</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/33534">#33534</a>
from storybookjs/copilot/fix-pnpm-command-resolutio...</li>
<li><a
href="bfb942b532"><code>bfb942b</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/34901">#34901</a>
from storybookjs/shilman/fix-csf-export-as-string-l...</li>
<li><a
href="fad8dd2b63"><code>fad8dd2</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/34791">#34791</a>
from tobiasdiez/type-fest-upgrade</li>
<li><a
href="cc19ae1a21"><code>cc19ae1</code></a>
Bump version from &quot;10.4.0&quot; to &quot;10.4.1&quot; [skip
ci]</li>
<li><a
href="f8c16d115c"><code>f8c16d1</code></a>
Bump version from &quot;10.4.0-beta.0&quot; to &quot;10.4.0&quot; [skip
ci]</li>
<li>Additional commits viewable in <a
href="https://github.com/storybookjs/storybook/commits/v10.4.3/code/core">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=storybook&package-manager=npm_and_yarn&previous-version=10.2.13&new-version=10.4.3)](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>
2026-06-11 07:34:34 +02:00
dependabot[bot]
dac36b83ce chore(deps-dev): bump @types/aws-lambda from 8.10.161 to 8.10.162 (#21427)
Bumps
[@types/aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/aws-lambda)
from 8.10.161 to 8.10.162.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/aws-lambda">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/aws-lambda&package-manager=npm_and_yarn&previous-version=8.10.161&new-version=8.10.162)](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>
2026-06-11 07:29:44 +02:00
dependabot[bot]
f8b0dca3f9 chore(deps): bump @tabler/icons-react from 3.31.0 to 3.44.0 (#21426)
Bumps
[@tabler/icons-react](https://github.com/tabler/tabler-icons/tree/HEAD/packages/icons-react)
from 3.31.0 to 3.44.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tabler/tabler-icons/releases">@​tabler/icons-react's
releases</a>.</em></p>
<blockquote>
<h2>Release 3.44.0</h2>
<!-- raw HTML omitted -->
<h3>18 new icons:</h3>
<ul>
<li><code>outline/code-ai</code></li>
<li><code>outline/email-stamp</code></li>
<li><code>outline/foodsteps</code></li>
<li><code>outline/git-pull-request-conflict</code></li>
<li><code>outline/noise-reduction</code></li>
<li><code>outline/photo-alt</code></li>
<li><code>outline/pointer-2</code></li>
<li><code>outline/pointer-collaboration-2</code></li>
<li><code>outline/pointer-collaboration</code></li>
<li><code>outline/roulette</code></li>
<li><code>outline/scan-cube</code></li>
<li><code>outline/sketching</code></li>
<li><code>outline/sparkle-2</code></li>
<li><code>outline/sparkle-highlight</code></li>
<li><code>outline/sparkle</code></li>
<li><code>outline/sphere-2</code></li>
<li><code>outline/text-scan-ai</code></li>
<li><code>outline/vignette</code></li>
</ul>
<p>Fixed icons: <code>outline/air-balloon</code>,
<code>outline/body-scan</code>, <code>outline/chart-sankey</code>,
<code>outline/ear-scan</code>, <code>outline/grid-scan</code>,
<code>outline/line-scan</code>, <code>outline/object-scan</code>,
<code>outline/photo-scan</code>, <code>outline/route-scan</code>,
<code>outline/scan-eye</code>, <code>outline/scan-letter-a</code>,
<code>outline/scan-letter-t</code>, <code>outline/scan-position</code>,
<code>outline/scan-traces</code>, <code>outline/scan</code>,
<code>outline/text-scan-2</code>, <code>outline/user-scan</code>,
<code>outline/zoom-scan</code></p>
<h2>Release 3.43.0</h2>
<!-- raw HTML omitted -->
<h3>18 new icons:</h3>
<ul>
<li><code>outline/acorn</code></li>
<li><code>outline/acrobatic</code></li>
<li><code>outline/banana</code></li>
<li><code>outline/brand-audible</code></li>
<li><code>outline/building-eiffel-tower</code></li>
<li><code>outline/car-door</code></li>
<li><code>outline/car-lifter</code></li>
<li><code>outline/chocolate</code></li>
<li><code>outline/dumbbell</code></li>
<li><code>outline/exercise-ball</code></li>
<li><code>outline/flood</code></li>
<li><code>outline/hula-hoop</code></li>
<li><code>outline/leaf-maple</code></li>
<li><code>outline/notdef</code></li>
<li><code>outline/rugby</code></li>
<li><code>outline/taiwan-dollar</code></li>
<li><code>outline/target-2</code></li>
<li><code>outline/unicycle</code></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="6d128ed935"><code>6d128ed</code></a>
Release 3.44.0</li>
<li><a
href="e40738b644"><code>e40738b</code></a>
Release 3.43.0</li>
<li><a
href="076f4a9e4d"><code>076f4a9</code></a>
Release 3.42.0</li>
<li><a
href="9b27b65e3d"><code>9b27b65</code></a>
Release 3.41.1</li>
<li><a
href="ebad60b50a"><code>ebad60b</code></a>
Update homepage links in documentation and package files to point to the
new ...</li>
<li><a
href="8ed617b1b7"><code>8ed617b</code></a>
Update README files to wrap images in anchor tags linking to the Tabler
Icons...</li>
<li><a
href="ef6e875bbe"><code>ef6e875</code></a>
Update dependencies in pnpm-lock.yaml and package.json files (<a
href="https://github.com/tabler/tabler-icons/tree/HEAD/packages/icons-react/issues/1497">#1497</a>)</li>
<li><a
href="6cbe8857c8"><code>6cbe885</code></a>
Release 3.41.0</li>
<li><a
href="19d735e620"><code>19d735e</code></a>
Add JSDoc with previews in icons-react (<a
href="https://github.com/tabler/tabler-icons/tree/HEAD/packages/icons-react/issues/1472">#1472</a>)</li>
<li><a
href="e4ca37707b"><code>e4ca377</code></a>
Release 3.40.0</li>
<li>Additional commits viewable in <a
href="https://github.com/tabler/tabler-icons/commits/v3.44.0/packages/icons-react">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@tabler/icons-react&package-manager=npm_and_yarn&previous-version=3.31.0&new-version=3.44.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>
2026-06-11 07:29:32 +02:00
Joseph Chiang
941c9e7586 fix: match relation field filters in optimistic & RLS record matchers (#21301)
Closes #21345.

## What

It should be caused by the GraphQL optimistic query.

`isRecordMatchingFilter` (front, Apollo optimistic cache) and
`isRecordMatchingRLSRowLevelPermissionPredicate` (server, RLS) now
handle a view filter that targets a **relation field object** (e.g. an
"is (not) empty" filter on a relation) by matching against the related
record id, instead of throwing.


<img width="3436" height="2250" alt="CleanShot 2026-06-08 at 06 44
01@2x"
src="https://github.com/user-attachments/assets/1dccbd1e-133c-4f4a-a0a9-7ccd02a9a0ae"
/>

<img width="1496" height="380" alt="CleanShot 2026-06-08 at 06 45 34@2x"
src="https://github.com/user-attachments/assets/e5c2071e-69df-4d99-bb7d-66d503a175b6"
/>


## Why

Both matchers only implemented the relation **join column** branch
(`fooId`) and threw `Not implemented yet, use UUID filter instead on the
corresponding "fooId" field` for the relation field itself (`foo`). In
practice the UI still stores relation filters keyed on the relation
object, so any view with such a filter made every create/update/delete
on that object throw: the optimistic effect re-evaluates all active view
filters against the changed record and hits the unimplemented branch.

Repro: add a self-relation field on People (e.g. "Referred By"), put it
in a view filter as "is not empty", then edit any Person. The optimistic
update throws.

## Behaviour change

| Scenario | Before | After |
|---|---|---|
| View filter on relation object (`referredBy is not empty`), then edit
a record | Throws `Not implemented yet...` | Record matched by related
id; update succeeds |
| Filter on relation join column (`referredById`) | Worked | Unchanged |

## Test plan

```bash
cd packages/twenty-front && npx jest isRecordMatchingFilter
cd packages/twenty-server && npx jest is-record-matching-rls-row-level-permission-predicate
```

- [x] Front: relation `is empty` / `is not empty` / `in` match by
related id; join-column path still passes (20/20)
- [x] Server: relation `is empty` / `is not empty` match by related id
(9/9)
- [x] `lint:diff-with-main` clean on both packages

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-06-11 07:29:10 +02:00
Gami
61b76b681e fix: i18n missing hardcoded strings in settings (#21424)
## What

Two user-visible strings in the Settings area were never wrapped with
Lingui, so they were excluded from i18n extraction and shipped
untranslated regardless of the selected language:

- **"Remote"** — the type chip shown for remote objects in **Settings →
Data Model** (`SettingsItemTypeTag`)
- **"Done"** — the confirm button of the fields configuration group
rename input (`FieldsConfigurationGroupRenameInput`)

## Changes

- Wrap the `Chip` `label` with the `t` macro in
`SettingsItemTypeTag.tsx` (the `placeholder` / `placeholderColorSeed`
props are intentionally left as-is — they drive the avatar initial and
color hash, not display text).
- Wrap the `Button` `title` with the existing `t` from `useLingui()` in
`FieldsConfigurationGroupRenameInput.tsx`.
- Add the corresponding source entries to `en.po` so Crowdin can
propagate the translations to all supported locales.

Both follow i18n patterns already used throughout the codebase — these
two were simply missed.

## Screenshots

Both components rendered via Storybook (source `en` locale) after the
change — the strings now resolve through Lingui's `t` macro without
breaking rendering:

![i18n settings
strings](https://raw.githubusercontent.com/AmilGael/twenty/pr-assets/.github/pr-assets/i18n-hardcoded-strings-settings.png)

## How to test

1. Switch the workspace language to a non-English locale.
2. Go to **Settings → Data Model** with a remote object present → the
type chip reads "Remote" translated.
3. Rename a fields configuration group → the confirm button reads "Done"
translated.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 04:38:58 +00:00
Charles Bochet
615c3d8dbe security: drop end-of-life apollo-server-core (#735, #736) (#21418)
Closes the `apollo-server-core` alerts (**#735**, **#736**) by
**removing the dependency** — no Apollo migration, no resolution.

### Why these were flagged "no patch available"
`apollo-server-core` is **Apollo Server v3, which is end-of-life** (per
its npm deprecation notice). No patched release of this package will
ever exist — the CVE fix lives only in the renamed `@apollo/server` v4
package.

### Why we can just drop it
twenty-server **doesn't use Apollo Server** — its GraphQL runtime is
**GraphQL Yoga** (`YogaDriver`). `apollo-server-core` was imported for
one thing only: the `gql` template tag in **6 integration test files**.
`gql` from `graphql-tag` is identical (apollo-server-core merely
re-exports it), `graphql-tag` is **already a direct dependency**, and
**15 other twenty-server tests already import `gql` from it**.

### Change
- Swapped `import { gql } from 'apollo-server-core'` → `import { gql }
from 'graphql-tag'` in the 6 test files.
- Removed `apollo-server-core` from
`packages/twenty-server/package.json`.
- Result: `apollo-server-core` (and its transitive surface) is gone from
`yarn.lock` entirely.

### Verification
- `yarn install --immutable` ✓
- No `apollo-server-core` references remain in source or lockfile
- Integration tests (which exercise the swapped `gql` imports) run in CI
2026-06-10 19:08:07 +02:00