18 Commits

Author SHA1 Message Date
Félix Malfait bb6da7b7d1 feat(code-interpreter): reuse a warm sandbox per conversation (E2B) (#21664)
## What

The E2B code-interpreter driver created a **fresh sandbox on every
execution** and killed it in `finally`, so every call in a conversation
paid full cold-start and started blank. This PR keeps **one warm sandbox
per conversation** and, on idle, **pauses** it rather than killing it.

## How

- **Discovery without a registry:** the sandbox is tagged with the chat
`threadId` (scoped `workspaceId:threadId`) via E2B **metadata**, found
with `Sandbox.list({ query: { state: ['running','paused'], metadata }
})` and resumed with `Sandbox.connect()` (which auto-resumes a paused
sandbox). E2B is the source of truth — no Redis/DB mapping.
- **Pause/resume (E2B 2.x):** session sandboxes are created with
`lifecycle: { onTimeout: 'pause', autoResume: true }`. When idle they
**pause** — compute billing stops, filesystem **and** kernel/memory
state are preserved — and resume in ~1s on the next call. This replaces
the earlier keepalive approach.
- **No premature pause mid-run:** the sandbox is kept alive for
`max(execution timeout, idle window)`, so a long execution is never
paused underneath itself.
- **Tenant isolation:** discovery filters by the `twentySessionId` tag
and **re-checks it client-side**, so a loose server-side match can never
hand one conversation's warm sandbox (with its files, kernel state,
token) to another.
- **Concurrency:** executions sharing a session are serialized
in-process (one active stream per thread, run as a single job — the chat
resolver queues concurrent messages), so parallel tool calls can't race
the shared kernel.
- **Output isolation:** `/home/user/output` is reset at the start of
each reused run, so a call only returns the artifacts it actually
produced; durable state lives elsewhere and persists.

## SDK upgrade

`@e2b/code-interpreter` **`^1.0.4` → `^2.6.0`** (pulls `e2b@2.x`). The
typed pause/resume API, `lifecycle`, and the `state`/`metadata` list
filter only exist in the 2.x line; 1.x exposed them only as untyped
OpenAPI internals. `Sandbox.list()` is now a paginator (handled).

## Config

| Var | Default | Purpose |
|---|---|---|
| `CODE_INTERPRETER_TIMEOUT_MS` | `300000` | Max single-execution
duration. |
| `CODE_INTERPRETER_IDLE_TIMEOUT_MS` | `300000` | Idle window before the
warm sandbox auto-pauses. |

Reuse is always-on when a session id is present (chat path). The
workflow-agent path and the dev-only `LocalDriver` are unaffected.

## ⚠️ Open item before merge: paused-sandbox GC

E2B retains paused sandboxes **indefinitely** (no TTL). Unlike the old
keepalive path (which auto-killed on idle), pause means a conversation's
sandbox persists after the chat ends — so without garbage collection,
paused sandboxes accumulate (≈ one per historical conversation) and
consume storage. A GC policy is required; the approach + retention
window are being decided (see PR discussion). Also: the E2B runtime path
can't run in CI, so this still needs a **live smoke test** (reuse hit,
idle→pause, resume) and confirmation of paused-storage pricing before
rollout.

## Tests / checks

