Commit Graph

191 Commits

Author SHA1 Message Date
Félix Malfait adf6eb572b feat(billing): embed Stripe Payment Element in onboarding (#21759)
## What & why

Replaces the hosted Stripe Checkout redirect on the onboarding "Choose
your plan" step (credit-card trial) with an inline Stripe **Payment
Element**, so users never leave the app to enter card details.

## How it works

- **Frontend:** a deferred `<Elements mode="setup">` renders the Payment
Element, themed via the Appearance API. On Continue: `elements.submit()`
→ `checkoutSession` mutation creates the trialing subscription
server-side and returns its pending SetupIntent `clientSecret` →
`stripe.confirmSetup()` confirms the card (handling 3DS) → redirect to
the existing `/plan-required/payment-success`.
- **Backend:** new `BILLING_STRIPE_PUBLISHABLE_KEY` config var exposed
via `/client-config`; the card path creates the subscription with
`payment_behavior: default_incomplete` + a free trial (so Stripe
attaches a `pending_setup_intent`) and returns its client secret. The
hosted-Checkout code path is removed.
- The **no-credit-card** trial path is unchanged.
- Billing address collection is **disabled** in the Payment Element to
reduce friction; `automatic_tax` is correspondingly disabled (tax needs
an address — collect it later, e.g. at conversion / via the billing
portal).

## Required before this works
1. Set `BILLING_STRIPE_PUBLISHABLE_KEY` (`pk_…`) on the server (infra
change pending).
2. Run `nx run twenty-front:graphql:generate --configuration=metadata`
against a server exposing the updated schema (see inline note on the
hand-authored document).
3. Verify in Stripe test mode: happy path, 3DS (`4000 0025 0000 3155`),
a decline.

## Verified
typecheck (front + server), oxlint + oxfmt clean,
`client-config.service.spec` passing. Not run here: the app end-to-end /
Stripe test mode and `graphql:generate` (no server/DB in the dev
container).

I've left self-review comments inline flagging cleanup opportunities
plus a couple of architectural/tech-debt items.

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

https://claude.ai/code/session_01TxCfinXq7abSrbF7aTw2cA

---
_Generated by [Claude
Code](https://claude.ai/code/session_01TxCfinXq7abSrbF7aTw2cA)_

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21759?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: Claude <noreply@anthropic.com>
2026-06-19 11:40:55 +02:00
Raphaël Bosi 9c9c34fccf Remove twenty-ui-deprecated and migrate frontend to twenty-ui (#21596)
Migrates `twenty-front`, `twenty-sdk`, and
`twenty-front-component-renderer` from `twenty-ui-deprecated` to
`twenty-ui` (mechanical import swap — the packages have API parity) and
deletes the deprecated package along with its workspace/CI/config
wiring.

Also adds `@linaria/react`/`@linaria/core` as direct deps of
`twenty-front` (it used them transitively via the deprecated package).

Note: move the required status check from `ci-ui-status-check` to
`ci-new-ui-status-check`.

Argos: the Storybook box-model/button-reset baseline shift (the bulk of
the visual diffs) is isolated in #21665 — Storybook now loads
twenty-ui's global `reset.scss`, which the production app already ships.
Once #21665 merges and this branch is rebased, the remaining Argos diffs
are component-level visual-parity items only.
2026-06-17 09:41:11 +00:00
Charles Bochet 9dd097e11e fix(front): set up Monaco workers for GraphQL playground (#21620)
## Problem

The GraphQL API playground (`/settings/playground/graphql/core`) crashes
with:

```
Uncaught Error: Cannot read properties of undefined (reading 'toUrl')
  at FileAccessImpl.toUri (monaco-editor)
  at WorkerManager.getLanguageServiceWorker (graphqlMode)
  at DiagnosticsAdapter._doValidate (graphqlMode)
```

## Root cause

GraphiQL 5 (adopted in the React 19 migration, #21531) renders its
editors with **Monaco** instead of CodeMirror. Monaco spawns web workers
for GraphQL validation/autocomplete and needs a
`globalThis.MonacoEnvironment.getWorker` factory. None was ever
configured, so Monaco fell back to a main-thread worker whose URL
resolves to `undefined` → the `toUrl` crash.

## Why not the official helper

GraphiQL ships `@graphiql/react/setup-workers/vite`, but its bundled
`?worker` imports are incompatible with our rolldown-based Vite setup:
- **pre-bundled** (in `optimizeDeps`): esbuild's optimizer can't process
`?worker` → the dep 504s and the page fails to load the chunk.
- **excluded** from `optimizeDeps`: rolldown tries to load
`editor.worker.js?worker` as a literal path → `UNLOADABLE_DEPENDENCY`,
crashing the dev server.

## Fix

- Register `MonacoEnvironment.getWorker` in **app source**
(`setupGraphiqlMonacoWorkers.ts`), where Vite's worker plugin handles
`?worker` reliably, and side-effect import it from
`GraphQLPlayground.tsx` before GraphiQL mounts.
- Align `monaco-editor` to `0.52.2` and add `monaco-graphql@1.8.0` as
direct deps so the workers run on the **same deduped Monaco instance**
GraphiQL uses on the main thread (a version mismatch would break the
worker protocol).

## Verification

Ran the playground locally against the dev server:
- Editor renders, syntax highlighting works, operation name parses
(GraphQL language service alive).
- All three worker files (`editor`, `json`, `graphql`) load `200` and
instantiate as module workers.
- Console is free of `toUrl` / `Cannot read` errors and the "must define
MonacoEnvironment.getWorker" warning.
- `oxlint`, `oxfmt`, and `nx typecheck twenty-front` pass.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21620?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-15 17:51:51 +02:00
Charles Bochet 88b9294afd feat(front): persist metadata store cache in IndexedDB instead of localStorage (#21586)
## Problem

The metadata store cache (object/field metadata, views, page layouts,
command menu items, …) is persisted client-side to power **cache-first
boot**: the app renders instantly from the cache, then
`MinimalMetadataLoadEffect` revalidates per-collection hashes and only
refetches what's stale.

It was persisted to **localStorage**, which Safari/WebKit caps at **~5
MB per origin, counted in UTF-16 (2 bytes/char)** → an effective ceiling
of ~2.5 M characters. Measured on the seeded demo workspace (33 objects,
612 fields):

| Bucket | Safari quota (UTF-16) |
|---|---|
| `metadataStoreState__*` (26 keys) | **1.9 MB — 37%** |
| Whole origin | **2.47 MB — 48%** |

A workspace ~2.5× the demo's schema blows past 5 MB, and there is **no
`QuotaExceededError` handling** — `setItem` throws and breaks the app.
This is what large-workspace users on Safari have been hitting.

## Fix

Move **only the metadata store** to **IndexedDB** (multi-GB, disk-based
quota), keeping a **fully synchronous read path** so the ~24 consumers
that read these atoms with `useAtomValue` never suspend. The auth/UI
atoms (incl. the synchronously-read `tokenPair`) stay on localStorage —
intentionally scoped.

- **`createIndexedDbBackedJotaiStorage.ts`** — a synchronous Jotai
storage facade backed by an in-memory map, hydrated once from IndexedDB
at boot and written through on every set. IndexedDB access uses the
**`idb-keyval`** library (by the IndexedDB spec co-author, ~0.6 KB)
rather than a hand-rolled wrapper. Each cache gets its own database +
BroadcastChannel (`twenty-front-<cacheName>`), so it's safely reusable.
Swallowed errors are surfaced via `logError`. When IndexedDB is
unavailable the cache stays in memory only (re-fetched each boot).
- **`createAtomFamilyState`** — gains an optional `storage` param;
`metadataStoreState` uses the IndexedDB-backed storage.
- **`index.tsx`** — awaits hydration before mounting so atoms
(`getOnInit: true`) read the persisted snapshot synchronously →
cache-first boot preserved.
- **No migration**: the facade does not touch localStorage at all.
Pre-existing localStorage snapshots are ignored — on first boot of the
new code the IndexedDB cache is empty and atoms re-fetch from the
network (a one-time reconnect). Old `metadataStoreState__*` localStorage
keys are left in place (cleared by the existing logout/reset cleanup);
new writes only ever go to IndexedDB.
- **Cross-tab sync**: the old localStorage atoms synced across tabs for
free via `storage` events; the IndexedDB facade had no equivalent, so a
schema change in one tab left others stale until reload. Restored by
implementing the Jotai storage `subscribe` contract over a
**`BroadcastChannel`** — writes broadcast to other tabs, which update
their in-memory map and notify `atomWithStorage` subscribers so mounted
atoms re-render live. (BroadcastChannel doesn't echo to the sender, so
no feedback loop; guarded for environments without it.)

## Why a synchronous facade (not async `atomWithStorage`)

Consumers use `useAtomValue` directly; an async storage would make the
atoms resolve to Promises and **suspend** every reader. The in-memory
facade keeps reads synchronous (zero ripple on consumers) and confines
the async part to a single bulk read at boot, which the existing
`MinimalMetadataGater` loader already covers.

## Tests

### Automated
- Unit test (10 cases) for the storage facade: synchronous read/write,
IndexedDB write-through, hydration from IndexedDB, `removeItem`/`clear`,
per-cache DB namespacing, persist-failure logging, in-memory-only
behaviour when IndexedDB is unavailable, distinguishing a stored
`undefined` from a missing key, and cross-tab subscriber registration.
- Existing metadata-store tests (`useIsLayoutCustomizationDirty`,
`useDefaultHomePagePath`) still pass.
- `nx typecheck twenty-front` and `nx lint:diff-with-main twenty-front`
clean.

### Manual (local seeded workspace, two tabs, Playwright)
Storage:
- After login the metadata cache lives in **IndexedDB (24 keys, ~945
KB)** and **localStorage drops 48% → 11%** of the Safari quota (the
remainder is `currentUserState` + auth, out of scope).
- Reload boots from the cache (no heavy refetch).

Scenarios:

| Scenario | Result |
|---|---|
| **Sign out** | auth cleared, redirect to sign-in, no leftover
localStorage, no errors |
| **Sign back in** | metadata `up-to-date`, company table renders, token
restored |
| **Add object** (`Gadget`) | write-through to IndexedDB; survives
reload via cache-first hydration |
| **Add view** (`QA Cross Tab View`, TABLE) | persisted to the `views`
collection (`up-to-date`) |
| **Two tabs open** | second tab boots cleanly from the shared IndexedDB
— no lock/crash under concurrent access |
| **Cross-tab live sync** | creating an object in tab A makes it appear
in tab B's open settings object list **without a reload** |

Verified by design (no regression):
- Runtime sign-out (`clearSession`) clears session keys and does a full
`window.location.assign` reload; the metadata-clearing path
(`resetJotaiStore`) is test-only, so there's no
async-`clear()`-vs-sign-in race. Metadata persisting across sign-out is
unchanged from the old localStorage behavior (it's schema, revalidated
by hash on next login).

## Notes / follow-ups (not in this PR)

- **IndexedDB query capabilities** are not used yet: the cache stores
one blob per collection (as it did in localStorage), so this is still a
pure key-value use (`idb-keyval`). If we later want to query individual
metadata records — e.g. fields by `objectMetadataId` via an
index/cursor, or partial hydration — that means record-level storage and
a richer wrapper (`idb` for a thin near-native layer, or **Dexie** for a
full query API + reactive `liveQuery` that could also replace the
BroadcastChannel sync).
- IndexedDB still has a (large) quota and Safari ITP eviction applies to
both stores — the cache-first design already tolerates eviction by
revalidating.
- Complementary "load less" wins remain: the denormalized per-field
`relation` block (~700 chars/field of pure duplication) and persisting
`currentUser.workspaceMembers` (the ~0.5 MB still in localStorage).

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21586?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-15 13:25:53 +00:00
Charles Bochet fb4608e437 chore(deps): upgrade Tier-1 deps (googleapis 173, gaxios 7, express 5, jsdom 29, date-fns 4, stripe 20) (#21570)
## What

Security-driven upgrade of the biggest-drift Tier-1 dependencies
(staying on latest = staying patched). Bundled because they share the
lockfile and the googleapis/gaxios pair must move together.

| Package | From | To | Gap |
|---|---|---|---|
| googleapis | 105.0.0 | **173.0.0** | 68 majors |
| gaxios | 5.1.3 | **7.1.5** | 2 majors |
| express | 4.22.2 | **5.2.1** | 1 major |
| jsdom | 26.1.0 | **29.1.1** | 3 majors |
| date-fns | 2.30.0 | **4.4.0** | 2 majors |
| date-fns-tz | 2.0.0 | **3.2.0** | 1 major |
| stripe | 19.3.1 | **20.4.1** | 1 major |

`yarn npm audit` reports **0 high/critical** advisories before and
after.

## Code changes

- **gaxios v7** — `GaxiosError.code` is now `string | number` (guard the
calendar network-error check by `typeof`); `GaxiosError` config/response
use `URL` + `Headers`; and crucially the v7 constructor drops
`response.data` unless `bodyUsed` is set — updated the synthetic gmail
error mocks accordingly (production gaxios sets it, so real error
parsing is unaffected).
- **google-auth-library / gaxios dedup** — `googleapis-common@8.0.2`
exact-pins `google-auth-library@10.5.0` + `gaxios@7.1.3` while
`googleapis` pulls `^10.2.0`; the two copies made
`OAuth2Client`/`GaxiosError` type-identities diverge across every
gmail/calendar service. Added two singleton `resolutions` (documented
inline in root `package.json`).
- **express 5** — no source changes. `@nestjs/platform-express@11.1.24`
already resolves `express@5.2.1` internally; the old `4.22.2` pin was
the override.
- **jsdom 29** — no source changes, but it now pulls ESM-only transitive
deps (`@csstools/*` `.mjs`, `parse5`, `entities`, `tough-cookie`,
`@exodus/bytes`). Extended the server jest `transformIgnorePatterns`
allowlist and added `.mjs` to the transform/extensions so jest can load
jsdom.
- **stripe 20** — `Subscription` gained a required `customer_account`
field; added to mocks. No runtime changes.
- **date-fns v4** — `Locale` is no longer ambient (import explicitly in
5 files); per-locale entrypoints dropped the typed `default` export (the
locale loader now reads the single named export); fixed the default
locale import in `formatTimeZoneLabel`.

## Tests

- Full suites green locally: **twenty-server 5709 passed**,
**twenty-front 4937 passed**, twenty-ui / twenty-ui-deprecated green;
typecheck + builds (swc + vite) + lint all pass.
- Added regression tests for the two runtime behaviors these upgrades
touch and that had no coverage:
  - `getDateFnsLocale` — named-export locale resolution (date-fns v4).
- `sanitizeFile` — jsdom 29 + DOMPurify still strips `<script>`/event
handlers from uploaded SVGs (security guard).

## Deliberately deferred (not in this PR)

- **stripe → 21/22**: stripe **21** bundles a runtime `Decimal` type for
money fields **and** jumps the pinned API version to `2026-03-25.dahlia`
(changes webhook/billing payload behavior) — too risky to fold into a
deps bump on billing code. stripe **22** additionally drops the
node10-resolvable `types` entry, which would force a repo-wide
`moduleResolution` change. Capped at the latest clean **20.x**.
- **openid-client → 6**: v6 is a full functional rewrite and its
passport strategy manages the OAuth `state` internally, but our SSO flow
uses `state` to carry `identityProviderId` across the shared
`/auth/oidc/callback`. That needs an auth-flow redesign (session-carried
provider id) on Enterprise SSO code with no integration harness — it
deserves its own focused PR rather than riding along here.

## Tier-1 source

Originated from a dependency-drift audit; remaining Tier-1 items
(date-fns done here) plus Tier-2/3 follow-ups tracked separately.


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21570?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-15 10:23:42 +02:00
Charles Bochet 7c0136b97b feat(deps): migrate frontend to React 19 (#21531)
## What

Migrates the frontend stack from **React 18.3 → 19.2**. The website,
sdk, companion and emails packages were already on React 19; this brings
the remaining holdouts (`twenty-front`, `twenty-ui`,
`twenty-ui-deprecated`, `twenty-front-component-renderer`) and
`twenty-server`'s email rendering onto 19, and pins a single React
version repo-wide.

## Why

React 18.x is now the legacy line. Staying current keeps us on the
patched/maintained branch and unblocks downstream library majors
(react-router 7, mantine 9, etc.) that require React 19 peers.

## Dependency bumps (required by React 19 peers / removed APIs)

| Package | From | To | Reason |
|---|---|---|---|
| react / react-dom | 18.3.1 | 19.2.3 | core |
| @hello-pangea/dnd | 16 | 18 | peer `^18 \|\| ^19` |
| react-datepicker | 6 | 9 | v<7 used removed `findDOMNode`; drops
`@types/react-datepicker` |
| react-data-grid | beta.13 | beta.59 | peer `^19.2`; new render API |
| graphiql (+ @graphiql/react, plugin-explorer) | 3 / 0.23 / 1 | 5 /
0.37 / 5.1 | peer `^18 \|\| ^19` |
| react-helmet-async | 1.3 | **@dr.pogodin/react-helmet** 3.2 | upstream
caps peer at `^18`; drop-in React 19 fork |

A `resolutions` pin enforces a single React (19.2.3) + `@types/react`
(19.2.14) across the monorepo to avoid duplicate copies / type-identity
splits. Versions are the aged lockfile patches (clears the
`npmMinimalAgeGate`).

## Code changes

- **Global `JSX` shim** (`react-jsx-global.d.ts` per package): React 19
moved the `JSX` namespace under `React.JSX`; several deps' published
types (notably `@linaria/react`'s `styled.d.ts`, which types every
`styled.x` via `keyof JSX.IntrinsicElements`) still reference the global
namespace. Without the shim, every styled component degrades to `any`
props.
- **Ref nullability**: `useRef<T>(null)` now returns `RefObject<T |
null>`; widened consumer prop/hook ref types accordingly (incl. the
shared `useListenClickOutside`).
- **react-datepicker v9**: `onChange`/`onSelect` accept `Date | null`,
`calendarStartDay` typing, `ReactDatePickerProps`→`DatePickerProps`,
relaxed the dynamic `selectsMultiple` discriminated union.
- **react-data-grid beta.59**: `formatter`→`renderCell`,
`editor`→`renderEditCell`, `headerRenderer`→`renderHeaderCell`,
`components`→`renderers`, `onRowClick`→`onCellClick`, object-shaped
`useRowSelection`, Set-based selection.
- **dnd style cast**: `@radix-ui/react-popper` augments `CSSProperties`
with a `--radix-*` index signature that dnd's closed `DraggingStyle`
doesn't satisfy → cast at the spread.

## Status / testing

-  `typecheck` green: twenty-front, twenty-ui, twenty-ui-deprecated,
twenty-front-component-renderer, twenty-server
-  build / lint / unit tests / storybook+argos / runtime smoke-test in
progress

Draft until local + CI verification completes. Notable behavior to QA
manually: spreadsheet import (data-grid), date pickers, drag-and-drop
boards/lists, GraphQL playground, page titles/favicon.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21531?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-14 15:42:22 +02:00
Charles Bochet 869680a5a1 fix(deps): esbuild ^0.28.1 floors + vite 7→8 (rolldown) upgrade (#21517)
## What this does

Resolves the remaining esbuild security alerts on packages we own, and
upgrades the repo to **Vite 8** (which drops esbuild entirely in favour
of rolldown/oxc).

### 1. esbuild → `^0.28.1` (security)
- Raised the declared `esbuild` floor in `twenty-sdk` and the
logic-function common-layer (both were `^0.25.0`, which can only resolve
to a vulnerable version). These are our packages, so this is just
declaring the patched version — clears Dependabot **#1467** and
**#1468**.

### 2. Vite 7 → 8
- Bumped `vite` to `^8` in the 5 packages that declare it, and
`@vitejs/plugin-react-swc` to `^4.3.1` (the only plugin that needed a
bump for Vite 8; everything else already supports it).
- `twenty-front` keeps esbuild minification, so esbuild is now an
explicit (patched) devDependency there — Vite 8 no longer ships it.

### Two Vite-8 fallout fixes (bundler internals changed)
- **Storybook tests:** added React to `optimizeDeps.include` so Vite's
dep optimizer doesn't re-bundle React mid-run and break in-flight
imports in browser-mode tests.
- **`hex-rgb`:** it's ESM-only and broke rolldown's CJS interop (a
default import resolved to the wrong thing under jest). Replaced its one
use with a tiny inline hex→rgb parse and dropped the dependency.

## Verified
Vite resolves to a single `8.0.16` with no esbuild in its tree. Builds
pass on Vite 8/rolldown: `twenty-front` production build, the SDKs, and
Storybook; the previously-failing front and storybook test jobs now
pass; `yarn install --immutable` is clean.

## Note
This doesn't close root alert **#1469** — esbuild is still pulled by
other third-party tools (storybook, tsx, lingui, zapier, etc.) that
haven't shipped a patched release. The vulnerable code path (esbuild's
dev server) isn't used here, so that one is best dismissed as
not-affected.
2026-06-13 10:44:22 +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
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
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 868cb02e45 security: close lodash CVEs (#824/#823/#385) via parent upgrades, no resolution (#21414)
Closes the remaining lodash Dependabot alerts **without any
`resolutions` override** — by upgrading the parent packages that pinned
the vulnerable lodash. Every `lodash` in the tree now resolves to
**4.18.1**.

### Closes
- **#824 — `_.template` code injection (HIGH)**
- #823 / #385 — prototype pollution in `_.unset` / `_.omit`

### What changed (4 parents pinned vulnerable lodash 4.17.x; all
upgraded, no override)
- **`@stoplight/spectral-functions`** → 1.10.2 (in-range; now uses
`lodash ^4.18.1`)
- **`zapier-platform-core`** 15.5.1 → 19.0.0 — aligns with the
already-present `zapier-platform-cli ^19` (they were mismatched). v19
tightened the `Bundle` types, so 3 call sites now type their bundle as
`Bundle<InputData>` and the test bundle includes the new `meta` fields.
- **`@graphql-codegen`** → `cli 6.3.1`, `typescript 5.0.10`,
`typescript-operations 5.1.0`, `typed-document-node 6.1.8`. These depend
on `@graphql-codegen/plugin-helpers ^6.3.0`, the release that dropped
lodash. (Stayed on the 6.x/5.x line on purpose — 7.x changes generated
output far more.)

### About the generated-file changes — they are cosmetic, not real
changes
The codegen bump touches one generated file. **Verified there is zero
semantic change:**

- Only `src/generated-metadata/graphql.ts` changes.
`src/generated/graphql.ts` (data) and `src/generated-admin/graphql.ts`
(admin) are **byte-identical**.
- Same 1,638 type declarations before and after — none added, none
removed.
- After stripping whitespace and union pipes, the file is
**byte-for-byte identical** — no type, field, or union member changed.

The entire diff is one formatting change from
`typescript-operations@5.x`: multi-member union types are now printed
multi-line with a leading `|` instead of on one line — which TypeScript
treats identically:
```ts
// before
payload?: { …ObjectMetadata… } | { …Path… } | null
// after
payload?:
    | { …ObjectMetadata… }
    | { …Path… }
   | null
```
Only metadata is affected because only its operations select GraphQL
union types. To keep generated types otherwise behavior-identical,
`defaultScalarType: 'any'` was added to the three codegen configs
(codegen 6 would otherwise default unmapped scalars to `unknown`).

### Verification
- `twenty-front` typecheck ✓, `twenty-zapier` typecheck ✓
- `yarn install --immutable` ✓ (passes the hardened 3-day age gate)
- CI green — including the `graphql:generate` freshness check, which
regenerates against the canonical schema and confirms the committed
output is exactly what codegen produces
- No `lodash@4.17.x` remains anywhere in `yarn.lock`

Supersedes #21411 (which closed these via a one-line resolution).
2026-06-10 18:12:46 +02:00
Charles Bochet 232ca8eec2 security: clear happy-dom High alerts by upgrading wyw-in-js 0.7 → 1.1 (#21394)
## What

Clears the 2 High `happy-dom` alerts (GHSA-w4gp-fjgq-3q4g,
GHSA-6q6h-j7hj-3r64) via a parent bump — **no resolution**.

`happy-dom@15.11.7` came from **`@wyw-in-js/transform@0.7.0`**
(Linaria's CSS transform), pinned by a root resolution + a local `.yarn`
patch and requested by `@wyw-in-js/vite@^0.7.0` in twenty-front +
twenty-ui-deprecated.

- `@wyw-in-js/vite` `^0.7.0` → `^1.1.0` (twenty-front,
twenty-ui-deprecated)
- `@wyw-in-js/babel-preset` `^0.6.0` → `^1.1.0` (twenty-ui-deprecated)
- **drop the `@wyw-in-js/transform` 0.7.0 resolutions + the `.yarn`
patch** — the patch added a `visited` cycle-guard to
`TransformCacheCollection.invalidateIfChanged`, which is **already
upstream** in transform 1.1.0, so it's obsolete.

`@wyw-in-js/transform` now resolves to **1.1.0** (→ happy-dom 20.10.2)
and 0.8.1 (website, unchanged, → happy-dom 20.8.9). The vulnerable
0.7.0/15.11.7 are gone.

## Required config change

wyw-in-js 1.x resolves modules in its CSS pre-build via vite's
`resolve.alias` instead of `vite-tsconfig-paths`. So twenty-front's `@/`
and `~/` tsconfig path aliases are mirrored into `vite.config`
`resolve.alias` — otherwise the CSS evaluator throws `Cannot find module
'@/...'` for aliased imports used inside `styled` definitions.

## Verification
- happy-dom now **20.8.9 + 20.10.2** (both patched); no 15.x left
- `nx build twenty-front` — CSS extraction works (**1018 files
transformed**) + `typecheck`
- `nx build twenty-ui`, `twenty-ui-deprecated` (Linaria CSS extraction)
- website's Linaria transform runs fine (local build only stops on a
missing `TWENTY_PARTNERS_API_URL` env var, unrelated)
- `yarn install --immutable` clean
2026-06-10 11:24:38 +02:00
Charles Bochet 217e1f5ab3 security: clear immutable High alert via @graphql-codegen typescript plugins v4 (#21380)
## What

Clears the High `immutable` alert (GHSA-wf6x-7x77-mvgw) via a parent
bump — **no resolution**.

`immutable@3.7.6` was pulled by `@ardatan/relay-compiler@12.0.0` (→
`immutable ~3.7.6`), reached through
`@graphql-tools/relay-operation-optimizer` inside the `@graphql-codegen`
visitor plugins. The fix lives in `relay-operation-optimizer@7.1.4` →
`relay-compiler@13.0.1` → `immutable@^5.1.5` — but the old codegen
typescript plugins (v3) pinned a 6.x optimizer stuck on relay-compiler
12.

**Fix chain:**
- `@graphql-codegen/typescript` `^3.0.4` → `^4.1.6`
- `@graphql-codegen/typescript-operations` `^3.0.4` → `^4.6.1`
- refresh `@graphql-tools/relay-operation-optimizer` (within its
existing `^7.0.0` range) → 7.1.4 → `relay-compiler@13.0.1` →
`immutable@5.1.6`

## Heads-up: this is effectively a codegen v4 plugin upgrade

The codegen typescript plugins v4 change the generated **scalar shape**
(`Scalars['X']` → `Scalars['X']['input'|'output']`), so the committed
`generated*/graphql.ts` are regenerated (~7.8k lines). The diff is
**purely type-level** — no runtime/enum/document changes — and was
regenerated against the current schema (verified: **no schema-content
drift**).

## Verification

- `immutable@3.7.6` gone (now 5.1.6); `relay-compiler@13.0.1`
- `nx typecheck twenty-front` passes against the regenerated types (0
errors)
- `yarn install --immutable` clean
- Generated files regenerated against a clean origin/main schema (no
drift markers)
2026-06-10 10:37:00 +02:00
Abdullah. ca63904ac5 fix(security): bump @scalar/api-reference-react to clear unhead XSS (#21382)
Resolves [Dependabot Alert
630](https://github.com/twentyhq/twenty/security/dependabot/630).

unhead@1.11.20 was pulled in transitively via
@scalar/api-reference-react@0.4.42 (@unhead/vue@^1.11.11). The
useHeadSafe XSS bypass (GHSA, alert
https://github.com/twentyhq/twenty/issues/630) is only patched on the
unhead 2.x line; the 1.x branch was never fixed and 1.11.20 is the
latest 1.x release, so the existing semver range could not reach a
patched version. Rather than a resolutions override, bump the direct
dependency to a Scalar release that depends on @unhead/vue@^2.x, which
resolves unhead to 2.1.15.

- Upgrade @scalar/api-reference-react ^0.4.36 -> ^0.9.42 (0.9.43+
blocked by the 3-day npmMinimalAgeGate; the caret adopts them once
aged).
- Migrate RestPlayground configuration to the new Scalar API:
  - spec.content -> top-level content
- authentication.http.bearer ->
authentication.securitySchemes.bearerAuth (with
preferredSecurityScheme), matching the server's OpenAPI scheme name.
- Drop the ?inline query on the style.css import. It was added in
https://github.com/twentyhq/twenty/pull/12099 to stop the old Scalar's
global CSS reset from leaking; the new CSS scopes every reset to
:where(.scalar-app), so importing it normally restores styling without
re-introducing that leak.

Proof:
<img width="215" height="48" alt="image"
src="https://github.com/user-attachments/assets/3a738fae-63bd-4e88-82c3-5dbe72d993ec"
/>

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-06-10 07:33:13 +02:00
Charles Bochet 0d8d463a44 security: clear all High minimatch Dependabot alerts via parent bumps (#21373)
## What

Clears **all 14 High `minimatch` ReDoS alerts** (GHSA-7r86-cg39-jmmj,
GHSA-23c5-xmqv-rm74, GHSA-3ppc-4f35-3m26) in the root tree — **by
bumping the actual parent dev tools, with no `resolutions`/overrides**.
Each parent that pinned a vulnerable minimatch is upgraded so the
patched version resolves naturally.

| Vulnerable minimatch | Pinned by | Fix |
|---|---|---|
| 10.0.3 | `@microsoft/api-extractor` 7.55.1 | → 7.58.7 (in-range
refresh) → minimatch 10.2.3 |
| 3.1.2 | `@stoplight/spectral-core` 1.20.0 | → 1.23.0 (in-range
refresh) → minimatch ^3.1.4 |
| 3.0.8 | `vite-plugin-dts` 3.8.1 → api-extractor 7.43.0 | bump to
`^4.5.4` (already used elsewhere here) → minimatch 10.2.3 |
| 4.2.3 | `graphql-config` 4.5.0 via `@graphql-codegen/cli` ^3.3.1 |
bump cli to `^5.0.7` → graphql-config 5.1.6 → minimatch ^10 |
| 9.0.3 | `zapier-platform-cli` ^15.4.1 | bump to `^19.0.0` |
| 7.4.6 | `verdaccio` 6.5.2 → `@verdaccio/core` 8.0.0-next | refresh to
6.7.2 → core 8.1.1 → minimatch 7.4.9 |

All six are **build/test tooling** — the ReDoS exposure is build-time,
never shipped to users.

## Verification

-  Every resolved `minimatch` in `yarn.lock` is now ≥ its patched floor
(3.1.5 / 7.4.9 / 9.0.9 / 10.2.3+). No `resolutions` added.
-  `nx build`: twenty-shared, twenty-ui, twenty-ui-deprecated,
twenty-emails (validates vite-plugin-dts v4)
-  twenty-zapier: typecheck + build + `zapier validate` (35/35 checks
pass; cli 19 + core 15.5.1)
-  twenty-front: typecheck; `graphql:generate` with codegen cli 5
produces **byte-identical** output (no generated-file changes in this
PR)
-  `yarn install --immutable` clean

## Notes

- The large `yarn.lock` diff is expected: major bumps to codegen (3→5),
zapier-cli (15→19), and vite-plugin-dts (3→4) cascade through dev-tree
transitives (net −1244 lines after dedup).
- `zapier-platform-core` (runtime) intentionally left at 15.5.1 — only
the CLI (dev tool) carried the vulnerable minimatch; `zapier validate`
flags only a non-blocking "consider upgrading core" suggestion.
- codegen plugins (`typescript`/`typescript-operations`) left at v3:
they run fine under cli 5 and produce identical output, so the minimal
change is just the cli bump.
2026-06-09 18:08:14 +02:00
Raphaël Bosi c596a5e342 Rename twenty-ui to twenty-ui-deprecated and twenty-new-ui to twenty-ui to prepare package release (#21315)
## Description

Promotes the next-gen UI library (formerly `twenty-new-ui`) to the name
**`twenty-ui`** (v0.1.0, publishable) and renames the old package to
**`twenty-ui-deprecated`**. Rewrites ~1,730 `twenty-ui` imports →
`twenty-ui-deprecated`, updates all configs/CI/Docker/deps, and migrates
twenty-front's `Toggle` to the new package (first consumer) as a
drop-in.

## Next steps
- Wire the `ui/v*` publish dispatch (`cd-deploy-tag.yaml` +
`.yarnrc.yml`), then tag `ui/v0.1.0` to publish.
- Continue migrating components from `twenty-ui-deprecated` →
`twenty-ui`.
2026-06-08 18:12:28 +02:00
Charles Bochet 13e8e26d1c security: bump uuid 9 → 11 (server, shared, front) (#21326)
Clears the `uuid` "missing buffer bounds check in v3/v5/v6" advisory —
patched in **11.1.1**. Bumps `twenty-server`, `twenty-shared`,
`twenty-front` from 9 → `^11.1.1`.

### Why 11 and not 13
uuid **11.1.x still ships a CommonJS build**, so jest loads it with **no
config changes**. uuid went **ESM-only at v12+**, which would otherwise
force `transformIgnorePatterns` workarounds across the jest projects
(and broke server/integration/storybook CI on the earlier 13 attempt).
11.1.1 is the actual patched version, so this is the minimal fix.

### Changes
- `uuid` → `^11.1.1` in the three workspaces (lockfile regenerated under
hardened mode)
- one test (`useCreateManyRecords.test.tsx`): pin the mocked `v4` to its
string-returning overload — uuid's types declare a `Uint8Array` overload
that `jest.mocked` resolves to (present in v11 too, unrelated to ESM).

All usages are named imports, so no source migration. typecheck passes
(server/shared/front); affected specs pass. **No jest config changes.**
2026-06-08 17:42:19 +02:00
Charles Bochet d2e7dc0e74 security: bump vulnerable direct dependencies (axios, next, vitest, qs, dompurify, …) (#21309)
## What

Within-major version bumps of **direct** dependencies to clear a large
batch of Dependabot alerts that are breaching (or near) their SLA. No
major-version changes — all stay within the current major, so risk is
low.

| Package | From → To | Clears |
|---|---|---|
| `axios` | ^1.13.5 → ^1.16.0 | ReDoS, Proxy-Auth leak, proto-pollution
gadgets, NO_PROXY bypass, resource DoS (56 alerts) |
| `next` | 16.1.7 → ^16.2.6 | DoS, middleware/proxy bypass, SSRF, cache
poisoning, XSS (32 alerts) |
| `vitest` | 4.0.18 → ^4.1.0 | **CRITICAL** — UI server arbitrary file
read/exec (#1421) |
| `qs` | ^6.11.2 → ^6.15.2 | `qs.stringify` DoS |
| `dompurify` | 3.3.3 → ^3.4.0 | proto-pollution XSS + FORBID_TAGS /
SAFE_FOR_TEMPLATES bypasses |
| `@nestjs/core` | 11.1.16 → ^11.1.18 | improper output neutralization /
injection |
| `nodemailer` | 8.0.4 → 8.0.10 | SMTP command injection via CRLF
(bumped via root `resolutions`) |
| `path-to-regexp` | ^8.2.0 → ^8.4.0 | ReDoS via multiple wildcards |
| `file-type` | ^21.3.1 → ^21.3.2 | ZIP decompression-bomb DoS |
| `@opentelemetry/exporter-prometheus` | ^0.211.0 → ^0.217.0 | exporter
process crash via malformed HTTP request (#1183/#1184) |

## Notes
- Added a `next` root **resolution** so the dev-only
`@react-email/preview-server` copy (hard-pinned at `16.0.10`) is also
pulled up to the patched `16.2.x` line — otherwise that copy keeps the
Next.js alerts open.
- `@opentelemetry/exporter-prometheus` 0.217 pulled
`@opentelemetry/sdk-metrics` to 2.7.1 (compatible); `@opentelemetry/api`
stays pinned at 1.9.1.
- **Transitive-only** vulnerable packages (undici, tmp, ws,
brace-expansion, …) are handled in a **separate PR** per the
split-by-group plan.
- Breaking major bumps (electron, uuid, serialize-javascript) and
migrations (Apollo Server 3→4, simplemde) are intentionally **out of
scope** here.
2026-06-08 12:49:31 +00:00
Charles Bochet f4da7767f8 chore: remove Chromatic dependencies and configuration (#21221)
## Summary

- Remove `chromatic` and `@chromatic-com/storybook` devDependencies from
twenty-front
- Remove global `chromatic` Nx target from nx.json and twenty-front
project.json override
- Remove commented Chromatic Storybook addon from twenty-front
- Remove `CHROMATIC_PROJECT_TOKEN` from .env.example
- Update README to remove Chromatic sponsor reference (image was already
missing)
- Update stale Chromatic comment in toSpliced.ts

## Context

Visual regression testing has moved from Chromatic SaaS to self-hosted
Argos at `argos.twenty-internal.com`. These are dead references that are
no longer used by any CI workflow.

**Note:** Story `parameters.chromatic: { disableSnapshot: true }`
entries are intentionally kept — the Argos plugin reads them as a
fallback.

## Test plan

- Verify `yarn install` succeeds after dependency removal
- Verify no workflow references `chromatic` or `nx chromatic`
2026-06-04 13:15:23 +00:00
Paul Rastoin 6ad6fcce0f Bump playwright (#21113)
Playwright installation is infinite looping in the ci
seems like to be a global outage
2026-06-01 18:06:55 +02:00
Paul Rastoin 41ad63a8ab [DockerFile] Optimize twenty-server deps and build (#20132)
# Introduction

Aiming for faster cd process

## Splitting front end server deps
Reduce dependencies bloating when target is server only, installing only
root repo dev deps and server dev and prod deps

Still pruning before copying to prod node_modules

## Server only remove twenty-ui

Also removing twenty-ui from server build as it was not consumed at all

Depends on https://github.com/twentyhq/twenty/pull/20140
2026-05-04 14:24:52 +00:00
Charles Bochet 3c7c62c79f fix(server): deduplicate @opentelemetry/api to fix NoopMeterProvider (#20231)
## Summary

**All OTel metrics in twenty-server have been silently dropped since
April 30.**

### Root cause

PR #20149 (`bump @sentry/profiling-node 10.27→10.51`) pulled in
`@sentry/node@10.51.0`, which declares `@opentelemetry/api: ^1.9.1` as a
**dependency** (not peer). Yarn installed it as a **nested** copy at
`1.9.1`, while the hoisted copy stayed at `1.9.0`.

At startup in `instrument.ts`:
1. `Sentry.init()` uses the **nested `1.9.1`** to register `trace`,
`propagation`, `context` on the OTel global → global version becomes
**`1.9.1`**
2. `setGlobalMeterProvider()` uses the **hoisted `1.9.0`** →
`registerGlobal` sees version mismatch (`1.9.1` ≠ `1.9.0`) → **silently
returns `false`**
3. Global stays `NoopMeterProvider` → every counter, gauge, and
histogram in the server is a no-op

### What this PR does

1. **Reverts three troubleshooting PRs** that are no longer needed now
that the root cause is identified:
   - #20230 — heartbeat gauge
   - #20228 — OTLP export lifecycle logs
- #20221 — Sentry revert to 10.27 (which never actually downgraded in
`yarn.lock` since `^10.27.0` resolved to `10.51.0`)

2. **Fixes the root cause**:
- Root Yarn resolution pinning `@opentelemetry/api` to `1.9.1` → single
copy in the entire tree, Sentry and Twenty share the same instance
- Named import in `instrument.ts` (`import { metrics as otelMetrics }`
instead of default import) as defense-in-depth against CJS interop
issues

### Verified on dev cluster

Exec'd into the running pod and confirmed:
- `@sentry/node` nests `@opentelemetry/api@1.9.1`, hoisted is `1.9.0`
- `Sentry.init()` → global version `1.9.1` → `setGlobalMeterProvider`
with VERSION `1.9.0` → returns `false` → `NoopMeterProvider`
- Same-version registration returns `true` → `MeterProvider` ✓

## Test plan
- [ ] CI passes (lint, typecheck, build)
- [ ] Deploy to dev cluster and verify metrics flow to collector
- [ ] Confirm `node_modules/@opentelemetry/api/package.json` shows
`1.9.1` with no nested copy under `@sentry/`

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-04 15:15:00 +02:00
Charles Bochet ff22988caf revert: Sentry #20064 + @sentry 10.27 (prod bisect) (#20221)
## Summary

Reverts **#20064** (`feat(sentry): propagate workspace context to all
spans`) and downgrades **@sentry** packages from **10.51** back to
**10.27** (reversing **#20149**), to validate in production whether
recent Sentry/instrumentation changes correlate with OTLP/metrics
issues.

## Changes

1. **Revert #20064** — removes `beforeSendSpan` from `instrument.ts`,
restores `WorkspaceAuthContextMiddleware` / `BullMQDriver` behavior, and
deletes the three `apply-workspace-sentry-*` utils added in that PR.
2. **Sentry versions** — `packages/twenty-server` (`@sentry/nestjs`,
`@sentry/node`, `@sentry/profiling-node`) and `packages/twenty-front`
(`@sentry/react`) set to `^10.27.0`; `yarn.lock` regenerated via `yarn
install`.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-04 11:09:48 +02:00
Paul Rastoin 8a0225e974 Dispatch root package.json hoisted deps and devDeps (#20140)
# Introduction
Dispatching root package.json devDeps, prod deps
Taking care of keeping non imported module used at build/ci level in the
root package.json

## Motivation
Avoid redundant deps declaration, better scoping allow better workspace
deps granularity installation.

<img width="385" height="247" alt="image"
src="https://github.com/user-attachments/assets/9d7162ec-ba01-4f58-8563-38333733fdf0"
/>

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-04-30 16:50:22 +00:00
dependabot[bot] 83db37d33f chore(deps): bump @sentry/profiling-node from 10.27.0 to 10.51.0 (#20149)
Bumps
[@sentry/profiling-node](https://github.com/getsentry/sentry-javascript)
from 10.27.0 to 10.51.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/getsentry/sentry-javascript/releases"><code>@​sentry/profiling-node</code>'s
releases</a>.</em></p>
<blockquote>
<h2>10.51.0</h2>
<h3>Important Changes</h3>
<ul>
<li>
<p><strong>feat(cloudflare): Add trace propagation for RPC method calls
(<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/20343">#20343</a>)</strong></p>
<p>Trace context is now propagated across Cloudflare Workers RPC calls,
connecting traces between Workers and Durable Objects.
This feature is opt-in and requires setting
<code>enableRpcTracePropagation: true</code> in your SDK
configuration:</p>
<pre lang="ts"><code>// Worker
export default Sentry.withSentry(
  env =&gt; ({
    dsn: env.SENTRY_DSN,
    enableRpcTracePropagation: true,
  }),
  handler,
);
<p>// Durable Object<br />
export const MyDurableObject =
Sentry.instrumentDurableObjectWithSentry(<br />
env =&gt; ({<br />
dsn: env.SENTRY_DSN,<br />
enableRpcTracePropagation: true,<br />
}),<br />
MyDurableObjectBase,<br />
);<br />
</code></pre></p>
</li>
<li>
<p><strong>feat(hono)!: Change setup for <code>@sentry/hono/node</code>
(<code>init</code> in external file) (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/20497">#20497</a>)</strong></p>
<p>To improve Node.js instrumentation, the <code>sentry()</code>
middleware exported from <code>@sentry/hono/node</code> no longer
accepts configuration options.
Instead, you must configure the SDK by calling
<code>Sentry.init()</code> in a dedicated instrumentation file that runs
before your application code (read more in the <a
href="https://github.com/getsentry/sentry-javascript/blob/develop/packages/hono/README.md">Hono
SDK readme</a>:</p>
<pre lang="ts"><code>// instrument.mjs (or instrument.ts)
import * as Sentry from '@sentry/hono/node';
<p>Sentry.init({<br />
dsn: '<strong>DSN</strong>',<br />
tracesSampleRate: 1.0,<br />
});<br />
</code></pre></p>
</li>
<li>
<p><strong>feat(nitro): Add <code>@sentry/nitro</code> SDK (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/19224">#19224</a>)</strong></p>
<p>A new <code>@sentry/nitro</code> package provides first-class Sentry
support for <a href="https://nitro.build/">Nitro</a> applications, with
HTTP handler and error instrumentation, middleware tracing, request
isolation, and build-time source map uploading via
<code>withSentryConfig</code>.
Read more in the <a
href="https://docs.sentry.io/platforms/javascript/guides/nitro/">Nitro
SDK docs</a> and the <a
href="https://github.com/getsentry/sentry-javascript/blob/develop/packages/nitro/README.md">Nitro
SDK readme</a>.</p>
</li>
</ul>
<h3>Other Changes</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md"><code>@​sentry/profiling-node</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>10.51.0</h2>
<h3>Important Changes</h3>
<ul>
<li>
<p><strong>feat(cloudflare): Add trace propagation for RPC method calls
(<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/20343">#20343</a>)</strong></p>
<p>Trace context is now propagated across Cloudflare Workers RPC calls,
connecting traces between Workers and Durable Objects.
This feature is opt-in and requires setting
<code>enableRpcTracePropagation: true</code> in your SDK
configuration:</p>
<pre lang="ts"><code>// Worker
export default Sentry.withSentry(
  env =&gt; ({
    dsn: env.SENTRY_DSN,
    enableRpcTracePropagation: true,
  }),
  handler,
);
<p>// Durable Object<br />
export const MyDurableObject =
Sentry.instrumentDurableObjectWithSentry(<br />
env =&gt; ({<br />
dsn: env.SENTRY_DSN,<br />
enableRpcTracePropagation: true,<br />
}),<br />
MyDurableObjectBase,<br />
);<br />
</code></pre></p>
</li>
<li>
<p><strong>feat(hono)!: Change setup for <code>@sentry/hono/node</code>
(<code>init</code> in external file) (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/20497">#20497</a>)</strong></p>
<p>To improve Node.js instrumentation, the <code>sentry()</code>
middleware exported from <code>@sentry/hono/node</code> no longer
accepts configuration options.
Instead, you must configure the SDK by calling
<code>Sentry.init()</code> in a dedicated instrumentation file that runs
before your application code (read more in the <a
href="https://github.com/getsentry/sentry-javascript/blob/develop/packages/hono/README.md">Hono
SDK readme</a>:</p>
<pre lang="ts"><code>// instrument.mjs (or instrument.ts)
import * as Sentry from '@sentry/hono/node';
<p>Sentry.init({<br />
dsn: '<strong>DSN</strong>',<br />
tracesSampleRate: 1.0,<br />
});<br />
</code></pre></p>
</li>
<li>
<p><strong>feat(nitro): Add <code>@sentry/nitro</code> SDK (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/19224">#19224</a>)</strong></p>
<p>A new <code>@sentry/nitro</code> package provides first-class Sentry
support for <a href="https://nitro.build/">Nitro</a> applications, with
HTTP handler and error instrumentation, middleware tracing, request
isolation, and build-time source map uploading via
<code>withSentryConfig</code>.
Read more in the <a
href="https://docs.sentry.io/platforms/javascript/guides/nitro/">Nitro
SDK docs</a> and the <a
href="https://github.com/getsentry/sentry-javascript/blob/develop/packages/nitro/README.md">Nitro
SDK readme</a>.</p>
</li>
</ul>
<h3>Other Changes</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/dc0b839ff4896cf90a02f5c1a6de54a31302dcf3"><code>dc0b839</code></a>
release: 10.51.0</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/b3cabee9a9348b9e67332262d44d3d1900424199"><code>b3cabee</code></a>
Merge pull request <a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/20599">#20599</a>
from getsentry/prepare-release/10.51.0</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/3be99a9afa77e49578e6839e4b32f97fb04fb0f8"><code>3be99a9</code></a>
meta(changelog): Update changelog for 10.51.0</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/bea1aad42277db894d5a299bfec3cdd633d6baf0"><code>bea1aad</code></a>
test(browser): Unflake some more tests (<a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/20591">#20591</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/50aa0859b3a188d34d0317dab3ad57f2140f02fe"><code>50aa085</code></a>
test(node): Unflake postgres tests (<a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/20593">#20593</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/1166839112c4766f210124dc0486ebbfd6db104b"><code>1166839</code></a>
fix(hono): Distinguish <code>.use()</code> middleware in sub-apps from
<code>.all()</code> handlers...</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/217ad4a69554281806eccbfeac1b27c4f43f6ffa"><code>217ad4a</code></a>
test(node): Fix flaky ANR test (<a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/20592">#20592</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/91ffb3fac90835ab160f8152527a54a5d64f3250"><code>91ffb3f</code></a>
test(node): Fix flaky worker thread integration test (<a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/20588">#20588</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/c4e3902c9297147158e730f017aba96e83ef619e"><code>c4e3902</code></a>
chore(ci): Do not report flaky test issues if we cannot find a test name
(<a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/20">#20</a>...</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/c0005cd387f3a7ea6fbb2e85041562c7f32e0484"><code>c0005cd</code></a>
test(node): Update timeout for cron integration tests (<a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/20586">#20586</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/getsentry/sentry-javascript/compare/10.27.0...10.51.0">compare
view</a></li>
</ul>
</details>
<br />


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

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

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

---

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

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


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2026-04-30 12:02:34 +00:00
Paul Rastoin 89ad87aa64 Make twenty-front build env agnostic (#20055)
## Introduction
In aim to reduce and optimize the number of twenty-front build we do
during our cd process and allow twenty-front build promotion

### Build time

**Nothing is baked.** The `build/` directory is a clean, env-agnostic
artifact. `index.html` contains the empty placeholder:

```html
<script id="twenty-env-config">
  window._env_ = {
    // This will be overwritten
  };
</script>
```

The JS bundles contain no hardcoded server URL.

---

### Deploy mode 1: Frontend served by the backend (Docker / NestJS)

1. Container starts, NestJS boots in `main.ts`
2. `generateFrontConfig()` runs, reads `process.env.SERVER_URL`
3. Rewrites `dist/front/index.html`, replacing the placeholder with:
   ```html
   <script id="twenty-env-config">
     window._env_ = {
       REACT_APP_SERVER_BASE_URL: "https://api.example.com"
     };
   </script>
   ```
4. NestJS serves the static `dist/front/` directory
5. Browser loads `index.html`, `window._env_` is set before the app JS
executes
6. `src/config/index.ts` reads `window._env_.REACT_APP_SERVER_BASE_URL`
and uses it

---

### Deploy mode 2: Frontend served standalone (CDN / nginx / static
server)

1. Take the `build/` artifact as-is
2. Before serving, run at deploy time:
   ```bash
REACT_APP_SERVER_BASE_URL=https://api.example.com sh
./scripts/inject-runtime-env.sh
   ```
3. This does the same `sed` replacement on `build/index.html`
4. Serve the `build/` directory with your static server of choice
5. Same resolution in the browser:
`window._env_.REACT_APP_SERVER_BASE_URL` is picked up by
`src/config/index.ts`

---

### Fallback: no injection at all

If neither mechanism runs (e.g. local dev with `vite dev`),
`window._env_.REACT_APP_SERVER_BASE_URL` is `undefined`, and
`getDefaultUrl()` kicks in:
- **Localhost**: returns `http://localhost:3000`
- **Non-localhost**: returns same-origin (`window.location.origin`)
2026-04-26 07:05:54 +00:00
dependabot[bot] 80e8f6d516 chore(deps): bump @blocknote/server-util from 0.47.1 to 0.47.3 (#19997)
Bumps
[@blocknote/server-util](https://github.com/TypeCellOS/BlockNote/tree/HEAD/packages/server-util)
from 0.47.1 to 0.47.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/TypeCellOS/BlockNote/releases"><code>@​blocknote/server-util</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v0.47.3</h2>
<h2>0.47.3 (2026-03-25)</h2>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>core:</strong> preserve whitespace edge cases but collapse
html formatting newlines (BLO-1065) (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2551">#2551</a>,
<a
href="https://redirect.github.com/TypeCellOS/BlockNote/issues/2230">#2230</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Yousef</li>
</ul>
<h2>v0.47.2</h2>
<h2>0.47.2 (2026-03-20)</h2>
<h3>🩹 Fixes</h3>
<ul>
<li>use <code>&lt;details&gt;</code> &amp; <code>&lt;summary&gt;</code>
for toggle block HTML export (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2524">#2524</a>)</li>
<li>remove <code>@hocuspocus/provider</code> peer dependency by inlining
tiptap comment types BLO-1064 (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2564">#2564</a>)</li>
<li><strong>core:</strong> slash menu fails in custom blocks after space
BLO-1036 (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2553">#2553</a>)</li>
<li><strong>i18n:</strong> fix typo in russian translation (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2560">#2560</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Drone</li>
<li>Yousef</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/TypeCellOS/BlockNote/blob/main/CHANGELOG.md"><code>@​blocknote/server-util</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>0.47.3 (2026-03-25)</h2>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>core:</strong> preserve whitespace edge cases but collapse
html formatting newlines (BLO-1065) (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2551">#2551</a>,
<a
href="https://redirect.github.com/TypeCellOS/BlockNote/issues/2230">#2230</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Yousef</li>
</ul>
<h2>0.47.2 (2026-03-20)</h2>
<h3>🩹 Fixes</h3>
<ul>
<li>use <!-- raw HTML omitted -->/<!-- raw HTML omitted --> for toggle
block HTML export (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2524">#2524</a>)</li>
<li>remove <code>@​hocuspocus/provider</code> peer dependency by
inlining tiptap comment types BLO-1064 (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2564">#2564</a>)</li>
<li><strong>core:</strong> slash menu fails in custom blocks after space
BLO-1036 (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2553">#2553</a>)</li>
<li><strong>i18n:</strong> fix typo in russian translation (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2560">#2560</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Claude Opus 4.6</li>
<li>Drone</li>
<li>Yousef</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/TypeCellOS/BlockNote/commit/cd92dc21be49397b658fef4e308e01ce8f5c04ad"><code>cd92dc2</code></a>
chore(release): publish 0.47.3</li>
<li><a
href="https://github.com/TypeCellOS/BlockNote/commit/b63b4096daa575f821980ef897fd90f4c76d9e42"><code>b63b409</code></a>
chore(release): publish 0.47.2</li>
<li><a
href="https://github.com/TypeCellOS/BlockNote/commit/d76fd68e016da698f3896f9d349a935a26a52d5f"><code>d76fd68</code></a>
test: get snapshots working again (<a
href="https://github.com/TypeCellOS/BlockNote/tree/HEAD/packages/server-util/issues/2554">#2554</a>)</li>
<li>See full diff in <a
href="https://github.com/TypeCellOS/BlockNote/commits/v0.47.3/packages/server-util">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@blocknote/server-util&package-manager=npm_and_yarn&previous-version=0.47.1&new-version=0.47.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>
Co-authored-by: Abdullah <125115953+mabdullahabaid@users.noreply.github.com>
2026-04-23 07:29:45 +00:00
Félix Malfait fd7387928c feat: queue messages + replace AI SDK with GraphQL SSE subscription (#19203)
## Summary

- **Queue messages while streaming**: Messages sent during active AI
streaming are queued server-side and auto-flushed when the current
stream completes. Frontend renders queued messages optimistically in a
dedicated queue UI.
- **Drop `@ai-sdk/react` + `resumable-stream`**: Replace the dual HTTP
SSE + AI SDK client architecture with a single GraphQL SSE subscription
per thread. All events (token chunks, message persistence, queue
updates, errors) flow through Redis PubSub → GraphQL subscription.
- **Server-driven architecture**: The server decides whether to queue or
stream (via `POST /:threadId/message`). The frontend mirrors this
decision for optimistic rendering but defers to the server response.
- **Reuse AI SDK accumulation logic**: `readUIMessageStream` from the
`ai` package handles chunk-to-message accumulation on the frontend,
avoiding a custom 780-line accumulator.

## Key files

**Backend:**
- `agent-chat-event-publisher.service.ts` — publishes events to Redis
PubSub
- `agent-chat-subscription.resolver.ts` — GraphQL subscription resolver
- `stream-agent-chat.job.ts` — publishes chunks via PubSub instead of
resumable-stream
- `agent-chat.controller.ts` — unified `POST /:threadId/message`
endpoint

**Frontend:**
- `useAgentChatSubscription.ts` — subscribes to `onAgentChatEvent`,
bridges to `readUIMessageStream`
- `useAgentChat.ts` — send/stop/optimistic rendering (no more AI SDK)
- `AgentChatStreamSubscriptionEffect.tsx` — replaces
`AgentChatAiSdkStreamEffect.tsx`

## Test plan

- [ ] Send message on new thread → optimistic render, streaming response
appears
- [ ] Send message while streaming → queued instantly (no flash in main
thread)
- [ ] Queued message auto-flushes after current stream completes
- [ ] Remove queued message via queue UI
- [ ] Stop streaming mid-response
- [ ] Leave chat idle for several minutes → streaming still works after
(SSE client recycling)
- [ ] Token refresh during session → requests succeed (authenticated
fetch)
- [ ] Switch threads while streaming → clean subscription handoff


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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 10:10:13 +02:00
Paul Rastoin 37908114fc [SDK] Extract twenty-front-component-renderer outside of twenty-sdk ( 2.8MB ) (#19021)
Followup https://github.com/twentyhq/twenty/pull/19010

## Dependency diagram

```
┌─────────────────────┐
│     twenty-front    │
│   (React frontend)  │
└─────────┬───────────┘
          │ imports runtime:
          │   FrontComponentRenderer
          │   FrontComponentRendererWithSdkClient
          │   useFrontComponentExecutionContext
          ▼
┌──────────────────────────────────┐         ┌─────────────────────────┐
│ twenty-front-component-renderer  │────────▶│       twenty-sdk        │
│   (remote-dom host + worker)     │         │  (app developer SDK)    │
│                                  │         │                         │
│  imports from twenty-sdk:        │         │  Public API:            │
│   • types only:                  │         │   defineFrontComponent  │
│     FrontComponentExecutionContext│         │   navigate, closeSide…  │
│     NavigateFunction             │         │   useFrontComponent…    │
│     CloseSidePanelFunction       │         │   Command components    │
│     CommandConfirmation…         │         │   conditional avail.    │
│     OpenCommandConfirmation…     │         │                         │
│     EnqueueSnackbarFunction      │         │  Internal only:         │
│     etc.                         │         │   frontComponentHost…   │
│                                  │         │   front-component-build │
│  owns locally:                   │         │   esbuild plugins       │
│   • ALLOWED_HTML_ELEMENTS        │         │                         │
│   • EVENT_TO_REACT               │         └────────────┬────────────┘
│   • HTML_TAG_TO_CUSTOM_ELEMENT…  │                      │
│   • SerializedEventData          │                      │ types
│   • PropertySchema               │                      ▼
│   • frontComponentHostComm…      │         ┌─────────────────────────┐
│     (local ref to globalThis)    │         │     twenty-shared       │
│   • setFrontComponentExecution…  │         │  (common types/utils)   │
│     (local impl, same keys)      │         │   AppPath, SidePanelP…  │
│                                  │         │   EnqueueSnackbarParams │
└──────────────────────────────────┘         │   isDefined, …          │
          │                                  └─────────────────────────┘
          │ also depends on
          ▼
    twenty-shared (types)
    @remote-dom/* (runtime)
    @quilted/threads (runtime)
    react (runtime)
```

**Key points:**

- **`twenty-front`** depends on the renderer, **not** on `twenty-sdk`
directly (for rendering)
- **`twenty-front-component-renderer`** depends on `twenty-sdk` for
**types only** (function signatures, `FrontComponentExecutionContext`).
The runtime bridge (`frontComponentHostCommunicationApi`) is shared via
`globalThis` keys, not module imports
- **`twenty-sdk`** has no dependency on the renderer — clean one-way
dependency
- The renderer owns all remote-dom infrastructure (element schemas,
event mappings, custom element tags) that was previously leaking through
the SDK's public API
- The SDK's `./build` entry point was removed entirely (unused)
2026-03-30 17:06:06 +00:00
Félix Malfait b470cb21a1 Upgrade Apollo Client to v4 and refactor error handling (#18584)
## Summary
This PR upgrades Apollo Client from v3.10.0 to v4 and refactors error
handling patterns across the codebase to use a new centralized
`useSnackBarOnQueryError` hook.

## Key Changes

- **Dependency Update**: Upgraded `@apollo/client` from `^3.10.0` to
`^3.11.0` in root package.json
- **New Hook**: Added `useSnackBarOnQueryError` hook for centralized
Apollo query error handling with snack bar notifications
- **Error Handling Refactor**: Updated 100+ files to use the new error
handling pattern:
  - Removed direct `ApolloError` imports where no longer needed
- Replaced manual error handling logic with `useSnackBarOnQueryError`
hook
- Simplified error handling in hooks and components across multiple
modules
- **GraphQL Codegen**: Updated codegen configuration files to work with
Apollo Client v3.11.0
- **Type Definitions**: Added TypeScript declaration file for
`apollo-upload-client` module
- **Test Updates**: Updated test files to reflect new error handling
patterns

## Notable Implementation Details

- The new `useSnackBarOnQueryError` hook provides a consistent way to
handle Apollo query errors with automatic snack bar notifications
- Changes span across multiple feature areas: auth, object records,
settings, workflows, billing, and more
- All changes maintain backward compatibility while improving code
maintainability and reducing duplication
- Jest configuration updated to work with the new Apollo Client version

https://claude.ai/code/session_019WGZ6Rd7sEHuBg9sTrXRqJ

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-13 14:59:46 +01:00
Abdul Rahman 5b28e59ca7 Navbar drag drop using dnd kit (#18288) 2026-03-08 20:25:50 +00:00
Charles Bochet 9d57bc39e5 Migrate from ESLint to OxLint (#18443)
## Summary

Fully replaces ESLint with OxLint across the entire monorepo:

- **Replaced all ESLint configs** (`eslint.config.mjs`) with OxLint
configs (`.oxlintrc.json`) for every package: `twenty-front`,
`twenty-server`, `twenty-emails`, `twenty-ui`, `twenty-shared`,
`twenty-sdk`, `twenty-zapier`, `twenty-docs`, `twenty-website`,
`twenty-apps/*`, `create-twenty-app`
- **Migrated custom lint rules** from ESLint plugin format to OxLint JS
plugin system (`@oxlint/plugins`), including
`styled-components-prefixed-with-styled`, `no-hardcoded-colors`,
`sort-css-properties-alphabetically`,
`graphql-resolvers-should-be-guarded`,
`rest-api-methods-should-be-guarded`, `max-consts-per-file`, and
Jotai-related rules
- **Migrated custom rule tests** from ESLint `RuleTester` + Jest to
`oxlint/plugins-dev` `RuleTester` + Vitest
- **Removed all ESLint dependencies** from `package.json` files and
regenerated lockfiles
- **Updated Nx targets** (`lint`, `lint:diff-with-main`, `fmt`) in
`nx.json` and per-project `project.json` to use `oxlint` commands with
proper `dependsOn` for plugin builds
- **Updated CI workflows** (`.github/workflows/ci-*.yaml`) — no more
ESLint executor
- **Updated IDE setup**: replaced `dbaeumer.vscode-eslint` with
`oxc.oxc-vscode` extension, configured `source.fixAll.oxc` and
format-on-save with Prettier
- **Replaced all `eslint-disable` comments** with `oxlint-disable`
equivalents across the codebase
- **Updated docs** (`twenty-docs`) to reference OxLint instead of ESLint
- **Renamed** `twenty-eslint-rules` package to `twenty-oxlint-rules`

### Temporarily disabled rules (tracked in `OXLINT_MIGRATION_TODO.md`)

| Rule | Package | Violations | Auto-fixable |
|------|---------|-----------|-------------|
| `twenty/sort-css-properties-alphabetically` | twenty-front | 578 | Yes
|
| `typescript/consistent-type-imports` | twenty-server | 3814 | Yes |
| `twenty/max-consts-per-file` | twenty-server | 94 | No |

### Dropped plugins (no OxLint equivalent)

`eslint-plugin-project-structure`, `lingui/*`, `@stylistic/*`,
`import/order`, `prefer-arrow/prefer-arrow-functions`,
`eslint-plugin-mdx`, `@next/eslint-plugin-next`,
`eslint-plugin-storybook`, `eslint-plugin-react-refresh`. Partial
coverage for `jsx-a11y` and `unused-imports`.

### Additional fixes (pre-existing issues exposed by merge)

- Fixed `EmailThreadPreview.tsx` broken import from main rename
(`useOpenEmailThreadInSidePanel`)
- Restored truthiness guard in `getActivityTargetObjectRecords.ts`
- Fixed `AgentTurnResolver` return types to match entity (virtual
`fileMediaType`/`fileUrl` are resolved via `@ResolveField()`)

## Test plan

- [x] `npx nx lint twenty-front` passes
- [x] `npx nx lint twenty-server` passes
- [x] `npx nx lint twenty-docs` passes
- [x] Custom oxlint rules validated with Vitest: `npx nx test
twenty-oxlint-rules`
- [x] `npx nx typecheck twenty-front` passes
- [x] `npx nx typecheck twenty-server` passes
- [x] CI workflows trigger correctly with `dependsOn:
["twenty-oxlint-rules:build"]`
- [x] IDE linting works with `oxc.oxc-vscode` extension
2026-03-06 01:03:50 +01:00
Charles Bochet 1affa1e004 chore(front): remove vite-plugin-checker background TS/ESLint checks (#18437)
## Summary

Removes `vite-plugin-checker` and all references to
`VITE_DISABLE_TYPESCRIPT_CHECKER` / `VITE_DISABLE_ESLINT_CHECKER`.

These background checks are no longer needed because our dev experience
now relies on **independent** linters and type-checkers:
- `npx nx lint:diff-with-main twenty-front` for ESLint
- `npx nx typecheck twenty-front` for TypeScript

Running these as separate processes (rather than inside Vite) is faster,
gives cleaner output, and avoids the significant memory overhead that
`vite-plugin-checker` introduces during `vite dev` and `vite build`. The
old env vars to disable them are removed from `vite.config.ts`,
`package.json` scripts, `nx.json`, `.env.example`, and all translated
docs.
2026-03-05 18:55:04 +01:00
dependabot[bot] 6a2e0182ab Bump @blocknote/server-util from 0.47.0 to 0.47.1 (#18408)
Bumps
[@blocknote/server-util](https://github.com/TypeCellOS/BlockNote/tree/HEAD/packages/server-util)
from 0.47.0 to 0.47.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/TypeCellOS/BlockNote/releases"><code>@​blocknote/server-util</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v0.47.1</h2>
<h2>0.47.1 (2026-03-02)</h2>
<h3>🩹 Fixes</h3>
<ul>
<li>typeerror cannot read properties of undefined (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2522">#2522</a>)</li>
<li>handle more delete key cases (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2126">#2126</a>)</li>
<li>add delay for <code>data-active</code> in collab cursors (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2383">#2383</a>)</li>
<li>disable slash menu in table content <a
href="https://github.com/TypeCellOS/BlockNote/tree/HEAD/packages/server-util/issues/2408">#2408</a>
(<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2504">#2504</a>,
<a
href="https://redirect.github.com/TypeCellOS/BlockNote/issues/2408">#2408</a>)</li>
<li><strong>ai:</strong> selections broken due to floating-ui focus
manager (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2527">#2527</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Matthew Lipski <a
href="https://github.com/matthewlipski"><code>@​matthewlipski</code></a></li>
<li>Nick Perez</li>
<li>Yousef</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/TypeCellOS/BlockNote/blob/main/CHANGELOG.md"><code>@​blocknote/server-util</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>0.47.1 (2026-03-02)</h2>
<h3>🩹 Fixes</h3>
<ul>
<li>typeerror cannot read properties of undefined (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2522">#2522</a>)</li>
<li>handle more delete key cases (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2126">#2126</a>)</li>
<li>add delay for <code>data-active</code> in collab cursors (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2383">#2383</a>)</li>
<li>disable slash menu in table content <a
href="https://github.com/TypeCellOS/BlockNote/tree/HEAD/packages/server-util/issues/2408">#2408</a>
(<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2504">#2504</a>,
<a
href="https://redirect.github.com/TypeCellOS/BlockNote/issues/2408">#2408</a>)</li>
<li><strong>ai:</strong> selections broken due to floating-ui focus
manager (<a
href="https://redirect.github.com/TypeCellOS/BlockNote/pull/2527">#2527</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Matthew Lipski <a
href="https://github.com/matthewlipski"><code>@​matthewlipski</code></a></li>
<li>Nick Perez</li>
<li>Yousef</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/TypeCellOS/BlockNote/commit/d5d056fe3d5362e73fb72e3e3bf1f839aee3e875"><code>d5d056f</code></a>
chore(release): publish 0.47.1</li>
<li>See full diff in <a
href="https://github.com/TypeCellOS/BlockNote/commits/v0.47.1/packages/server-util">compare
view</a></li>
</ul>
</details>
<br />


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

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

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

---

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

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


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abdullah <125115953+mabdullahabaid@users.noreply.github.com>
2026-03-05 09:22:06 +01:00
dependabot[bot] 72086fe111 Bump @dagrejs/dagre from 1.1.3 to 1.1.8 (#18409)
Bumps [@dagrejs/dagre](https://github.com/dagrejs/dagre) from 1.1.3 to
1.1.8.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/dagrejs/dagre/commit/7e4d15f191678f7f05f3c86d9071a193230e7e00"><code>7e4d15f</code></a>
Building for release</li>
<li><a
href="https://github.com/dagrejs/dagre/commit/d3908e2c13148c9143db585accc10ae0b6634657"><code>d3908e2</code></a>
Bumping version</li>
<li><a
href="https://github.com/dagrejs/dagre/commit/ce295f8e073c4fe96c9e36ecf08ae2940e5e6a10"><code>ce295f8</code></a>
Build for release</li>
<li><a
href="https://github.com/dagrejs/dagre/commit/b64b9057726eee17f24f73579ba0668527276448"><code>b64b905</code></a>
Bumping the version</li>
<li><a
href="https://github.com/dagrejs/dagre/commit/de169d24c13d06c1e9c560f4f4f8f98650109b94"><code>de169d2</code></a>
Merge pull request <a
href="https://redirect.github.com/dagrejs/dagre/issues/481">#481</a>
from Nathan-Fenner/nf/improve-network-simplex-perform...</li>
<li><a
href="https://github.com/dagrejs/dagre/commit/065e0d8374f4c1c35a7cb4b84df37aaa31598d86"><code>065e0d8</code></a>
improve performance of graph node ranking</li>
<li><a
href="https://github.com/dagrejs/dagre/commit/00d3178d671e49de9c032e3abd281dc9f2739e73"><code>00d3178</code></a>
Typo</li>
<li><a
href="https://github.com/dagrejs/dagre/commit/3982a69d2b323b06aa969a4ec09829d37fe6e7bd"><code>3982a69</code></a>
Bump version and set as pre-release</li>
<li><a
href="https://github.com/dagrejs/dagre/commit/1339f5516508dba0cbcc4ef1c0587e7384bec23d"><code>1339f55</code></a>
Building for release</li>
<li><a
href="https://github.com/dagrejs/dagre/commit/9459f01bc815f16b87db727821d8401acbad2cd3"><code>9459f01</code></a>
Bumping the version</li>
<li>Additional commits viewable in <a
href="https://github.com/dagrejs/dagre/compare/v1.1.3...v1.1.8">compare
view</a></li>
</ul>
</details>
<br />


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

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

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

---

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

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


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abdullah <125115953+mabdullahabaid@users.noreply.github.com>
2026-03-05 09:21:45 +01:00
Abdullah. 76c7639eb3 fix: upgrade storybook to latest to resolve dependabot alert (#18285)
Resolves [Dependabot Alert
509](https://github.com/twentyhq/twenty/security/dependabot/509).

Upgraded storybook and related packages to latest, also fixed a failing
test to match what the DOM really contains.
2026-02-27 10:58:54 +01:00
Abdullah. 4ed09a3feb Upgrade blocknote dependencies from 0.31.1 to 0.47.0. (#18207)
This PR pgrades all BlockNote packages (@blocknote/core,
@blocknote/react, @blocknote/mantine, @blocknote/server-util,
@blocknote/xl-docx-exporter, @blocknote/xl-pdf-exporter) to 0.47.0 and
adapts the codebase to the new API.

### Changes
- Dependency upgrades: Bumped all BlockNote packages to 0.47.0, added
required Mantine v8 peer dependencies, removed unnecessary prosemirror
resolutions
- Formatting toolbar: Replaced the manual reimplementation of
FormattingToolbarController (which handled visibility, positioning,
portal rendering, text-alignment-based placement, and a
dangerouslySetInnerHTML transition trick) with BlockNote's built-in
FormattingToolbarController. The toolbar buttons themselves are
unchanged.
- Side menu: Replaced manual drag handle menu positioning and rendering
(DashboardBlockDragHandleMenu, DashboardBlockColorPicker, and their
floating configs) with BlockNote's built-in SideMenuController,
DragHandleButton, and DragHandleMenu components. Deleted 4 files that
became dead code.
- Extension API migration: Replaced deprecated editor.suggestionMenus
and editor.formattingToolbar APIs with the new extension system
(SuggestionMenu, useExtensionState, editor.getExtension())
- Slash menu fixes: Filtered out BlockNote's new default "File" item
(added in 0.47) to avoid duplicates with our custom one; added icon
mappings for new block types (Toggle List, Divider, Toggle Headings,
Headings 4-6)
- Server-side: Switched @blocknote/server-util to dynamic import() to
handle ESM-only transitive dependencies in CJS context
2026-02-27 09:16:49 +01:00
Abdullah. 9107f5bbc7 feat: upgrade ai package to version six and the corresponding @ai-sdk/* packages to compatible versions (#18172)
Used the migration guide to carry out this upgrade:
https://ai-sdk.dev/docs/migration-guides/migration-guide-6-0

I have not been able to test locally due to credits.

<img width="220" height="450" alt="image"
src="https://github.com/user-attachments/assets/050b34b9-3239-4010-8c47-b43d44571994"
/>

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-02-25 16:49:26 +01:00
Charles Bochet 121788c42f Fully deprecate old recoil (#18210)
## Summary

Removes the `recoil` dependency entirely from `package.json` and
`twenty-front/package.json`, completing the migration to Jotai as the
sole state management library.

Removes all Recoil infrastructure: `RecoilRoot` wrapper from `App.tsx`
and test decorators, `RecoilDebugObserver`, Recoil-specific ESLint rules
(`use-getLoadable-and-getValue-to-get-atoms`,
`useRecoilCallback-has-dependency-array`), and legacy Recoil utility
hooks/types (`useRecoilComponentState`, `useRecoilComponentValue`,
`createComponentState`, `createFamilyState`, `getSnapshotValue`,
`cookieStorageEffect`, `localStorageEffect`, etc.).

Renames all `V2`-suffixed Jotai state files and types to their canonical
names (e.g., `ComponentStateV2` -> `ComponentState`,
`agentChatInputStateV2` -> `agentChatInputState`, `SelectorCallbacksV2`
-> `SelectorCallbacks`), and removes the now-redundant V1 counterparts.

Updates ~433 files across the codebase to use the renamed Jotai imports,
remove Recoil imports, and clean up test wrappers (`RecoilRootDecorator`
-> `JotaiRootDecorator`).
2026-02-25 12:26:42 +01:00
Félix Malfait 0e25aeb5be chore: upgrade @swc/core to 1.15.11 and align SWC ecosystem (#18088)
## Summary

- Upgrades `@swc/core` from 1.13.3 to **1.15.11** (swc_core v56), which
introduces CBOR-based plugin serialization replacing rkyv, eliminating
strict version-matching between SWC core and Wasm plugins
- Upgrades `@lingui/swc-plugin` from ^5.6.0 to **^5.11.0** (swc_core
50.2.3, built with `--cfg=swc_ast_unknown` for cross-version
compatibility)
- Upgrades `@swc/plugin-emotion` from 10.0.4 to **14.6.0** (swc_core 53,
also with backward-compat feature)
- Upgrades companion packages: `@swc-node/register` 1.8.0 → 1.11.1,
`@swc/helpers` ~0.5.2 → ~0.5.18, `@vitejs/plugin-react-swc` 3.11.0 →
4.2.3

### Why this is safe now

Starting from `@swc/core v1.15.0`, SWC replaced the rkyv serialization
scheme with CBOR (a self-describing format) and added `Unknown` AST enum
variants. Plugins built with `swc_core >= 47` and
`--cfg=swc_ast_unknown` are now forward-compatible across `@swc/core`
versions. Both `@lingui/swc-plugin@5.10.1+` and
`@swc/plugin-emotion@14.0.0+` have this support, meaning the old
version-matching nightmare between Lingui and SWC is largely solved.

Reference: https://github.com/lingui/swc-plugin/issues/179

## Test plan

- [x] `yarn install` resolves without errors
- [x] `npx nx build twenty-shared` succeeds
- [x] `npx nx build twenty-ui` succeeds (validates
@swc/plugin-emotion@14.6.0)
- [x] `npx nx typecheck twenty-front` succeeds
- [x] `npx nx build twenty-front` succeeds (validates vite + swc +
lingui pipeline)
- [x] `npx nx build twenty-emails` succeeds (validates lingui plugin)
- [x] Frontend jest tests pass (validates @swc/jest +
@lingui/swc-plugin)
- [x] Server jest tests pass (validates server-side SWC + lingui)

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

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-19 15:27:56 +00:00
Charles Bochet d2f8352cb8 Start Jotai Migration (#17893)
## Recoil → Jotai progressive migration: infrastructure +
ChipFieldDisplay

### Benchmark

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

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



### Approach

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

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

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

#### Dual-write bridge for progressive migration

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

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

#### First migration: ChipFieldDisplay render path

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

#### Pattern for migrating additional state

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

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

Evaluated
[jotai-recoil-adapter](https://github.com/clockelliptic/jotai-recoil-adapter)
— not production-ready (21 open issues, no React 19, forces providerless
mode, missing types). We built a purpose-built thin layer instead.
2026-02-12 16:05:38 +01:00
Raphaël Bosi f0bc9fcb43 [FRONT COMPONENTS] Move to twenty-sdk (#17587)
Move front components from twenty-shared to twenty-sdk
2026-02-02 12:21:53 +00:00
nitin fb97c40cad [Dashboards] Replace nivo bar chart with custom canvas bar chart (#17441)
before - 


https://github.com/user-attachments/assets/01d1ce73-1732-4516-bde0-d43c1bbcb734

after - 
I got rid of line chart in the after clip -- because now its the line
chart thats more laggy :) -- but now could be easily migrated away from
nivo


https://github.com/user-attachments/assets/430f4697-68cd-47be-b63e-f8df34a2ee0e

stress test - 

before - 



https://github.com/user-attachments/assets/c3d3e05c-943e-48dc-9429-a2ecf41cd4fe



after - 




https://github.com/user-attachments/assets/98b35a43-f918-4a46-9b66-3bc8deabfdb8

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
2026-02-02 07:42:20 +00:00
dependabot[bot] 2b60e41374 build(deps-dev): bump @typescript-eslint/parser from 8.39.0 to 8.51.0 (#16926)
Bumps
[@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser)
from 8.39.0 to 8.51.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases"><code>@​typescript-eslint/parser</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v8.51.0</h2>
<h2>8.51.0 (2025-12-29)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>eslint-plugin:</strong> expose rule name via RuleModule
interface (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11719">#11719</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment] fix
some cases to optional syntax (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11871">#11871</a>)</li>
<li><strong>eslint-plugin:</strong> add namespace to plugin meta (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11885">#11885</a>)</li>
<li><strong>tsconfig-utils:</strong> more informative error on parsing
failures (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11888">#11888</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> fix crash and false positives in
<code>no-useless-default-assignment</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11845">#11845</a>)</li>
<li><strong>eslint-plugin:</strong> remove fixable from
no-dynamic-delete rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11876">#11876</a>)</li>
<li><strong>eslint-plugin:</strong> bump ts-api-utils to 2.2.0 (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11881">#11881</a>)</li>
<li><strong>eslint-plugin:</strong> [prefer-optional-chain] handle
MemberExpression in final chain position (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11835">#11835</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Josh Goldberg </li>
<li>Kirk Waiblinger <a
href="https://github.com/kirkwaiblinger"><code>@​kirkwaiblinger</code></a></li>
<li>mdm317</li>
<li>Ulrich Stark</li>
<li>Yannick Decat <a
href="https://github.com/mho22"><code>@​mho22</code></a></li>
<li>Yukihiro Hasegawa <a
href="https://github.com/y-hsgw"><code>@​y-hsgw</code></a></li>
</ul>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>v8.50.1</h2>
<h2>8.50.1 (2025-12-22)</h2>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [method-signature-style] ignore
methods that return <code>this</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11813">#11813</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-assertion]
correct handling of undefined vs. void (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11826">#11826</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Josh Goldberg </li>
<li>Tamashoo <a
href="https://github.com/Tamashoo"><code>@​Tamashoo</code></a></li>
</ul>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>v8.50.0</h2>
<h2>8.50.0 (2025-12-15)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment] add
rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11720">#11720</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md"><code>@​typescript-eslint/parser</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>8.51.0 (2025-12-29)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.50.1 (2025-12-22)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.50.0 (2025-12-15)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.49.0 (2025-12-08)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.48.1 (2025-12-02)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.48.0 (2025-11-24)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.47.0 (2025-11-17)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.46.4 (2025-11-10)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.46.3 (2025-11-03)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/e4c57f5996a9a3aed8a8c2b02712a9ce37db4928"><code>e4c57f5</code></a>
chore(release): publish 8.51.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/d520b88990e1b20674dcfa3db3b0461c1d6d9aa2"><code>d520b88</code></a>
chore(release): publish 8.50.1</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/c62e85874f0e482156a54b6744fe90a6f270012a"><code>c62e858</code></a>
chore(release): publish 8.50.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/864595a44b56beb9870bf0f41d59cf7f8f48276a"><code>864595a</code></a>
chore(release): publish 8.49.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/32b7e891bd60ae993e85018ceefa2a0c07590688"><code>32b7e89</code></a>
chore(deps): update dependency <code>@​vitest/eslint-plugin</code> to
v1.5.1 (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser/issues/11816">#11816</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/8fe34456f75c1d1e8a4dc518306d5ab93422efec"><code>8fe3445</code></a>
chore(release): publish 8.48.1</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/6fb1551634b2ff11718e579098f69e041a2ff92c"><code>6fb1551</code></a>
chore(release): publish 8.48.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/a4dc42ac541139f0da344550bce7accd8f3d366a"><code>a4dc42a</code></a>
chore: migrate to nx 22 (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser/issues/11780">#11780</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/28cf8032c2492bb3c55dd7dd145249f2246034ad"><code>28cf803</code></a>
chore(release): publish 8.47.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/843f144797c0a94272cdb002c00c5639cf0797c6"><code>843f144</code></a>
chore(release): publish 8.46.4</li>
<li>Additional commits viewable in <a
href="https://github.com/typescript-eslint/typescript-eslint/commits/v8.51.0/packages/parser">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for <code>@​typescript-eslint/parser</code>
since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@typescript-eslint/parser&package-manager=npm_and_yarn&previous-version=8.39.0&new-version=8.51.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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abdullah <125115953+mabdullahabaid@users.noreply.github.com>
2026-01-05 17:19:08 +05:00
Félix Malfait 21ff42074d feat: implement skills system for AI agents (#16865)
## Summary
This PR introduces a Skills system for AI agents, inspired by the [Agent
Skills specification](https://agentskills.io/specification).

## Changes

### Backend
- **SkillEntity**: New database entity with migration for storing skills
- **V2 Sync Mechanism**: Implemented FlatSkill, builders, validators,
and action handlers following the v2 flat entity pattern
- **Standard Skills**: Pre-defined skills (workflow-building,
data-manipulation, dashboard-building, metadata-building, research,
code-interpreter, xlsx, pdf, docx, pptx)
- **GraphQL API**: CRUD operations for skills with proper guards and
permissions
- **Workspace Cache**: Integrated skills into the workspace cache system

### Frontend  
- **Skills Table**: Searchable table in AI settings showing all skills
- **Skill Form**: Create/edit page with Label (primary), Description,
and Content (markdown editor)
- **API Name**: Following existing patterns, name is derived from label
with advanced settings toggle for custom API names
- **Standard vs Custom**: Standard skills are read-only, custom skills
can be edited/deleted

## Key Design Decisions
- Skills are stored in the database (Salesforce-like approach) rather
than files
- Name is derived from Label by default (isLabelSyncedWithName pattern)
- Skills reference functions/files via @ mentions in markdown content
rather than explicit relations
- Standard skills are synced from code, custom skills are created via UI

## Screenshots
Skills table and form UI follow existing settings patterns.

## Testing
- [x] Lint passes
- [x] Typecheck passes
- [ ] CI tests
2026-01-02 14:22:01 +00:00
Abhishek Kumar 61addf8b62 fix(email threads): linkify Email body so that URL links are properly formatted (#16415)
Closes #16396

Added [linkify-react](https://www.npmjs.com/package/linkify-react) and
[linkifyjs](https://www.npmjs.com/package/linkifyjs?activeTab=versions)
to dependancies.
Both are widely used libraries with millions of weekly downloads. 
Both of them have 0 dependancies on other packages, so should be safe to
use.

### Before
URLs were shown as plain text

<img width="395" height="699" alt="Screenshot 2025-12-09 at 12 25 03 PM"
src="https://github.com/user-attachments/assets/772e6d03-8c48-45a1-985c-f775bbd3465c"
/>


### After
URLs are shown as link and are clickable now.

<img width="367" height="641" alt="Screenshot 2025-12-09 at 2 50 29 PM"
src="https://github.com/user-attachments/assets/d15bf23a-7cae-4cd4-b9da-e99706c7db38"
/>

<img width="376" height="656" alt="Screenshot 2025-12-09 at 2 50 46 PM"
src="https://github.com/user-attachments/assets/ba112a65-7550-47e3-b42f-83b94c08bfa6"
/>

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2025-12-30 16:49:31 +00:00
dependabot[bot] 3096769616 build(deps): bump @monaco-editor/react from 4.6.0 to 4.7.0 (#16829)
Bumps
[@monaco-editor/react](https://github.com/suren-atoyan/monaco-react)
from 4.6.0 to 4.7.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/suren-atoyan/monaco-react/releases"><code>@​monaco-editor/react</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.7.0</h2>
<ul>
<li>package: update <code>@monaco-editor/loader</code> to the latest
(<code>v1.5.0</code>) version (this uses <code>monaco-editor</code>
<code>v0.52.2</code>)</li>
<li>package: inherit all changes from <code>v4.7.0-rc.0</code></li>
</ul>
<h2>v4.7.0-rc.0</h2>
<ul>
<li>package: add support for react/react-dom <code>v19</code> as a peer
dependency</li>
<li>playground: update playground's React version to 19</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/suren-atoyan/monaco-react/blob/master/CHANGELOG.md"><code>@​monaco-editor/react</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>4.7.0</h2>
<ul>
<li>package: update <code>@​monaco-editor/loader</code> to the latest
(v1.5.0) version (this uses monaco-editor v0.52.2)</li>
<li>package: inherit all changes from v4.7.0-rc.0</li>
</ul>
<h2>4.7.0-rc.0</h2>
<ul>
<li>package: add support for react/react-dom v19 as a peer
dependency</li>
<li>playground: update playground's React version to 19</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/eb120e66378471315620fe5339b73ba003f199ad"><code>eb120e6</code></a>
update package to 4.7.0 version</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/cdd070c9f080caf4a9a7b13c2c34fa4e10edc9bf"><code>cdd070c</code></a>
update snapshots</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/55a063e45d2f2672884b77059ac97850758764ae"><code>55a063e</code></a>
update <code>@​monaco-editor/loader</code> to the latest (v1.5.0)
version</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/52e8c75616e09730b7b1a0b5822385212a082ce8"><code>52e8c75</code></a>
update package to 4.7.0-rc.o version</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/e72be4edc1b4492eae9f7d85671ee61a43a6aee8"><code>e72be4e</code></a>
add react 19 to peerDependencies</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/642be903a9dd21d6fe639ab5c92c234dad77c813"><code>642be90</code></a>
update playground's react version to 19</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/ceee344fbe26285dabb0fe90985fe18ec867211c"><code>ceee344</code></a>
Add Monaco-React AI Bot in Readme (<a
href="https://redirect.github.com/suren-atoyan/monaco-react/issues/655">#655</a>)</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/f7cac39fbad0f062dc66458831aaf57a7126dd40"><code>f7cac39</code></a>
add electron blog post link</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/ea601cf9f6fe9f2cc0c6271d6a9cde9a332b6dc0"><code>ea601cf</code></a>
add tea constitution file</li>
<li><a
href="https://github.com/suren-atoyan/monaco-react/commit/3327f3c368cb6d56c02f2df8a9d45177ce6f52e9"><code>3327f3c</code></a>
add GitHub sponsor button</li>
<li>See full diff in <a
href="https://github.com/suren-atoyan/monaco-react/compare/v4.6.0...v4.7.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@monaco-editor/react&package-manager=npm_and_yarn&previous-version=4.6.0&new-version=4.7.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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abdullah <125115953+mabdullahabaid@users.noreply.github.com>
2025-12-29 20:01:05 +01:00
Abdullah. 1fcb8b464c fix: move vite plugins into the packages that use them (#16134)
I was looking into [Dependabot Alert
107](https://github.com/twentyhq/twenty/security/dependabot/107) and
figured that the alert is caused by `vite-plugin-dts`, which is a
development dependency and does not make it into the production build
for it to be dangerous.

However, while at it, I also saw that some packages used plugins from
root package.json while others had them defined in their local
package.json. Therefore, I refactored to move plugins where they're
required and removed a redundant package.

Builds for the following succeed as intended:
- twenty-ui
- twenty-emails
- twenty-website
- twenty-front

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-12-01 14:44:19 +00:00
Abdullah. 978c0acb90 fix: sentry's sensitive headers are leaked when sendDefaultPii is set to true (#16122)
Resolves [Dependabot Alert
323](https://github.com/twentyhq/twenty/security/dependabot/323),
[Dependabot Alert
324](https://github.com/twentyhq/twenty/security/dependabot/324) and
[Dependabot Alert
325](https://github.com/twentyhq/twenty/security/dependabot/325).

It updates Sentry's packages on the server from 10.21.0 to 10.27.0.

I also moved @sentry/react to twenty-front package.json and updated the
version from 9.26.0 to 10.27.0 - no breaking changes were introduced in
the major upgrade in regards to the API exposed by the dependency.

Since @sentry/profiling-node was redundant in the root package.json, I
removed it - twenty-server has it already and is the only package
dependent on @sentry/profiling-node.
2025-11-27 17:28:59 +05:00
Copilot a1bfab82df Remove VITE_DISABLE_ESLINT_CHECKER environment variable (#15943)
The `VITE_DISABLE_ESLINT_CHECKER` environment variable is removed from
the codebase. ESLint checker no longer runs during Vite builds
(equivalent to the previous `VITE_DISABLE_ESLINT_CHECKER=true`
behavior).

**Configuration**
- Removed from `.env.example` (active and commented lines)
- Removed from `vite.config.ts` destructuring and conditional logic
- Removed from build scripts in `package.json` and `nx.json`

**Code change in vite.config.ts:**
```diff
- if (VITE_DISABLE_ESLINT_CHECKER !== 'true') {
-   checkers['eslint'] = {
-     lintCommand: 'eslint ../../packages/twenty-front --max-warnings 0',
-     useFlatConfig: true,
-   };
- }
```

**Documentation**
- Updated main English troubleshooting guide to remove references to the
variable
- Translated documentation files are intentionally not modified and will
be handled by a separate workflow

> [!NOTE]
> ESLint will not run in the background via Vite's checker plugin.
Developers will need to run `npx nx lint twenty-front` manually or rely
on their IDE's ESLint extension for real-time feedback on open files.

Created from VS Code via the <a
href="https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github">GitHub
Pull Request</a> extension.

<!-- START COPILOT CODING AGENT SUFFIX -->



<details>

<summary>Original prompt</summary>

> Your job is to delete everything related to
VITE_DISABLE_ESLINT_CHECKER in the codebase.
> 
> We mention this env var in documentation: drop the content talking
about it.
> 
> We use it in the vite config: drop the check and keep the code paths
that used to run when `VITE_DISABLE_ESLINT_CHECKER=true`.
> 
> User has selected text in file packages/twenty-front/.env.example from
3:1 to 3:28


</details>

Created from VS Code via the [GitHub Pull
Request](https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github)
extension.

<!-- START COPILOT CODING AGENT TIPS -->
---

 Let Copilot coding agent [set things up for
you](https://github.com/twentyhq/twenty/issues/new?title=+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Devessier <29370468+Devessier@users.noreply.github.com>
2025-11-20 11:38:43 +01:00