Commit Graph

286 Commits

Author SHA1 Message Date
Abdullah. c7919673af fix: lift root postcss to 8.5.23 (Dependabot) (#23396)
## Summary

Clears the root postcss alert
[1851](https://github.com/twentyhq/twenty/security/dependabot/1851):
**GHSA-r28c-9q8g-f849** (high) - path traversal in previous source map
auto-loading (`sourceMappingURL`) leading to arbitrary `.map` file
disclosure, vulnerable `<= 8.5.17`.

The root lockfile carried **two** vulnerable copies, both behind exact
pins with no fixed upstream release:

| Copy | Pinner | Latest release still pins |
|---|---|---|
| 8.5.15 | `next` (8.4.31 exact) | 16.2.12 -> 8.4.31 |
| 8.5.14 | `@mintlify/common` (8.5.14 exact) | 1.0.1051 -> 8.5.14 |

So no parent upgrade reaches the fix. The existing `next/postcss`
resolution moves **8.5.15 -> 8.5.23** and a matching
**`@mintlify/common/postcss`** pin is added, placed alphabetically among
the other `@mintlify/*` entries. The caret consumers (`^8.4.38`,
`^8.4.47`, `^8.5.15`) dedupe onto the same version.

## Verification

- The two copies **collapse into a single `postcss@8.5.23` entry**;
nothing at or below 8.5.17 remains.
- `yarn install --immutable` passes.
- 8.5.23 published 2026-07-24, clears the 3-day npm age gate.
- `//resolutions` updated with the advisory, both pinners (and their
latest-version evidence) and the drop condition.

The app-lockfile side of this advisory shipped separately in #23340.
2026-07-28 08:06:23 +00:00
Paul Rastoin 24067ec87a chore: remove twenty-companion dead code (#23310)
## What

Removes `packages/twenty-companion` (package name `twenty-desktop`), the
Electron "Twenty Desktop" proof of concept that landed with the
Recall.ai call-recording work in #18281.

## Why it's dead code

- **Not in the nx graph** — no `project.json`, so no target ever runs
against it.
- **Not in CI** — no workflow references it. #21327 said as much when
bumping its Electron: "there's no CI job that builds/tests
twenty-companion, so this isn't exercised by CI".
- **No code references** — nothing imports it, and the only path
references were the root `workspaces` array, `yarn.lock`, and
`.vscode/twenty.code-workspace`. It talks to Twenty over the public REST
API from a separate process, so there is no coupling to remove.
- **Self-declared POC** — its README opens with "This application is a
Proof of Concept (POC) and must NOT be used in production. [...]
Security, stability, and performance have not been validated for
production use."
- **No feature work since it landed** (March 2026). Every commit
touching it since has been a dependency or tooling sweep: React 19
migration, ESLint→OxLint, npm→yarn workspaces, and four CVE bumps.
- **Docs already stale** — its README points at
`packages/twenty-apps/internal/call-recording`, which no longer exists.
The shipped app lives at `packages/twenty-apps/public/call-recorder` and
does not reference the desktop companion.

Meanwhile it pulled a full Electron + electron-forge toolchain into
every root install, and kept generating Dependabot noise against a tree
nothing builds.

## Changes

- Delete `packages/twenty-companion`.
- Drop its entry from root `workspaces` and from
`.vscode/twenty.code-workspace`.
- Drop four root `resolutions` that existed only to evict CVEs from the
Electron tree, along with their entries in the `//resolutions` rationale
doc:
  - `@electron/rebuild/tar`, `@electron/node-gyp/tar`
  - `@electron-forge/plugin-webpack/webpack-dev-server`
- `make-fetch-happen` — its only sub-`^15` consumer was the Electron
`node-gyp` fork; the remaining consumers (`@sigstore/sign`,
`npm-registry-fetch`, `tuf-js`) already declare `^15.x`
- Regenerate `yarn.lock`.

## Lockfile impact

469 descriptors removed, **zero version changes for any surviving
descriptor** (verified with a descriptor-level diff of old vs new
resolutions). Two descriptors show up as new —
`make-fetch-happen@npm:^15.0.1` and `@npm:^15.0.4` — only because the
global resolution was previously rewriting them; both still resolve to
`15.0.6`. Re-running resolution produces a byte-identical lockfile.

## Test plan

- [x] Repo-wide grep confirms no remaining references to
`twenty-companion` / `twenty-desktop` / the Electron toolchain.
- [x] `yarn install --mode=update-lockfile` is stable and idempotent
under hardened mode.
- [x] Descriptor-level lockfile diff shows no resolution changes outside
the removed tree.
- [ ] CI green (nothing targets the removed package, so the risk surface
is the lockfile).


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

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/23310?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-07-26 16:52:52 +00:00
Abdullah. 15f571837e fix: bump js-yaml pins 4.2.0 -> 4.3.0 (Dependabot) (#23178)
## Summary

Bumps all nine scoped **js-yaml resolutions 4.2.0 -> 4.3.0** and lifts
the caret copy, clearing Dependabot alert
[1768](https://github.com/twentyhq/twenty/security/dependabot/1768):
**GHSA-52cp-r559-cp3m / CVE-2026-59869** (high) - YAML merge-key chains
force quadratic CPU consumption, vulnerable `>= 4.0.0, < 4.3.0`, fixed
**4.3.0**. Follow-up to the merge-key DoS fixed in 4.2.0
(GHSA-h67p-54hq-rp68).

## Why the pins move (not drop)

Checked upstream first: all seven 4.1.1 exact-pinners are unchanged at
latest (`@mintlify/cli@4.0.1331`, `@mintlify/common@1.0.1037`,
`@mintlify/prebuild@1.0.1185`, `@mintlify/previewing@4.0.1254`,
`@mintlify/scraping@4.0.902`, `@mintlify/validation@0.1.795`,
`@verdaccio/config@8.1.2` - every one still pins `js-yaml 4.1.1` exact).
front-matter and @istanbuljs/load-nyc-config remain EOL on `^3.13.1`. So
no parent upgrade carries 4.3.0; the existing scoped pins just move up,
plus a recursive `yarn up` for the cosmiconfig caret consumers. The
`//resolutions` doc entry is updated with the new advisory and drop
condition (`>=4.3.0`).

## Verification

- Single `js-yaml 4.3.0` entry remains in the lockfile (no 4.2.0, no
3.x).
- `yarn install --immutable` passes.
- front-matter patch intact (`loader = parser.load`); docs front-matter
parses cleanly on 4.3.0.
- `mintlify validate` reports only pre-existing ChartIcon MDX import
warnings from #23091 (content, unrelated - zero `.mdx` files in this
diff).
- 4.3.0 published 2026-06-26, clears the 3-day age gate.
2026-07-23 17:24:05 +05:00
Abdul Rahman ba8e1bf5a3 chore(docs): self-clean orphans and surface failed languages in i18n … (#22278)
## Summary
Two robustness fixes to `docs-i18n-pull.yaml` so localized docs can't
silently drift:

1. **Prune orphan localized files.** The pull only adds/updates files,
never deletes — so localized copies of renamed/moved/deleted English
pages linger and serve dead URLs (recently ~113 of them). A new
`prune-orphan-translations` script (run with `--apply` in the workflow,
on real pulls only) removes any `l/<lang>/**` file whose English source
no longer exists.
2. **Surface per-language download failures.** The loop previously
swallowed failures with `|| echo "Warning..."`, so a language whose
Crowdin server-side build fails (e.g. `ja`, failing at 79%) was skipped
*silently* and froze indefinitely while every other language updated. We
now collect failures, still commit the languages that succeeded, and
**fail the run at the end** so a broken language is visible.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 04:40:55 +05:30
Abdullah. be8102c4a4 fix: evict js-yaml 3.x via front-matter patch + scoped resolutions (#22312)
## Summary

Closes the last open Dependabot alert on `main` — [alert
1504](https://github.com/twentyhq/twenty/security/dependabot/1504)
(GHSA-h67p-54hq-rp68 / CVE-2026-53550, js-yaml merge-key
quadratic-complexity DoS; medium, dev scope).

The 4.x js-yaml copies are already pinned to 4.2.0 (the seven
`@mintlify/*` + `@verdaccio/config` resolutions). The remaining
vulnerable copy was **js-yaml 3.14.2**, held by two `^3.13.1` consumers
with no fixed upstream release:
- `@istanbuljs/load-nyc-config@1.1.0` (jest coverage)
- `front-matter@4.0.2` (mintlify docs tooling — EOL, latest is 4.0.2)

## Approach

Both are forced to **js-yaml 4.2.0** via scoped resolutions, which
evicts the 3.x copy entirely:

```jsonc
"front-matter/js-yaml": "4.2.0",
"@istanbuljs/load-nyc-config/js-yaml": "4.2.0",
```

- **load-nyc-config** already calls `yaml.load` (present +
safe-by-default in 4.x), so its pin alone works.
- **front-matter** crashed on js-yaml 4.x because its default loader
called the removed `safeLoad`, so it's also **patched**
(`.yarn/patches/front-matter-npm-4.0.2-e1cc0efa69.patch`):

  ```diff
  -  var loader = allowUnsafe ? parser.load : parser.safeLoad
  +  var loader = parser.load
  ```

On 4.x `load` is already safe-by-default and there's no full/unsafe
schema, so the `allowUnsafe` ternary is dead.

**Why the version move is a separate resolution, not folded into the
patch:** a `yarn patch` only rewrites a package's *files* — it does
**not** change the resolved dependency graph. Bumping js-yaml inside the
patched `package.json` is ignored by resolution (verified:
front-matter@patch still pulled 3.14.2 until the explicit pin was
added). This is the repo's first *transitive* patch; like every other
transitive override it lives in root `resolutions`. Documented in the
`//resolutions` note.

## Verification

- js-yaml 3.x **fully evicted** — the tree resolves js-yaml to **4.2.0
only** (no `^3.13.1` descriptor remains).
- `yarn install --immutable` passes.
- front-matter parses real docs front-matter correctly on 4.2.0 (unit
smoke test).
- **`mintlify validate` passes** — the docs toolchain builds with the
patched front-matter.
2026-06-29 20:14:17 +05:00
Abdullah. 20ac0a52bf fix(deps): scope js-yaml to 4.2.0 under the mintlify/verdaccio pinners (#22078)
## Summary

Resolves [Dependabot alert
#1504](https://github.com/twentyhq/twenty/security/dependabot/1504) —
js-yaml **CVE-2026-53550 / GHSA-h67p-54hq-rp68** (quadratic-complexity
DoS in YAML merge-key handling, vulnerable `<=4.1.1`, fixed `4.2.0`) —
by lifting the vulnerable **js-yaml 4.1.1 → 4.2.0**.

## Why scoped resolutions (not a global pin)

- js-yaml 4.1.1 is held alive by **7 packages that hard-pin it exact**
(no caret, still 4.1.1 in their latest):
`@mintlify/{cli,common,prebuild,previewing,scraping,validation}` +
`@verdaccio/config`. No parent upgrade carries the fix, so each is
scoped to 4.2.0 — matching the repo's `parent/child` convention.
- The 5 alert paths (`@graphql-codegen/cli`, `@lingui/cli`,
`@lingui/vite-plugin`, `@wyw-in-js/vite`, `vite-plugin-svgr`) only
*shared* that 4.1.1 via `cosmiconfig` (`^4.1.0`) — once the exact pins
are lifted, they **dedupe onto 4.2.0 on their own**.
- Forcing 4.1.1 → 4.2.0 is a **safe minor** (same 4.x `.load` API; the
fix just bounds merge-key complexity).

## The js-yaml 3.x remnant (deliberately left)

`front-matter@4.0.2` (via mintlify) and
`@istanbuljs/load-nyc-config@1.1.0` (via storybook coverage) declare
`js-yaml ^3.13.1 → 3.14.2`. **front-matter calls the `safeLoad` API that
js-yaml 4.x removed**, so it cannot take 4.2.0 — a global pin would
break it (which is why this is scoped). That 3.x copy is left in place;
both parse only **first-party trusted YAML** (nycrc + docs
front-matter), so the merge-key DoS isn't reachable. If Dependabot still
flags that 3.x copy, it's a dismiss candidate (no safe transitive fix —
front-matter is EOL on the `safeLoad` API).

## Verification

- `yarn install --immutable` passes.
- No `js-yaml@4.1.1` remains; js-yaml is now `4.2.0` (+ the documented
`3.14.2` remnant).
- Diff is js-yaml-only; matching `"//resolutions"` doc entry included.
2026-06-24 18:24:00 +05:00
Abdullah. b7cd6db458 fix(deps): resolve qs to 6.15.2 (dedupe caret group + scope body-parser) (#22050)
## Summary

Closes [Dependabot alert
#1305](https://github.com/twentyhq/twenty/security/dependabot/1305) — qs
**CVE-2026-8723 / GHSA-q8mj-m7cp-5q26** (vulnerable `>=6.11.1 <=6.15.1`,
fixed `6.15.2`) — via two changes:

1. **`yarn dedupe qs`** collapses the caret-range consumers (gitbeaker,
formidable, superagent, googleapis-common, union, body-parser@2.2.2)
from `6.15.0` onto the `6.15.2` already in the tree. Clean, no
resolution.
2. A scoped **`body-parser/qs: 6.15.2`** resolution for the lone
tilde-pinned holdout.

## Why the one resolution

- After the dedupe, the only vulnerable qs left was `6.14.2`, from
**`body-parser@1.20.4`** which declares `qs ~6.14.0` (capped at 6.14.x).
- body-parser **2.x** uses `qs ^6.15.2`, but that needs **express 5** —
and the `body-parser@1.20.4` here comes from **express 4.22.x**, pulled
by `@mintlify/previewing` + verdaccio (build/dev tooling, not bumpable
to express 5).
- So a scoped `body-parser/qs: 6.15.2` is the right fix — qs `6.14 →
6.15` is a compatible minor. It's grouped with the existing `express/qs`
+ `@cypress/request/qs` entries (same CVE, same express-4.x root cause)
in both the `resolutions` block and the `"//resolutions"` doc.

## Verification

- `yarn install --immutable` passes.
- No qs in `[6.11.1, 6.15.1]` remains — all qs is now `6.15.2`.
- `qs` is build/dev tooling here (mintlify, verdaccio, gitbeaker, etc.),
not the production server runtime.
2026-06-24 08:51:19 +02:00
Abdullah. 11218561d0 fix(deps): pin form-data under nx and zapier-platform-core to 4.0.6 (#22023)
## Summary

Adds two scoped `resolutions` (`nx/form-data` +
`zapier-platform-core/form-data` → `4.0.6`) forcing the lone vulnerable
`form-data@4.0.5` up to the patched `4.0.6`, resolving [Dependabot alert
#1506](https://github.com/twentyhq/twenty/security/dependabot/1506) —
CVE-2026-12143 / GHSA-hmw2-7cc7-3qxx (CRLF injection via unescaped
multipart field names/filenames, vulnerable `>=4.0.0 <4.0.6`).

## Why scoped resolutions (not a parent-bump)

- `form-data@4.0.5` is pinned **exactly** by `nx@22.7.5` (root devDep)
and `zapier-platform-core@19.0.0` (twenty-zapier) — and **both still pin
4.0.5 in their latest release**, so no parent upgrade carries the fix.
- Every *other* form-data consumer already resolves `4.0.6` naturally
via its `^4.0.x` range, so the two scoped pins simply **dedupe**
nx/zapier's copy onto that existing 4.0.6 — no new copy introduced.
- Scoped, not global, to match the existing `express/qs` +
`@cypress/request/qs` two-entry pattern (only form-data 4.x is in the
tree).

## Changes

- `package.json`: the two `resolutions` entries **plus** a matching
`"//resolutions"` doc entry (advisory, why-no-parent-bump, scope
rationale, drop condition).

## Verification

- `yarn install --immutable` passes.
- No form-data in `[4.0.0, 4.0.6)` remains in `yarn.lock`.
2026-06-23 19:40:54 +05:00
Abdullah. 558f2509c2 fix(deps): pin undici under @module-federation/dts-plugin to ^7.28.0 (#22014)
## Summary

Adds a **scoped** `resolutions` entry pinning `undici` under
`@module-federation/dts-plugin` to `^7.28.0`, resolving **6 Dependabot
alerts** — #1523 & #1566 (high), #1522 & #1570 (medium), #1565 & #1572
(low); all `undici >=7.0.0 <7.28.0`.

## Why a scoped resolution (not a parent-bump or a global pin)

- The vulnerable `undici@7.24.7` is pinned **exactly** by the transitive
build tool `@module-federation/dts-plugin@2.5.1`. There's no parent to
bump — its parents pin it and it doesn't loosen the pin at latest — so a
committed scoped resolution (matching the existing `@nestjs/graphql/ws`,
`express/qs` pattern) is the right fix.
- A **global** `undici` resolution would be wrong: the tree also has
`undici@6.27.0` (`^6.25.0`, outside the advisory) and the latest undici
is `8.5.0`, so forcing all undici to 7.x would break the 6.x consumer.
- `^7.28.0` resolves to `7.28.0` (highest 7.x), which **dedupes** with
the `undici@7.28.0` already in the tree (via `^7.25.0`) — no new copy is
introduced.

## Result

- `undici@7.24.7` is gone; the only undici 7.x is now `7.28.0`.
`undici@6.27.0` (6.x) is untouched.
- Build-tooling dependency (module-federation type generation) — not in
the production server runtime; `undici 7.24 → 7.28` is a compatible
minor bump.

## Verification

- `yarn install --immutable` passes (lockfile consistent with CI).
- No undici in `[7.0.0, 7.28.0)` remains in `yarn.lock`.
2026-06-23 15:27:12 +02:00
Charles Bochet a884945aca fix(deps): remediate HIGH image vulns (multer, ws, nodemailer) (#21984)
## What

Clears the HIGH-severity AWS Inspector findings on the `twenty-server`
container image. All three have stable, in-range fixes — no prereleases.

| Package | From → To | CVE | Path |
|---------|-----------|-----|------|
| multer | 2.1.1 → **2.2.0** (resolution) | CVE-2026-5038, CVE-2026-5079
(DoS) | transitive via `@nestjs/platform-express` |
| ws | 8.20.1 → **8.21.0** (resolution) | CVE-2026-48779 | pinned by
`@nestjs/graphql` (8.21.0 already in tree) |
| nodemailer | 8.0.10 → **9.0.1** | GHSA-p6gq-j5cr-w38f | nested in
`imapflow`; bumped `imapflow` 1.3.6 → 1.4.2 which depends on nodemailer
9.0.1 |

## Notes

- **multer 2.2.0 is the stable fix.** The advisories
([CVE-2026-5038](https://advisories.gitlab.com/npm/multer/CVE-2026-5038/),
[CVE-2026-5079](https://advisories.gitlab.com/npm/multer/CVE-2026-5079/))
list both `2.2.0` and `3.0.0-alpha.2` as fixed; Inspector reported only
the `3.0.0-alpha.2` prerelease, but we stay on the stable 2.x line.
- **nodemailer:** the top-level dep was already `^9.0.1`; only
`imapflow`'s nested copy was stale. imapflow 1.4.0 still ships
nodemailer 8.0.10 and 1.4.1 ships 9.0.0 (< the 9.0.1 fix), so **1.4.2 is
the minimum** that pulls the patched nodemailer.
- Lockfile-only resolution for multer/ws (they're transitive); imapflow
is a direct dep bump. yarn.lock net-shrinks from deduping.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21984?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-23 00:54:46 +02:00
Abdullah. 6ae2170744 chore(deps): bump wrangler to 4.102.0 and drop the wrangler/esbuild resolution (#21930)
## chore(deps): bump wrangler to 4.102.0 and drop the `wrangler/esbuild`
resolution

Removes a now-redundant `resolutions` override (resolution **cleanup**,
identified by the resolutions audit). It does not close a Dependabot
alert — esbuild stays at `0.28.1` either way — but reduces the standing
override count by one, per the `//resolutions` policy of dropping each
entry once its parent ships a fixed range.

### What

The `wrangler/esbuild: 0.28.1` resolution existed because `wrangler`
exact-pinned a vulnerable esbuild (`0.27.3`). **wrangler 4.102.0 now
ships esbuild `0.28.1` natively**, and our workspaces declare `wrangler
^4.0.0`, so it resolves to the safe version on its own.

### How — parent-bump, then drop the override

- Bumped `wrangler` within `^4.0.0` to `4.102.0` (lockfile-only).
- Removed the `wrangler/esbuild` entry from `resolutions`.
- Updated the `//resolutions` doc: moved wrangler to the "fixed by
parent-bump" list and decremented the esbuild counts (seven → six
resolutions; six → five exact-pin parents).

### Verification

- No `esbuild 0.27.3` regression (wrangler 4.102.0 pins `0.28.1`); the
remaining six esbuild resolutions are unchanged.
- `//resolutions` doc is consistent with the `resolutions` object.
- Lockfile + package.json only; `yarn install --immutable` passes.
2026-06-22 10:26:15 +02:00
Abdullah. 569d887d1e [Website] Cut over to the rebuilt site (#21825)
Renaming the package so any further PRs directed to the website are
targeted to the reworked code instead of diverging. Once merged, I will
start preparing this for deployment to dev to test before releasing to
prod. Any improvements will also be applied to this package.

I avoided making significant changes to API routes so nothing breaks,
but will test it thoroughly today to confirm. That said, everything is
ported - double checked.

Big diff PR, impossible to review, but last one! No more rebuilds.
2026-06-19 10:22:46 +02:00
Abdullah. ba7b435885 fix(security): bump webpack-dev-server resolution to 5.2.5 (HMR WS interception) (#21818)
## fix(security): bump webpack-dev-server resolution to 5.2.5 (HMR WS
interception)

Resolves [Dependabot Alert
#1514](https://github.com/twentyhq/twenty/security/dependabot/1514).

### What

`webpack-dev-server` `< 5.2.5` is affected by
[GHSA-mx8g-39q3-5c79](https://github.com/advisories/GHSA-mx8g-39q3-5c79)
(**Moderate**) — HMR WebSocket interception via permissive user proxies.
Patched in `5.2.5`.

### How

`webpack-dev-server` is already force-resolved via a scoped
`resolutions` entry: its sole consumer `@electron-forge/plugin-webpack`
(latest 7.11.2 / 8.x alphas) still declares `webpack-dev-server ^4`, so
the resolution evicts the vulnerable 4.x line up to 5.x. The
newly-disclosed CVE affects the pinned `5.2.4`, so this **bumps the
existing scoped resolution `5.2.4 -> 5.2.5`** and updates its
`//resolutions` doc line — extending an already-documented, load-bearing
entry rather than adding a new one.

**Still-required check:** `@electron-forge/plugin-webpack` still
declares `^4`, so the resolution remains necessary (removing it would
regress to vulnerable 4.x).

### Verification

- `webpack-dev-server` resolves to a single `5.2.5` bucket; no `< 5.2.5`
remains.
- Not imported in our source (electron-forge build tooling only).
- `yarn install --immutable` passes.

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-06-19 07:17:23 +00:00
Abdullah. bebe03e453 fix(security): bump tar to 7.5.16 across lockfiles (PAX file smuggling) (#21813)
## fix(security): bump tar to 7.5.16 across lockfiles (PAX file
smuggling)

Resolves [#1472 1474 1476 1479 1481 1483 1485 1487 1489 1491 1493 1496
1498 1505](https://github.com/twentyhq/twenty/security/dependabot/1472
1474 1476 1479 1481 1483 1485 1487 1489 1491 1493 1496 1498 1505).

### What

`tar` (`node-tar`) `<= 7.5.15` applies a PAX size override to
intermediary GNU long-name/long-link headers, causing a tar-parser
interpretation differential (file smuggling). Patched in `7.5.16`.

### Why these alerts

The advisory is scanned across many independent Yarn projects, so it
surfaced as one alert per lockfile: the root `yarn.lock` plus 13
`packages/twenty-apps/**` lockfiles (each pulls `tar` transitively).

### How

- Refreshed `tar` to `7.5.16` in the root and all 13 app lockfiles —
they hold `tar` via `^7.5.x` ranges that already permit it, so this is
an in-range lockfile refresh (no override) via `yarn up -R tar`.
- The root additionally had `tar@7.5.15` exact-pinned by
`@mintlify/previewing`, which has **no upstream fix** (latest `4.0.1163`
still pins `7.5.15`). Added a scoped resolution
`@mintlify/previewing/tar -> ^7.5.16`, **extending the existing scoped
tar resolutions** already used for `@electron/rebuild` and
`@electron/node-gyp`.

### Not included

`seed-dependencies/yarn.lock` (alert #1500) is intentionally excluded:
that lockfile and its checksum constants are already modified by the
open form-data PR, so its `tar` bump will follow separately to avoid a
conflict.

### Verification

- No `tar <= 7.5.15` remains across the root or any app lockfile.
- `yarn install --immutable` passes.
2026-06-19 08:49:07 +02:00
Abdullah. 465eb05aaf Reworked website. (#21763)
twenty-website had accumulated structural problems that were cheaper to
fix by rebuilding than to refactor in place:
  
- Drift had no guardrails. Values were matched at call sites instead of
single-sourced, so things silently diverged — e.g. the radius token base
was wrong for days (every radius() consumer rendered double) because
nothing measured it against the old site's CSS variables.
- A whole tree escaped quality checks. src/lib/ (~9.8k lines) was never
format-checked, because oxfmt silently ignores directories named lib/.
- Inconsistent rhythm. Hero spacing varied 24–88px between pages
(CEO-flagged), because section spacing wasn't a token.
- Over-extraction. -config.ts sprawl pulled single-component
configuration out into the wrong place.
  
The goal: a ground-up rebuild where drift is structurally impossible,
held to a Linear / Railway / Notion / Attio quality bar. The old site is
treated as source of intent only — nothing is blindly ported; every
piece is re-decided and A/B-verified.

**Rebuild**
  
A full rebuild on Next 16 + Turbopack + Linaria (zero-runtime CSS),
~1,100 files. Marketing pages (home, product, pricing, partners +
marketplace, customers/case-studies, why-twenty, releases, legal), the
interactive AppPreview product mockup, the platform/visuals WebGL system
(engine + rigs, three code-split off every initial chunk), and the
standalone /halftone studio (the dev tool that generates the site's
halftone art — engine, exporters, and full UI ported as an isolated
island).
  
**Architecture & guarantees**
  
- Parity by construction. src/tokens/definitions.ts is the only file
with raw values; the :root CSS-variable block is generated from it at
build time and accessors derive var names through the same helpers —
derived alpha tokens appear in served CSS without ever being
hand-written.
- Mobile-first by API shape. mediaUp() is the only media helper (no
max-width helper exists, on purpose).
- Section rhythm is a token (RHYTHM.section) — the hero-spacing
inconsistency class is fixed by construction.
- Fluid type ramps interpolate font-size and line-height between
designed endpoints [390px → md]; TYPE_SCALE is the single source.
- three.js never enters an initial chunk — confined to platform/visuals
heavy zones, reached only via dynamic(ssr:false), enforced by
check-visual-bundle.
2026-06-18 11:55:24 +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 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 a84a4c1ab7 fix(server): load integration jest config transpile-only; drop tsx pin (#21563)
## Context

Follow-up to [#21559](https://github.com/twentyhq/twenty/pull/21559)
(the esbuild 0.28.1 security bump). That PR had to pin `tsx` to `4.21.0`
to avoid a CI-only `server-integration-test` failure. This removes the
need for that pin by fixing the root cause.

## Root cause

The integration-test command boots jest with `NODE_OPTIONS="--import
tsx/esm"`, while jest *also* compiles `jest-integration.config.ts` with
**ts-node, type-checking on**. Two TypeScript transformers run over the
same file:

- tsx's loader transpiles `node-environment.interface.ts` via esbuild,
downleveling the enum to `var NodeEnvironment = (…)(NodeEnvironment ||
{})`.
- jest's ts-node then *type-checks that downleveled output* and rejects
it with `TS7022: 'NodeEnvironment' … referenced directly or indirectly
in its own initializer`.

It's not a real type error and not esbuild's fault — esbuild's output is
valid JS, just not valid TS to re-type-check. It only surfaced once
`tsx` resolved to `4.22.x` (whose loader feeds that output into
ts-node), which is why #21559 pinned tsx to 4.21.0.

Verified in isolation: ts-node type-checking esbuild's downleveled enum
→ `TS7022`; the same under `transpileOnly`/`TS_NODE_TRANSPILE_ONLY=true`
→ clean.

## Fix

Run the integration jest config **transpile-only**
(`TS_NODE_TRANSPILE_ONLY=true` on the `test:integration` target, base +
`with-db-reset`). The config file doesn't need type-checking at boot,
and jest's ts-node now emits JS without re-type-checking esbuild's
output — eliminating the whole class of tsx/esbuild-downleveling
sensitivity.

With the collision gone, drop the workaround from the root
`package.json`:
- removed the `tsx: 4.21.0` resolution
- removed the `tsx/esbuild: 0.28.1` resolution

`tsx`'s `^4.x` ranges now resolve to **4.22.4**, which pins esbuild
`~0.28.0` → **0.28.1** on its own, so esbuild stays 0.28.1 across the
lockfile with no resolution. The `//resolutions` doc block is updated
accordingly.

## Verification

- `yarn install` clean; lockfile has only esbuild 0.28.1; tsx resolves
to 4.22.4.
- `jest --config ./jest-integration.config.ts --listTests` with tsx
4.22.4 + `TS_NODE_TRANSPILE_ONLY=true` loads the config and lists all
420 suites.
- CI `server-integration-test` is the real validator (the failure was
CI-only).

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21563?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 23:34:21 +02:00
Charles Bochet fa80eb68b3 fix(deps): upgrade esbuild to 0.28.1 (GHSA-gv7w-rqvm-qjhr) (#21559)
## Context

Clears [Dependabot alert
#1469](https://github.com/twentyhq/twenty/security/dependabot/1469) —
esbuild Deno-module binary-integrity RCE (`GHSA-gv7w-rqvm-qjhr`,
vulnerable `>=0.17.0 <0.28.1`, fixed in `0.28.1`).

The advisory's range is much wider than the previous esbuild one
(`>=0.27.3`), so it re-exposed several older transitive esbuild copies
in the tree.

## Approach

Prefer upgrading the parent over adding a resolution; resolutions only
where the latest upstream release still pins a vulnerable esbuild
**outside** the `0.28.1` range (so an upgrade can't help).

**Upgraded parent (no resolution needed):**
- `tsx` → `^4.22.4` across all workspaces (its `~0.28.0` esbuild now
resolves to 0.28.1)
- `size-limit` / `@size-limit/preset-small-lib` → `^12.1.0` in
`twenty-ui` (v12 pins esbuild `^0.28.0`)

**Resolutions added** (verified against npm — latest still pins
vulnerable esbuild):
- `@opennextjs/aws` (exact-pins 0.25.4, still 0.25.4 in latest 4.0.3)
- `@lingui/cli` (`^0.25.1`, caps `<0.26`, unchanged in latest 6.3.0)
- `storybook` (range tops at `^0.27.0`, caps `<0.28`, unchanged in
latest 10.4.4)
- `zapier-platform-cli` (exact-pins 0.25.8, latest)

The three existing esbuild resolutions (`wrangler`, `@react-email/ui`,
`react-email`) remain. The `//resolutions` doc in `package.json` and the
`.yarnrc.yml` age-gate comment were updated to cover both advisories.

## Result

Every esbuild copy in `yarn.lock` now resolves to a single `0.28.1`
entry — no version `<0.28.1` remains. Lockfile change is a net reduction
(dropped duplicate esbuild trees + their `@esbuild/*` platform
binaries); no unrelated deps bumped. `yarn install` passes with
constraint checks enabled.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21559?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 22:29:11 +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 4614fe963c fix(deps): bump esbuild to 0.28.1 to fix GHSA-g7r4-m6w7-qqqr (#21515)
## Summary

Fixes Dependabot alert
[#1438](https://github.com/twentyhq/twenty/security/dependabot/1438) —
**esbuild dev-server path traversal**
([GHSA-g7r4-m6w7-qqqr](https://github.com/advisories/GHSA-g7r4-m6w7-qqqr),
CWE-22, low severity, Windows-only). Vulnerable range `>= 0.27.3, <
0.28.1`; patched in `0.28.1`.

Two vulnerable transitive `esbuild` copies were present in the lockfile:

| Version | Parent | Notes |
|---|---|---|
| `0.27.3` | `wrangler@4.98.0` (twenty-website) | exact-pinned;
**latest** wrangler `4.100.0` *still* pins `0.27.3` |
| `0.28.0` | `@react-email/ui@6.5.0`, `react-email@6.5.0`,
`twenty-client-sdk` (twenty-emails / our SDK) | `@react-email/ui`
exact-pins it; **latest** `6.6.0` still does |

Because no fixed upstream release exists for these parents, bumping them
can't reach `0.28.1`.

## Changes

- **`package.json`** — scoped `resolutions` forcing `esbuild` to
`0.28.1` for `wrangler`, `@react-email/ui`, and `react-email`.
Documented in the existing `//resolutions` ledger.
- **`packages/twenty-client-sdk/package.json`** — raised the `esbuild`
floor `^0.28.0` → `^0.28.1` at the source. `esbuild` is a runtime
`dependency` of the SDK, so fixing it here (rather than via a root
resolution) also protects consumers of the published package.
- **`.yarnrc.yml`** — `0.28.1` was published 2026-06-11, inside the
`npmMinimalAgeGate: 3d` window, so it's quarantined. Preapproved
`esbuild@0.28.1` + `@esbuild/*@0.28.1` (scoped to this exact version) so
the security fix can land now instead of waiting out the gate. Safe to
remove once `0.28.1` ages past the gate.
- **`yarn.lock`** — regenerated.

## Verification

- No vulnerable esbuild left in the lockfile — remaining versions are
`0.25.4`, `0.25.8`, `0.25.12`, `0.27.2`, `0.28.1`, all outside `>=
0.27.3, < 0.28.1`.
- `yarn install --immutable` passes (no quarantine errors, clean link
step).

## Follow-up

The scoped resolutions are load-bearing only until upstreams ship an
esbuild `>= 0.28.1` pin; the `react-email` one can also drop once
`0.28.1` clears the age gate. All noted in the `//resolutions` ledger.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21515?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-12 23:26:22 +02:00
Charles Bochet 503c689f37 security: upgrade typeorm to 0.3.26 (CVE-2025-60542) (#21456)
## Context

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

## Changes

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

## Why we're confident this time

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

## Verification

- `npx nx typecheck twenty-server` — clean
- Full `twenty-server` unit suite — green (5651 passed)
- `group-by-resolver` integration suite — 19/19 on a fresh 0.3.26-seeded
test DB
- Postcard app-sync stress loop — 12/12 on this exact stack
- Lockfile: typeorm 0.3.26 + new `sql-highlight` dep, `esbuild`/uuid
entries untouched
2026-06-11 16:41:22 +02:00
Charles Bochet 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 166f7ee0d2 chore(deps): prune yarn resolutions down to load-bearing entries (#21446)
## Context

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

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

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

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

## Removed — replaced by a parent upgrade

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

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

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

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

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

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

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

## Follow-ups (separate PRs)

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

## Verification

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

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

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

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

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

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

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

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

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

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

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

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

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

### Verification
- Every postcss now resolves `>= 8.5.14` (safe); `yarn install
--immutable` ✓.
- postcss is build-time and **CI doesn't build twenty-website on regular
PRs**, so verified locally: **twenty-website** (Next production build) ✓
and **twenty-front-component-renderer** ✓.
2026-06-11 11:19:50 +02:00
Charles Bochet 2da28cb03e security: upgrade express 4.22.2 + qs 6.15.2 resolution for dev-tool holdouts (Dependabot alert 1305) (#21434)
Closes the qs Dependabot alert —
[1305](https://github.com/twentyhq/twenty/security/dependabot/1305) — by
**upgrading express where possible** and using a **documented qs
resolution** only for the irreducible dev-only holdouts.

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

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

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

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

### Verification
- `yarn install --immutable` ✓; every `qs` resolves to `6.15.2`; express
app/tooling on `4.22.2` (only verdaccio/mintlify remain on old express,
neutralized by the resolution).
- `twenty-server` typecheck ✓ (90 files import express types;
4.22.1→4.22.2 is a patch).
- Non-exploitable in prod regardless (express/body-parser use
`qs.parse`, not the vulnerable `stringify`).
2026-06-11 10:46:04 +02:00
Charles Bochet 9100fb1e9f security: scoped resolution for webpack-dev-server 5.2.4 (Dependabot alerts 1237/691/692) (#21420)
Closes 3 webpack-dev-server Dependabot alerts —
[1237](https://github.com/twentyhq/twenty/security/dependabot/1237),
[691](https://github.com/twentyhq/twenty/security/dependabot/691),
[692](https://github.com/twentyhq/twenty/security/dependabot/692) — with
a **scoped** resolution:
`@electron-forge/plugin-webpack/webpack-dev-server: 5.2.4`.

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

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

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

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

### Scope / verification
- `yarn install --immutable` ✓; webpack-dev-server resolves to 5.2.4
only (was 4.15.2), no vulnerable copy remains.
- Only exercised by `electron-forge start` (dev HMR); production
`make`/`package` builds don't use it, and **twenty-companion has no CI
workflow**, so this can't affect CI.
- Residual manual check (not CI-covered): `yarn start:electron` in
twenty-companion still boots the dev server.
2026-06-11 09:38:16 +02:00
Charles Bochet 09cc0c6f21 security: clear yeoman-environment High alert via resolution to 6.0.1 (#21400)
## What

Clears the `yeoman-environment` High alert (GHSA-vv9j-gjw2-j8wp —
*arbitrary package install without confirmation*).

`yeoman-environment@4.4.3` is exact-pinned by `zapier-platform-cli`.
**There is no parent-bump fix**: `zapier-platform-cli@19.0.0` is the
latest stable and still pins 4.4.3 — cli 17→3.19.3, 18/19→4.4.3, all in
the vulnerable `< 6.0.1` range.

## Why a resolution (and why it's safe for us)

zapier-cli **lazy-loads** `yeoman-environment` via dynamic `import()`
*only* inside its `init` and `pull` scaffolding command handlers.
twenty-zapier only ever runs `validate` / `versions` / `push` /
`promote` (see `project.json`), so the vulnerable code path is never
imported here.

Since no zapier-cli release carries the fix, the only way to remove the
vulnerable version is a resolution:

```jsonc
"yeoman-environment": "6.0.1"
```

The 4→6 major only affects zapier-cli's `init`/`pull` (which we never
invoke); all our commands are unaffected.

## Verification
- `yeoman-environment` now **6.0.1** (no 4.4.3 in the lockfile)
- `nx build` + `typecheck` twenty-zapier 
- `zapier-platform validate` → **35/35 checks pass** with yeoman 6
forced
- `yarn install --immutable` clean
2026-06-10 13:35:28 +02:00
Charles Bochet e53f877559 security: clear picomatch High alert via @angular-devkit/core resolution (#21398)
## What

Clears the root `picomatch` High alert (GHSA-c2c7-rcm5-vvqj, range
`>=4.0.0 <4.0.4`).

`picomatch@4.0.2` is exact-pinned by `@angular-devkit/core@19.2.x`,
pulled by NestJS's codegen tooling (`@nestjs/schematics` + `@nestjs/cli`
use Angular's schematics engine). angular-devkit/core backported the
picomatch 4.0.4 fix in **19.2.24**.

## Why a resolution here (not a parent bump)

The clean parent-bump — bumping `@nestjs/cli` so it pulls patched
angular-devkit — **breaks `nest build`**. `@nestjs/cli` 11.0.17+ has an
SWC-builder output-path change: it writes compiled files under
`dist/`**`src/`**`…` instead of `dist/…`, breaking every `node
dist/<path>` reference (`main`, `command`, worker,
`database/scripts/*`). This is what failed in the first revision of this
PR (`Cannot find module '…/dist/database/scripts/truncate-db.js'`).

- The cli's angular-devkit pin is **exact**, so there's no clean
refresh.
- Every `@nestjs/cli` ≥11.0.17 (incl. the latest 11.0.23) has the
regression.
- There's no stable NestJS 12/13 to move to (12 is alpha-only).
- `tsconfig` `rootDir` doesn't override the output base.

So a one-patch resolution is genuinely the cleaner, lower-risk fix:

```jsonc
"@angular-devkit/core": "19.2.24"   // patch within the same 19.2 minor
```

`@nestjs/cli` stays 11.0.16 (correct `dist/` layout), and picomatch
resolves to 4.0.4.

## Verification
- picomatch now **4.0.4 + 2.3.2** (both patched); no 4.0.2 in the
lockfile
- `nx build twenty-server` emits `dist/main.js` and
`dist/database/scripts/*.js` at the correct paths (the prior CI failure)
- `yarn install --immutable` clean
2026-06-10 13:22:05 +02:00
Charles Bochet 3ee82c7a3c security: clear koa High alert by bumping nx 22.5.4 → 22.7.5 (#21396)
## What

Clears the High `koa` alert (GHSA-7gcc-r8m5-44qm) — via a parent bump,
**no resolution**.

`koa@3.0.3` was a deep transitive of the module-federation build
tooling:
`koa` ← `@module-federation/dts-plugin@0.21.4` ←
`@module-federation/enhanced@0.21.4`, pulled via **two** paths —
`@nx/module-federation@22.5.4` (directly) and `@module-federation/node`
(pinning the old `enhanced@0.21.x` line).

`@module-federation/dts-plugin` 2.x dropped koa, so the fix moves both
paths onto the 2.x line:

- bump `nx` + `@nx/{jest,js,react,storybook,vite,web}` **22.5.4 →
22.7.5** (minor): `@nx/module-federation@22.7.5` uses
`@module-federation/enhanced@^2.3.3`
- refresh `@module-federation/node` within its existing `^2.7.21` range
→ 2.7.44, which uses `@module-federation/enhanced@2.5.1`

Result: `@module-federation/enhanced` + `dts-plugin` collapse to 2.5.1,
and **koa is gone from the tree entirely** (net −309 lockfile lines
after dedup).

## Verification (nx is the monorepo task runner — verified broadly)
- `nx build` + `typecheck`: twenty-shared, twenty-ui, twenty-front 
- `nx typecheck twenty-server` 
- `nx test twenty-shared` 
- `yarn install --immutable` clean

The only `package.json` change is the nx version bump; everything else
is lockfile.
2026-06-10 11:44:03 +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 1e309369bc chore(deps): upgrade tar to v7, evict vulnerable tar@6.2.1 (CVE-2026-24842) (#21341)
## Summary

Removes all transitive **`tar@6.2.1`** from the dependency tree,
resolving [Dependabot alert
#400](https://github.com/twentyhq/twenty/security/dependabot/400)
([GHSA-34x7-hfp2-rc4v](https://github.com/isaacs/node-tar/security/advisories/GHSA-34x7-hfp2-rc4v)
/ CVE-2026-24842 — node-tar hardlink path traversal, high/8.2).

The alert had been dismissed as `no_bandwidth`, but `tar@6.2.1` was
still in the lockfile. I confirmed **6.2.1 is genuinely exploitable** by
running the advisory's PoC (the hardlink escaped the extraction dir to a
parent-directory file); `7.5.16` blocks it. There is **no patched 6.x
release** — the fix only exists in `7.5.7+`.

## Approach

Upgrade the build tooling that pulled tar v6 to the majors that depend
on tar v7, rather than forcing tar onto v6-era consumers:

| Package | Change | Mechanism |
|---|---|---|
| `node-gyp` | 10.2.0 / 7.1.2 / 9.4.1 → **12.4.0** | resolution |
| `cacache` | 18 → **20.0.4** | resolution |
| `make-fetch-happen` | → **15.0.6** | resolution |
| `mintlify` (twenty-docs) | `latest` → **^4.2.594**
(`@mintlify/previewing` → tar 7.5.15) | direct dep bump |
| `@electron/rebuild`, `@electron/node-gyp`, `pacote` → `tar` | →
**^7.5.16** | scoped resolution |

The last row covers the two subtrees with **no upstream tar-v7
release**: `@electron/rebuild` (+ electron's `node-gyp` fork) in
`twenty-companion`, and `pacote@11/15` via `zapier-platform-cli` in
`twenty-zapier`.

All `tar` now resolves to **7.5.13 / 7.5.15 / 7.5.16**; `node_modules`
verified free of tar v6.

## Validation done
- `yarn install` completes cleanly (constraints pass, only pre-existing
`enableScripts: false` + peer-dep warnings).
- Installed `node_modules` contains zero tar v6.

## Validation still needed before merge ⚠️
- The scoped overrides force tar v7 onto packages written for the v6
API. Resolution is consistent, but **runtime not exercised**
(`enableScripts: false` skips native builds at install). Please
validate:
  - `twenty-companion` electron `make` / native rebuild
  - `twenty-zapier` build/push
- If either breaks, drop the scoped overrides and accept those two
**dev/build-only** clusters as residual — they extract only trusted
archives at build time, so the CVE (which needs attacker-controlled
input) isn't reachable there.
- `mintlify` is pinned (not `latest`) because `.yarnrc.yml`'s
`npmMinimalAgeGate: 3d` quarantines the true latest. Pinning is arguably
healthier, but it's a deliberate behavior change.

## Note
twenty-server's own runtime tarball extraction
(`extract-tarball-securely.util.ts`) was already on patched tar **and**
rejects all hardlink/symlink entries — so this PR addresses the
remaining build-tooling exposure, not a live runtime hole.

Large `yarn.lock` churn is expected: the node-gyp/cacache major bumps
refresh npm-internals tree-wide.
2026-06-08 20:48:44 +02:00
Charles Bochet 822beb6a86 chore: force tmp >= 0.2.7 for root dev tooling (nx/zapier) (#21338)
Resolves the **root** `tmp` Dependabot alert (`tmp < 0.2.6`, #1308).

In the root workspace, `tmp` is a transitive dep of `nx` (`~0.2.1`) and
`zapier-platform-cli` (exact `0.2.1`) — dev/CLI tooling that
**exact-pins old tmp with no fixed parent to upgrade to** (verified:
even latest `zapier-platform-cli@15.19.0` still pins `0.2.1`). So it's
pinned to the patched **0.2.7** via a root `resolutions` entry — the
correct tool for un-dedupe-able transitive pins. Not in the prod image.

### Why the `twenty-apps/*` alerts are not fixed here
Those come from a different source — `twenty-sdk → inquirer ^10 →
@inquirer/editor 4.x → external-editor → tmp@0.0.33`. Rather than add a
`resolutions` block to every app's `package.json` (which doesn't scale —
every newly-scaffolded app would need it), they'll be fixed
**centrally** by bumping `inquirer` in `twenty-sdk` (`^10 → ^12`, which
reaches `@inquirer/editor 5.x` that dropped external-editor). Separate
PR — apps inherit the fix on the next SDK release with no manual
additions.
2026-06-08 20:11:56 +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 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
Raphaël Bosi 6f9b59b224 Scaffold twenty-new-ui (#21236)
Scaffolds `twenty-new-ui`, the next-gen replacement for `twenty-ui`, on
**SCSS** Modules + **Base UI** (no Linaria).

- **Tooling**: Vite lib build, subpaths mirror twenty-ui, typed SCSS
Modules, Storybook + axe a11y, size-limit, Nx targets.
- **Theme**: single token source → nx generateTheme emits the CSS vars +
accessor; parity test asserts token-for-token match with twenty-ui.

Migrated a first `Toggle` component with its stories to allow
@charlesBochet to wire the new pixel-diff system.

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 10:42:57 +00:00
Thomas des Francs 1642be86f5 Bonapara/twenty codex plugin (#20857)
@martmull v2.0 ;)

---------

Co-authored-by: martmull <martmull@hotmail.fr>
Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
2026-06-02 14:39:14 +00:00
dependabot[bot] 6d550611d2 chore(deps): bump typescript from 5.9.2 to 5.9.3 (#20991)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.2
to 5.9.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/microsoft/TypeScript/releases">typescript's
releases</a>.</em></p>
<blockquote>
<h2>TypeScript 5.9.3</h2>
<p>Note: this tag was recreated to point at the correct commit. The npm
package contained the correct content.</p>
<p>For release notes, check out the <a
href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-9/">release
announcement</a></p>
<ul>
<li><a
href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&amp;q=milestone%3A%22TypeScript+5.9.0%22+is%3Aclosed+">fixed
issues query for Typescript 5.9.0 (Beta)</a>.</li>
<li><a
href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&amp;q=milestone%3A%22TypeScript+5.9.1%22+is%3Aclosed+">fixed
issues query for Typescript 5.9.1 (RC)</a>.</li>
<li><em>No specific changes for TypeScript 5.9.2 (Stable)</em></li>
<li><a
href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&amp;q=milestone%3A%22TypeScript+5.9.3%22+is%3Aclosed+">fixed
issues query for Typescript 5.9.3 (Stable)</a>.</li>
</ul>
<p>Downloads are available on:</p>
<ul>
<li><a href="https://www.npmjs.com/package/typescript">npm</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/microsoft/TypeScript/commit/c63de15a992d37f0d6cec03ac7631872838602cb"><code>c63de15</code></a>
Bump version to 5.9.3 and LKG</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/8428ca4cc8a7ecc9ac18dd0258016228814f5eaf"><code>8428ca4</code></a>
🤖 Pick PR <a
href="https://redirect.github.com/microsoft/TypeScript/issues/62438">#62438</a>
(Fix incorrectly ignored dts file fr...) into release-5.9 (#...</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/a131cac6831aa6532ea963d0cb3131b957cad980"><code>a131cac</code></a>
🤖 Pick PR <a
href="https://redirect.github.com/microsoft/TypeScript/issues/62351">#62351</a>
(Add missing Float16Array constructo...) into release-5.9 (#...</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/04243333584a5bfaeb3434c0982c6280fe87b8d5"><code>0424333</code></a>
🤖 Pick PR <a
href="https://redirect.github.com/microsoft/TypeScript/issues/62423">#62423</a>
(Revert PR 61928) into release-5.9 (<a
href="https://redirect.github.com/microsoft/TypeScript/issues/62425">#62425</a>)</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/bdb641a4347af822916fb8cdb9894c9c2d2421dd"><code>bdb641a</code></a>
🤖 Pick PR <a
href="https://redirect.github.com/microsoft/TypeScript/issues/62311">#62311</a>
(Fix parenthesizer rules for manuall...) into release-5.9 (#...</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/0d9b9b92e2aca2f75c979a801abbc21bff473748"><code>0d9b9b9</code></a>
🤖 Pick PR <a
href="https://redirect.github.com/microsoft/TypeScript/issues/61978">#61978</a>
(Restructure CI to prepare for requi...) into release-5.9 (#...</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/2dce0c58af51cf9a9068365dc2f756c61b82b597"><code>2dce0c5</code></a>
Intentionally regress one buggy declaration output to an older version
(<a
href="https://redirect.github.com/microsoft/TypeScript/issues/62163">#62163</a>)</li>
<li>See full diff in <a
href="https://github.com/microsoft/TypeScript/compare/v5.9.2...v5.9.3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typescript&package-manager=npm_and_yarn&previous-version=5.9.2&new-version=5.9.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: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Weiko <corentin@twenty.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Félix Malfait <FelixMalfait@users.noreply.github.com>
2026-05-29 08:39:35 +02:00
neo773 323e66433e lint: migrate prettier to oxfmt (#20783)
Most changes are `implements` being unwrapped this is not a oxfmt
regression
Prettier in 3.7 (we're on 3.1) changed this behaviour prettier blog
[post](https://prettier.io/blog/2025/11/27/3.7.0#change-18094)

This unifies our linting tooling

---------

Co-authored-by: github-actions <github-actions@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2026-05-22 00:21:33 +02:00
Félix Malfait 658bdf3e57 chore(website): rename twenty-website-new → twenty-website (#20745)
## Summary
Follow-up to the Cloudflare/OpenNext migration (#20741). Now that the
legacy `twenty-website` package was already removed in #20270, the
`-new` suffix on the marketing site package is no longer meaningful.

## What changes
- **Directory rename**: `git mv packages/twenty-website-new
packages/twenty-website` (1213 files moved, no content change)
- **Package + nx config**: `package.json` and `project.json` name fields
updated, `sourceRoot` repointed
- **Source refs**: `load-local-articles.ts` and
`load-local-release-notes.ts` had a hardcoded `'twenty-website-new'`
segment in their monorepo-root fallback path;
`app/[locale]/releases/page.tsx` had display strings showing where to
add content
- **External refs**: root `package.json` workspaces, root `CLAUDE.md` /
`README.md`, `twenty-sdk` + `create-twenty-app` READMEs,
`.vscode/twenty.code-workspace`, `.cursor/rules/changelog-process.mdc`,
Crowdin config + the three `website-i18n-*` CI workflows +
`ci-website.yaml`
- **Docker cleanup**:
`packages/twenty-docker/twenty-website-new/Dockerfile` deleted; the two
Makefile targets (`prod-website-new-build` / `prod-website-new-run`)
that referenced it removed — EKS deploy was retired in the Cloudflare
migration
- **`yarn.lock`** regenerated against the new workspace path

## What's deliberately not in this PR
The dev hostname `website-new.twenty-main.com` in `wrangler.jsonc` stays
for now. Migrating it to `website.twenty-main.com` needs coordinated DNS
deletion (current CNAME points at the legacy Docusaurus NLB and serves
503s) and removal of the matching legacy `website` Helm chart in
`twenty-infra`. Flagged as a separate cleanup.

Companion infra PR: https://github.com/twentyhq/twenty-infra/pull/682
(workflow paths + Terraform ECR + docs)

## Test plan
- [x] `yarn install --immutable` resolves clean against the new path
- [x] `npx nx typecheck twenty-website` passes
- [x] `npx nx lint twenty-website` passes
- [ ] CI on this PR confirms the same on a fresh checkout
- [ ] After merge: trigger `Deploy Website` workflow against
`environment=dev` to confirm the renamed working-directory deploys
correctly
2026-05-19 23:42:09 +02:00
Thomas des Francs 93d83b2e36 [codex] Add Twenty Claude skills package (#20450)
## Summary

Adds a new `twenty-claude-skills` workspace package under `packages/`
for Claude skills related to Twenty.

## Changes

- Registers `packages/twenty-claude-skills` in the root Yarn workspace
list.
- Adds package metadata for `twenty-claude-skills`.
- Adds a README documenting the multi-skill layout.
- Adds the `twenty-record-presentation` skill under
`skills/twenty-record-presentation/SKILL.md`.

## Impact

This gives Claude-specific Twenty skills a dedicated package location
while preserving the skill metadata from the provided skill bundle.

## Validation

- Parsed the root `package.json` and
`packages/twenty-claude-skills/package.json` with Node.
- Compared the imported skill content against the source `.skill`
archive; the only difference is a trailing newline at EOF.
2026-05-11 14:56:45 +00:00
martmull 773245fa65 Isolate twenty apps from nx project (#20406)
- avoids importing twenty-shared or else in twenty-apps applications
- update and add workflow action in twenty linear app
2026-05-08 13:16:25 +00:00
neo773 1faf725498 Fix NestJS CLI pin chokidar to v3 (#20316)
fixes `EMFILE` by downgrading chokidar to v3
root cause is v4 removed kernel level FSEvents on macOS and instead uses
`node:fs.watch` which doesn't scales for a repo of our size

Seems to be working well, even survives multiple hot reloads after
editing files
2026-05-07 09:55:53 +02:00
Paul Rastoin 3b180e7cb5 Fix root monorepo package json focused installation (#20292)
# Introduction
Running `yarn workspace focus twenty`( only installing root package.json
dependencies ) would fail because the yarn constraint expect the yarn
types to be installed
2026-05-05 15:13:31 +00:00
Abdullah. 59107b5b23 Remove twenty-website package. (#20270) 2026-05-05 12:45:02 +02:00
martmull 3ffda0a29e Add twenty version validation (#20227)
as title, server version is checked before app deploy, and app install
commands

### New section in publishing doc
<img width="1344" height="912" alt="image"
src="https://github.com/user-attachments/assets/2a9335e7-0a7a-4973-a2db-f30f03181001"
/>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-04 13:55:31 +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
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