- Resolver unit tests (`getOrCreateSessionSandbox`): reuse+extend,
create-when-absent, duplicate reaping, connect-failure fallback,
keep-first-connectable-when-earlier-dead, **ignore cross-tenant
metadata**, and **kill-on-timeout-refresh-failure**.
- `nx typecheck twenty-server` (against e2b 2.x), `oxlint --type-aware`,
`oxfmt --check` all clean.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-17 08:12:24 +00: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 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
github-actions[bot] f1b2be041a i18n - translations (#20801)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-05-21 13:35:35 +02:00
martmull 74fa26f9e5 Fix must wait 3 days to create app in twenty-apps (#20794)
as title
2026-05-21 09:29:47 +00:00
github-actions[bot] 915ce37d20 i18n - translations (#20551)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-05-13 19:32:03 +02:00
neo773 565995e715 security: harden CI against supply-chain attacks (#20476)
- Pin all third-party actions to SHA
- Gate claude.yml triggers to internal authors with Harden-Runner egress
audit
- Ignore fork-PR lifecycle scripts
- Narrow cross-repo dispatch payloads
- Add 7d npm release-age gate
- Add CODEOWNERS on .github/** and .yarnrc.yml

---------

Co-authored-by: prastoin <paul@twenty.com>
2026-05-12 12:20:29 +00:00
Paul Rastoin 052aecccc7 Refactor dependency graph for SDK, client-sdk and create-app (#18963)
## Summary

### Externalize `twenty-client-sdk` from `twenty-sdk`

Previously, `twenty-client-sdk` was listed as a `devDependency` of
`twenty-sdk`, which caused Vite to bundle it inline into the dist
output. This meant end-user apps had two copies of `twenty-client-sdk`:
one hidden inside `twenty-sdk`'s bundle, and one installed explicitly in
their `node_modules`. These copies could drift apart since they weren't
guaranteed to be the same version.

**Change:** Moved `twenty-client-sdk` from `devDependencies` to
`dependencies` in `twenty-sdk/package.json`. Vite's `external` function
now recognizes it and keeps it as an external `require`/`import` in the
dist output. End users get a single deduplicated copy resolved by their
package manager.

### Externalize `twenty-sdk` from `create-twenty-app`

Similarly, `create-twenty-app` had `twenty-sdk` as a `devDependency`
(bundled inline). After refactoring `create-twenty-app` to
programmatically import operations from `twenty-sdk` (instead of
shelling out via `execSync`), it became a proper runtime dependency.

**Change:** Moved `twenty-sdk` from `devDependencies` to `dependencies`
in `create-twenty-app/package.json`.

### Switch E2E CI to `yarn npm publish`

The `workspace:*` protocol in `dependencies` is a Yarn-specific feature.
`npm publish` publishes it as-is (which breaks for consumers), while
`yarn npm publish` automatically replaces `workspace:*` with the
resolved version at publish time (e.g., `workspace:*` becomes `=1.2.3`).

**Change:** Replaced `npm publish` with `yarn npm publish` in
`.github/workflows/ci-create-app-e2e.yaml`.

### Replace `execSync` with programmatic SDK calls in
`create-twenty-app`

`create-twenty-app` was shelling out to `yarn twenty remote add` and
`yarn twenty server start` via `execSync`, which assumed the `twenty`
binary was already installed in the scaffolded app. This was fragile and
created an implicit circular dependency.

**Changes:**
- Replaced `execSync('yarn twenty remote add ...')` with a direct call
to `authLoginOAuth()` from `twenty-sdk/cli`
- Replaced `execSync('yarn twenty server start')` with a direct call to
`serverStart()` from `twenty-sdk/cli`
- Deleted the duplicated `setup-local-instance.ts` from
`create-twenty-app`

### Centralize `serverStart` as a dedicated operation

The Docker server start logic was previously inline in the `server
start` CLI command handler (`server.ts`), and `setup-local-instance.ts`
was shelling out to `yarn twenty server start` to invoke it -- meaning
`twenty-sdk` was calling itself via a child process.

**Changes:**
- Extracted the Docker container management logic into a new
`serverStart` operation (`cli/operations/server-start.ts`)
- Merged the detect-or-start flow from `setup-local-instance.ts` into
`serverStart` (detect across multiple ports, start Docker if needed,
poll for health)
- Deleted `setup-local-instance.ts` from `twenty-sdk`
- Added `onProgress` callback (consistent with other operations like
`appBuild`) instead of direct `console.log` calls
- Both the `server start` CLI command and `create-twenty-app` now call
`serverStart()` programmatically

related to https://github.com/twentyhq/twenty-infra/pull/525
2026-03-26 10:56:52 +00:00
github-actions[bot] 9787a6efb6 i18n - translations (#13102)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2025-07-08 15:13:02 +02:00
Niklas Korz 47313c388d Update yarn and remove explicit hardened mode (#13092)
Updates yarn to the latest version 4.9.2 (from 4.4.0).

Also removes the explicit `enableHardenedMode` from yarnrc as it
significantly slows down installation.
This is already enabled automatically for pull requests on Github, thus
preventing lockfile poisoning where it's relevant.

See <https://yarnpkg.com/features/security#hardened-mode>:

> in most cases you won't even have to think about it - the hardened
mode is enabled by default when Yarn detects it runs in a pull request
from a public GitHub repository.

It can additionally be enabled explicitly for specific CI jobs by using
an environment variable, if desired:

> The hardened mode can be set (or disabled) [...] by defining
`YARN_ENABLE_HARDENED_MODE=1|0` in your environment variables

If this is the case, yarn still recommends **not** enabling it
everywhere:

> **DANGER**
>
> The hardened mode makes installs significantly slower as Yarn has to
query the registry to make sure the information contained in the
lockfile are accurate. If your CI pipeline runs multiple jobs, we
recommend disabling the hardened mode in all but one of them so as to
limit the performance impact.

---------

Co-authored-by: prastoin <paul@twenty.com>
2025-07-08 14:57:08 +02:00
github-actions[bot] 18de7efaaa i18n - translations (#10735)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2025-03-07 18:19:42 +01:00
Paul Rastoin 65e569986d [ENHC] Create Yarn constraints to validate node version (#10542)
## Introduction
This is PR is a suggestion ! And should be discussed

With yarn `^4`, during installation won't raise an error if current dev
env does not satisfies the `engines` policy.
We have usually 10+ contributors support request regarding higher node
version issue per week

I would have preferred a very declarative integration using npm
[engines](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#engines)
but this does not seems to be natively supported by `yarn`

We should keep in mind that this might block any machines from our CICD
if they have diff node version installed ( such as running the project
on a different node version could result in bugs too )

## Implem

Created a yarn [constraints](https://yarnpkg.com/features/constraints)
run after each installation that checking if current node version
satisfies defined engines range ( might also be done for others engines
entries )

I assume we will always have the same engines policy for every packages,
at least that's not a consideration from now

## Further
We could refactor our package.json engines into only one using
`Yarn.set` etc

## Resource
- https://yarnpkg.com/configuration/yarnrc
- https://yarnpkg.com/features/constraints

## Note
- Not running constraints in `preInstall` hook as won't be effective on
fresh install
-
[engine-strict](https://docs.npmjs.com/cli/v8/using-npm/config#engine-strict)
is an npm-config
-
[devEngines](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#devengines)
are npm feature too ( for instance pnpm current PR
https://github.com/pnpm/pnpm/issues/8153 )

## Conclusion
As always any suggestions are more than welcomed !
2025-02-27 15:18:07 +01:00
github-actions[bot] 14478afa7e i18n - translations (#10250)
Co-authored-by: github-actions <github-actions@twenty.com>
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-02-17 12:00:59 +01:00
nitin 774cb554f4 removed @blocknote/core from dependencies (#6580)
Fixes #6564  & #6561 

@FelixMalfait 

Removed @blocknote/core from dependencies



https://github.com/user-attachments/assets/ef6acfff-2945-4062-a35c-21dd108a4345

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2024-08-08 15:44:09 +02:00
Jérémy M cfb36ec0fb feat: bump yarn to last stable version (#6081)
This PR bump yarn version to latest stable version
2024-07-19 15:38:03 +02:00
Charles Bochet 8d53c63801 Fix docker install (#2925)
* Fix docker install

* Move back twenty-eslint-plugin to eslint-plugin-twenty

* fix: add bundled yarn

* Improve makeifle structure

* Update commands and doc

* Add pg_graphql binaries

* Fix

---------

Co-authored-by: Jérémy Magrin <jeremy.magrin@gmail.com>
2023-12-11 13:36:24 +01:00
Charles Bochet 44baaee28e Update scripts and documentation to use nx and new monorepo architecture (#2912)
* Update scripts and documentation to use nx and new monorepo architecture

* Start fixing docker

* Migrate eslint plugin and postgres setup

* Fix docker

* Fix patches

* Fix

* fix: wip try to fix the patches

* Apply patches

---------

Co-authored-by: Jérémy Magrin <jeremy.magrin@gmail.com>
2023-12-11 10:54:57 +01:00
Charles Bochet 5bdca9de6c Migrate to a monorepo structure (#2909) 2023-12-10 18:10:54 +01:00