Commit Graph
12204 Commits
Author SHA1 Message Date
7ca2efeb96 i18n - translations (#20796)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-05-21 11:42:46 +02:00
WeikoandGitHub 224376233b fix(front): focus new Field widget and open side panel on add (#20777)
## Context
In the record-page edit mode, the "Add widget" section has three menu
items:
`Fields group`, `Field`, and `More widgets`. `Fields group` creates the
widget, focuses it, and opens its settings side panel. `Field` only
added the widget to the draft — no focus, no panel — which left the user
without visible confirmation or a way to immediately edit the new
widget.

## Change
Updated `useCreateRecordPageFieldWidget` to mirror
`useCreateRecordPageFieldsWidget`:
After appending the new widget to the draft, it now sets
`pageLayoutEditingWidgetIdComponentState` to the new widget's id and
navigates the side panel to `SidePanelPages.RecordPageFieldSettings`
(with `focusTitleInput: true`, `resetNavigationStack: true`).
This matches the behavior of clicking an existing field widget in
`useOpenWidgetSettingsInSidePanel` (`WidgetType.FIELD` branch).
2026-05-21 09:22:21 +00:00
Paul RastoinandGitHub a3c92311e3 Application file storage service (#20793)
# Introduction
Fix unsafe resource path join with expected prefix at file storage
directly
Add early paths transversal detections in metadata validators
2026-05-21 09:21:44 +00:00
1ed347bc17 chore: sync AI model catalog from models.dev (#20791)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

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

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

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-05-21 09:14:02 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b792f7654b chore(deps): bump tinyglobby from 0.2.15 to 0.2.16 (#20788)
Bumps [tinyglobby](https://github.com/SuperchupuDev/tinyglobby) from
0.2.15 to 0.2.16.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/SuperchupuDev/tinyglobby/releases">tinyglobby's
releases</a>.</em></p>
<blockquote>
<h2>0.2.16</h2>
<h2>Fixed</h2>
<ul>
<li>Upgraded <code>picomatch</code> to 4.0.4, mitigating any potential
exposure to <a
href="https://github.com/micromatch/picomatch/security/advisories/GHSA-c2c7-rcm5-vvqj">CVE-2026-33671</a>
and <a
href="https://github.com/micromatch/picomatch/security/advisories/GHSA-3v7f-55p6-f55p">CVE-2026-33672</a></li>
</ul>
<h2>Changed</h2>
<ul>
<li>Overhauled and optimized most internals by <a
href="https://github.com/Torathion"><code>@​Torathion</code></a></li>
<li>Ignore patterns are no longer compiled twice by <a
href="https://github.com/webpro"><code>@​webpro</code></a></li>
</ul>
<p>Consider <a
href="https://github.com/sponsors/SuperchupuDev">sponsoring</a> if you'd
like to support the development of this project and the goal of reaching
a lighter and faster ecosystem</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/SuperchupuDev/tinyglobby/blob/main/CHANGELOG.md">tinyglobby's
changelog</a>.</em></p>
<blockquote>
<h3><a
href="https://github.com/SuperchupuDev/tinyglobby/compare/0.2.15...0.2.16">0.2.16</a></h3>
<h4>Fixed</h4>
<ul>
<li>Upgraded <code>picomatch</code> to 4.0.4, mitigating any potential
exposure to
<a
href="https://github.com/micromatch/picomatch/security/advisories/GHSA-c2c7-rcm5-vvqj">CVE-2026-33671</a>
and <a
href="https://github.com/micromatch/picomatch/security/advisories/GHSA-3v7f-55p6-f55p">CVE-2026-33672</a></li>
</ul>
<h4>Changed</h4>
<ul>
<li>Overhauled and optimized most internals by <a
href="https://github.com/Torathion">Torathion</a></li>
<li>Ignore patterns are no longer compiled twice by <a
href="https://github.com/webpro">webpro</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/SuperchupuDev/tinyglobby/commit/577920259c91f5603fab3dbfa599a83bbb14a27a"><code>5779202</code></a>
release 0.2.16</li>
<li><a
href="https://github.com/SuperchupuDev/tinyglobby/commit/071954f97f4d2b573ecd92aecb48220867b3c776"><code>071954f</code></a>
bump deps once more</li>
<li><a
href="https://github.com/SuperchupuDev/tinyglobby/commit/e541dde000158e69b44e8b5a03789d136d88ae0d"><code>e541dde</code></a>
do not import the whole <code>fs</code> module</li>
<li><a
href="https://github.com/SuperchupuDev/tinyglobby/commit/2381b766d3447e078b3112e533ada07621f60526"><code>2381b76</code></a>
fix root being too broad</li>
<li><a
href="https://github.com/SuperchupuDev/tinyglobby/commit/0addeb9a78cab5fd93ac6dad217f75930cfbfda2"><code>0addeb9</code></a>
chore(deps): update all non-major dependencies (<a
href="https://redirect.github.com/SuperchupuDev/tinyglobby/issues/191">#191</a>)</li>
<li><a
href="https://github.com/SuperchupuDev/tinyglobby/commit/91ac26cc3bda60378d188565ce4f05e884aa4f31"><code>91ac26c</code></a>
chore(deps): update pnpm/action-setup action to v5 (<a
href="https://redirect.github.com/SuperchupuDev/tinyglobby/issues/192">#192</a>)</li>
<li><a
href="https://github.com/SuperchupuDev/tinyglobby/commit/c50558e944bf71dbfeb392f8693fada87f520a70"><code>c50558e</code></a>
upgrade picomatch (and everything else)</li>
<li><a
href="https://github.com/SuperchupuDev/tinyglobby/commit/618517544e95f8167f1722902558dd78dcd34fe6"><code>6185175</code></a>
chore(deps): update dependency picomatch to v4.0.4 [security] (<a
href="https://redirect.github.com/SuperchupuDev/tinyglobby/issues/193">#193</a>)</li>
<li><a
href="https://github.com/SuperchupuDev/tinyglobby/commit/49c2b9356c4977f1f531de651f90b420a06c64f6"><code>49c2b93</code></a>
enable pnpm <code>trustPolicy</code></li>
<li><a
href="https://github.com/SuperchupuDev/tinyglobby/commit/bc825c476a5a429e58e06d11364cd68707b4cdd1"><code>bc825c4</code></a>
chore(deps): update all non-major dependencies (<a
href="https://redirect.github.com/SuperchupuDev/tinyglobby/issues/181">#181</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/SuperchupuDev/tinyglobby/compare/0.2.15...0.2.16">compare
view</a></li>
</ul>
</details>
<br />


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

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

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

---

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

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


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-21 05:47:58 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
42ad3cbd1a chore(deps): bump linkify-react from 4.3.2 to 4.3.3 (#20789)
Bumps
[linkify-react](https://github.com/nfrasser/linkifyjs/tree/HEAD/packages/linkify-react)
from 4.3.2 to 4.3.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/nfrasser/linkifyjs/releases">linkify-react's
releases</a>.</em></p>
<blockquote>
<h2>v4.3.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix parsing bugs with some special encoded URLs</li>
<li>Parsed emails should not include port numbers</li>
<li>Exact version requirement for interfaces and plugins to avoid
incompatibility issues with older versions of linkify core</li>
<li>Support for jQuery 4</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/nfrasser/linkifyjs/compare/v4.3.2...v4.3.3">https://github.com/nfrasser/linkifyjs/compare/v4.3.2...v4.3.3</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/nfrasser/linkifyjs/blob/main/CHANGELOG.md">linkify-react's
changelog</a>.</em></p>
<blockquote>
<h2>v4.3.3</h2>
<ul>
<li>Fix parsing bugs with some special encoded URLs</li>
<li>Parsed emails should not include port numbers</li>
<li>Exact version requirement for interfaces and plugins to avoid
incompatibility issues with older versions of linkify core</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/nfrasser/linkifyjs/commit/7fffcc6b48f7dbf8e98fca493e1c997a659fe651"><code>7fffcc6</code></a>
v4.3.3</li>
<li><a
href="https://github.com/nfrasser/linkifyjs/commit/2cb8352d78c7449cd8c7ee489a647d3422640a25"><code>2cb8352</code></a>
Update dependencies (<a
href="https://github.com/nfrasser/linkifyjs/tree/HEAD/packages/linkify-react/issues/529">#529</a>)</li>
<li>See full diff in <a
href="https://github.com/nfrasser/linkifyjs/commits/v4.3.3/packages/linkify-react">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new
releaser for linkify-react since your current version.</p>
</details>
<br />


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

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

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

---

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

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


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-21 05:47:35 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e1378dd4cf chore(deps): bump @azure/msal-node from 3.8.4 to 3.8.10 (#20787)
Bumps
[@azure/msal-node](https://github.com/AzureAD/microsoft-authentication-library-for-js)
from 3.8.4 to 3.8.10.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/releases">@​azure/msal-node's
releases</a>.</em></p>
<blockquote>
<h2><code>@​azure/msal-node</code> v3.8.10</h2>
<h2>3.8.10</h2>
<p>Wed, 18 Mar 2026 20:48:29 GMT</p>
<h3>Patches</h3>
<ul>
<li>Bump <code>@​azure/msal-common</code> to v15.17.0 (beachball)</li>
<li>Bump eslint-config-msal to v0.0.0 (beachball)</li>
<li>Bump rollup-msal to v0.0.0 (beachball)</li>
</ul>
<h2><code>@​azure/msal-node</code> v3.8.9</h2>
<h2>3.8.9</h2>
<p>Fri, 13 Mar 2026 04:32:07 GMT</p>
<h3>Patches</h3>
<ul>
<li>Bump <code>@​azure/msal-common</code> to v15.16.1 (beachball)</li>
<li>Bump eslint-config-msal to v0.0.0 (beachball)</li>
<li>Bump rollup-msal to v0.0.0 (beachball)</li>
</ul>
<h2><code>@​azure/msal-node</code> v3.8.8</h2>
<h2>3.8.8</h2>
<p>Mon, 23 Feb 2026 16:28:24 GMT</p>
<h3>Patches</h3>
<ul>
<li>Bump <code>@​azure/msal-common</code> to v15.15.0 (beachball)</li>
<li>Bump eslint-config-msal to v0.0.0 (beachball)</li>
<li>Bump rollup-msal to v0.0.0 (beachball)</li>
</ul>
<h2><code>@​azure/msal-node</code> v3.8.7</h2>
<h2>3.8.7</h2>
<p>Tue, 10 Feb 2026 22:19:29 GMT</p>
<h3>Patches</h3>
<ul>
<li>Bump <code>@​azure/msal-common</code> to v15.14.2 (beachball)</li>
<li>Bump eslint-config-msal to v0.0.0 (beachball)</li>
<li>Bump rollup-msal to v0.0.0 (beachball)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/commit/74c792ec34cd83a3470c4d878b403af0fa2884f0"><code>74c792e</code></a>
[v4] Add missing client capabilities in platform broker flows (<a
href="https://redirect.github.com/AzureAD/microsoft-authentication-library-for-js/issues/8429">#8429</a>)</li>
<li><a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/commit/e096fc85e22fcb941646b3f5d9f264b90dffd0ad"><code>e096fc8</code></a>
[v4] Post-release PR (<a
href="https://redirect.github.com/AzureAD/microsoft-authentication-library-for-js/issues/8425">#8425</a>)</li>
<li><a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/commit/23cd31c1fbcfa569dd9135830f5168ec71678a19"><code>23cd31c</code></a>
[v4] Add support for client data telemetry with CLI_DATA parameter (<a
href="https://redirect.github.com/AzureAD/microsoft-authentication-library-for-js/issues/8378">#8378</a>)</li>
<li><a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/commit/eb893e565a4f7de5b9c957b37bb4f975302f1713"><code>eb893e5</code></a>
Track online/offline status change (<a
href="https://redirect.github.com/AzureAD/microsoft-authentication-library-for-js/issues/8410">#8410</a>)</li>
<li><a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/commit/d221f4e6dbc439e771a90f1648c8f5db09b4d88b"><code>d221f4e</code></a>
[v4] Respect claims of the brokered application (<a
href="https://redirect.github.com/AzureAD/microsoft-authentication-library-for-js/issues/8409">#8409</a>)</li>
<li><a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/commit/73df97e5c505010f6b9681749df28a328e4e3894"><code>73df97e</code></a>
Common partial release resolution (<a
href="https://redirect.github.com/AzureAD/microsoft-authentication-library-for-js/issues/8397">#8397</a>)</li>
<li><a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/commit/ee5e7abd5d9a6cfb6ada9b3ac36e15a81f7ba3a8"><code>ee5e7ab</code></a>
monitor_window_timeout telemetry (<a
href="https://redirect.github.com/AzureAD/microsoft-authentication-library-for-js/issues/8380">#8380</a>)</li>
<li><a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/commit/2be7888051cc12e7447487e84c826159dad3ed42"><code>2be7888</code></a>
Rename dev to v4-lts changes (<a
href="https://redirect.github.com/AzureAD/microsoft-authentication-library-for-js/issues/8364">#8364</a>)</li>
<li><a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/commit/4486b7e4bfedc414f7f5f1a7786be30484318206"><code>4486b7e</code></a>
Fix JSON object conversion in PlatformDOMRequest v4 (<a
href="https://redirect.github.com/AzureAD/microsoft-authentication-library-for-js/issues/8350">#8350</a>)</li>
<li><a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/commit/3e5d58b71e232b5978edcf0bd4c05f5948b8a747"><code>3e5d58b</code></a>
Post-release PR (<a
href="https://redirect.github.com/AzureAD/microsoft-authentication-library-for-js/issues/8354">#8354</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/AzureAD/microsoft-authentication-library-for-js/compare/msal-node-v3.8.4...msal-node-v3.8.10">compare
view</a></li>
</ul>
</details>
<br />


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

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

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

---

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

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


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-21 05:06:59 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5e1b23a28b chore(deps): bump @recallai/desktop-sdk from 2.0.8 to 2.0.15 (#20785)
Bumps @recallai/desktop-sdk from 2.0.8 to 2.0.15.


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

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

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

---

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

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


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-21 05:04:13 +00:00
7aef406696 i18n - translations (#20782)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-05-20 21:33:20 +02:00
923c3beead fix(auth): clarify error when joining a non-active workspace (#20769)
## Summary

When an existing user accepts an invite into a workspace whose
`activationStatus` is not `ACTIVE` (e.g. `SUSPENDED`, `INACTIVE`,
`PENDING_CREATION`), the throw in
`throwIfWorkspaceIsNotReadyForSignInUp` returns:

> User is not part of the workspace

The message describes the symptom (they aren't a member yet) instead of
the cause (the workspace can't accept new members), which makes invitees
assume their invite is broken when the real issue is the target
workspace's state.

The sibling branch a few lines above — for brand-new users hitting the
same non-ACTIVE workspace — already returns `"Workspace is not ready to
welcome new members"`. This PR reuses the same message in the
existing-user branch so both paths give a consistent, accurate
explanation.

Single file, two string literals.

## Test plan

- [ ] Sign in via Google with an existing Twenty account, accepting an
invite to a `SUSPENDED` workspace → confirm the new message is shown
instead of "User is not part of the workspace".
- [ ] Confirm the happy path (sign-in to an `ACTIVE` workspace via
invite) is unchanged — early-return on `ACTIVE` is untouched.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-05-20 19:16:11 +00:00
Paul RastoinandGitHub 31842f7714 Ci server custom jest reporter (#20765)
# Introduction
Only display failing unit tests trace in the ci-server server-test jobs
So it's possible to identify what unit test are failing without having
to re run them locally
2026-05-20 17:58:27 +00:00
Charles BochetandGitHub 9988f98577 feat(server): idempotent CLI to rotate ENCRYPTION_KEY across enc:v2 rows (#20613)
## Summary
Adds the \`secret-encryption:rotate\` CLI command, which re-encrypts
every at-rest secret stored in an \`enc:v2:\` envelope under the current
\`ENCRYPTION_KEY\`. The command is **online** and **resumable**: a SQL
filter skips rows already on the current keyId, so interrupting it
(Ctrl-C, container restart, …) and re-running picks up where it left off
without re-rotating earlier rows.

### Sites covered (one handler each)
| Site | Table.column | Scope |
| --- | --- | --- |
| \`connected-account-tokens\` | \`connectedAccount.{accessToken,
refreshToken}\` | workspace |
| \`application-variable\` | \`applicationVariable.value\` (isSecret
only) | workspace |
| \`application-registration-variable\` |
\`applicationRegistrationVariable.encryptedValue\` | instance |
| \`signing-key-private-keys\` | \`signingKey.privateKey\` | instance |
| \`sensitive-config-storage\` | \`keyValuePair.value\` (isSensitive +
STRING configs) | instance |
| \`totp-secrets\` | \`twoFactorAuthenticationMethod.secret\` |
workspace |

Each handler:
- Filters at SQL level on \`value LIKE 'enc:v2:%' AND value NOT LIKE
'enc:v2:<primaryKeyId>:%'\` to enforce idempotency without re-decrypting
already-rotated rows.
- Uses cursor-based batching (default **200**, capped **5000**).
- Threads \`workspaceId\` into HKDF for workspace-scoped sites; runs
instance-scoped for the rest.

### CLI flags
| Flag | Description |
| --- | --- |
| \`-s, --site <site>\` | Limit to a single site. |
| \`-b, --batch-size <n>\` | Override per-batch row count. |
| \`-d, --dry-run\` | Decrypt + re-encrypt in memory, skip the
\`UPDATE\`. |

The runner logs progress via Nest \`Logger\` (per-site start,
completion, final summary) and exits non-zero when any site reports
\`errors > 0\`. \`FALLBACK_ENCRYPTION_KEY\` must be set to the previous
\`ENCRYPTION_KEY\` during rotation; the runner warns when it is unset.

Operator documentation lives in #20611 (docs PR).
2026-05-20 17:51:29 +00:00
3c458ce4ca i18n - docs translations (#20778)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-05-20 19:28:51 +02:00
b869107a22 fix(messaging): preserve all gmail to/cc/bcc recipients as participants (#20491)
As title but I also refactored it a little to match our current file and
code conventions since the code was very old

Reported by a cloud customer

---------

Co-authored-by: martmull <martmull@hotmail.fr>
2026-05-20 15:40:29 +00:00
EtienneandGitHub 4c4dc4cb21 fix(ai-chat)-preference models import (#20776) 2026-05-20 15:20:09 +00:00
martmullGitHubcubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
237a943947 Update twenty sdk commands (#20735)
Performs twenty-sdk cli command migration:

Summary

``` ┌─────┬──────────────────────────┬────────────────────────────┬───────────────────────┐
 │  #  │       Old command        │        New command         │        Status         │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 1   │ twenty dev [appPath]     │ twenty dev [appPath]       │ Unchanged (now also   │
 │     │                          │                            │ DEFAULT)              │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 2   │ twenty dev --once        │ twenty dev --once          │ Unchanged             │
 │     │ [appPath]                │ [appPath]                  │                       │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 3   │ twenty dev --watch       │ twenty dev [appPath]       │ --watch flag removed  │
 │     │ [appPath]                │                            │ (was default)         │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 4   │ twenty dev --verbose     │ twenty dev --verbose       │ Unchanged             │
 │     │ [appPath]                │ [appPath]                  │                       │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 5   │ twenty dev --debug       │ twenty dev --debug         │ Unchanged             │
 │     │ [appPath]                │ [appPath]                  │                       │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 6   │ twenty dev --debounceMs  │ twenty dev --debounceMs    │ Unchanged             │
 │     │ <ms> [appPath]           │ <ms> [appPath]             │                       │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 7   │ twenty build [appPath]   │ twenty dev:build [appPath] │ Deprecated → colon    │
 │     │                          │                            │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 8   │ twenty build --tarball   │ twenty dev:build --tarball │ Deprecated → colon    │
 │     │ [appPath]                │  [appPath]                 │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 9   │ twenty typecheck         │ twenty dev:typecheck       │ Deprecated → colon    │
 │     │ [appPath]                │ [appPath]                  │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 10  │ twenty logs [appPath]    │ twenty dev:fn-logs         │ Deprecated → colon    │
 │     │                          │ [appPath]                  │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 11  │ twenty logs -n <name>    │ twenty dev:fn-logs -n      │ Deprecated → colon    │
 │     │ [appPath]                │ <name> [appPath]           │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 12  │ twenty logs -u <id>      │ twenty dev:fn-logs -u <id> │ Deprecated → colon    │
 │     │ [appPath]                │  [appPath]                 │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 13  │ twenty exec [appPath]    │ twenty dev:fn-exec         │ Deprecated → colon    │
 │     │                          │ [appPath]                  │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 14  │ twenty exec -n <name>    │ twenty dev:fn-exec -n      │ Deprecated → colon    │
 │     │ [appPath]                │ <name> [appPath]           │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 15  │ twenty exec -u <id>      │ twenty dev:fn-exec -u <id> │ Deprecated → colon    │
 │     │ [appPath]                │  [appPath]                 │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 16  │ twenty exec -p <json>    │ twenty dev:fn-exec -p      │ Deprecated → colon    │
 │     │ [appPath]                │ <json> [appPath]           │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 17  │ twenty exec              │ twenty dev:fn-exec         │ Deprecated → colon    │
 │     │ --postInstall [appPath]  │ --postInstall [appPath]    │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 18  │ twenty exec --preInstall │ twenty dev:fn-exec         │ Deprecated → colon    │
 │     │  [appPath]               │ --preInstall [appPath]     │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 19  │ twenty add [entityType]  │ twenty dev:add             │ Deprecated → colon    │
 │     │                          │ [entityType]               │ command               │
 ├─────┼──────────────────────────┼────────────────────────────┼───────────────────────┤
 │ 20  │ twenty add --path <path> │ twenty dev:add --path      │ Deprecated → colon    │
 │     │  [entityType]            │ <path> [entityType]        │ command               │
 └─────┴──────────────────────────┴────────────────────────────┴───────────────────────┘

 App lifecycle commands

 ┌─────┬────────────────────────┬────────────────────────────┬─────────────────────────┐
 │  #  │      Old command       │        New command         │         Status          │
 ├─────┼────────────────────────┼────────────────────────────┼─────────────────────────┤
 │ 21  │ twenty publish         │ twenty app:publish         │ Deprecated → colon      │
 │     │ [appPath]              │ [appPath]                  │ command                 │
 ├─────┼────────────────────────┼────────────────────────────┼─────────────────────────┤
 │ 22  │ twenty publish --tag   │ twenty app:publish --tag   │ Deprecated → colon      │
 │     │ <tag> [appPath]        │ <tag> [appPath]            │ command                 │
 ├─────┼────────────────────────┼────────────────────────────┼─────────────────────────┤
 │ 23  │ twenty deploy          │ twenty app:publish         │ Deprecated → colon      │
 │     │ [appPath]              │ --private [appPath]        │ command + --private     │
 ├─────┼────────────────────────┼────────────────────────────┼─────────────────────────┤
 │ 24  │ twenty install         │ twenty app:install         │ Deprecated → colon      │
 │     │ [appPath]              │ [appPath]                  │ command                 │
 ├─────┼────────────────────────┼────────────────────────────┼─────────────────────────┤
 │ 25  │ twenty uninstall       │ twenty app:uninstall       │ Deprecated → colon      │
 │     │ [appPath]              │ [appPath]                  │ command                 │
 ├─────┼────────────────────────┼────────────────────────────┼─────────────────────────┤
 │ 26  │ twenty uninstall -y    │ twenty app:uninstall -y    │ Deprecated → colon      │
 │     │ [appPath]              │ [appPath]                  │ command                 │
 └─────┴────────────────────────┴────────────────────────────┴─────────────────────────┘

 Server commands

 ┌─────┬─────────────────────────┬─────────────────────────────┬──────────────────────┐
 │  #  │       Old command       │         New command         │        Status        │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 27  │ twenty server start     │ twenty docker:start         │ Deprecated → colon   │
 │     │                         │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 28  │ twenty server start -p  │ twenty docker:start -p      │ Deprecated → colon   │
 │     │ <port>                  │ <port>                      │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 29  │ twenty server start     │ twenty docker:start --test  │ Deprecated → colon   │
 │     │ --test                  │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 30  │ twenty server stop      │ twenty docker:stop          │ Deprecated → colon   │
 │     │                         │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 31  │ twenty server stop      │ twenty docker:stop --test   │ Deprecated → colon   │
 │     │ --test                  │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 32  │ twenty server status    │ twenty docker:status        │ Deprecated → colon   │
 │     │                         │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 33  │ twenty server status    │ twenty docker:status --test │ Deprecated → colon   │
 │     │ --test                  │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 34  │ twenty server logs      │ twenty docker:logs          │ Deprecated → colon   │
 │     │                         │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 35  │ twenty server logs -n   │ twenty docker:logs -n       │ Deprecated → colon   │
 │     │ <lines>                 │ <lines>                     │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 36  │ twenty server logs      │ twenty docker:logs --test   │ Deprecated → colon   │
 │     │ --test                  │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 37  │ twenty server reset     │ twenty docker:reset         │ Deprecated → colon   │
 │     │                         │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 38  │ twenty server reset     │ twenty docker:reset --test  │ Deprecated → colon   │
 │     │ --test                  │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 39  │ twenty server upgrade   │ twenty docker:upgrade       │ Deprecated → colon   │
 │     │ [version]               │ [version]                   │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 40  │ twenty server upgrade   │ twenty docker:upgrade       │ Deprecated → colon   │
 │     │ --test [version]        │ --test [version]            │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 41  │ twenty server           │ twenty app:catalog-sync  │ Deprecated → colon   │
 │     │ catalog-sync            │                             │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 42  │ twenty server           │ twenty app:catalog-sync  │ Deprecated → colon   │
 │     │ catalog-sync -r <name>  │ -r <name>                   │ syntax               │
 ├─────┼─────────────────────────┼─────────────────────────────┼──────────────────────┤
 │ 43  │ twenty catalog-sync     │ (removed)                   │ Removed (was already │
 │     │                         │                             │  deprecated)         │
 └─────┴─────────────────────────┴─────────────────────────────┴──────────────────────┘

 Remote commands

 ┌─────┬────────────────────────┬──────────────────────────┬──────────────────────────┐
 │  #  │      Old command       │       New command        │          Status          │
 ├─────┼────────────────────────┼──────────────────────────┼──────────────────────────┤
 │ 44  │ twenty remote add      │ twenty remote:add        │ Deprecated → colon       │
 │     │                        │                          │ syntax                   │
 ├─────┼────────────────────────┼──────────────────────────┼──────────────────────────┤
 │ 45  │ twenty remote add --as │ twenty remote:add --as   │ Deprecated → colon       │
 │     │  <name>                │ <name>                   │ syntax                   │
 ├─────┼────────────────────────┼──────────────────────────┼──────────────────────────┤
 │ 46  │ twenty remote add      │ twenty remote:add        │ Deprecated → colon       │
 │     │ --api-key <key>        │ --api-key <key>          │ syntax                   │
 ├─────┼────────────────────────┼──────────────────────────┼──────────────────────────┤
 │ 47  │ twenty remote add      │ twenty remote:add        │ Deprecated → colon       │
 │     │ --api-url <url>        │ --api-url <url>          │ syntax                   │
 ├─────┼────────────────────────┼──────────────────────────┼──────────────────────────┤
 │ 48  │ twenty remote add      │ twenty remote:add        │ Deprecated → colon       │
 │     │ --local                │ --local                  │ syntax                   │
 ├─────┼────────────────────────┼──────────────────────────┼──────────────────────────┤
 │ 49  │ twenty remote add      │ twenty remote:add --test │ Deprecated → colon       │
 │     │ --test                 │                          │ syntax                   │
 ├─────┼────────────────────────┼──────────────────────────┼──────────────────────────┤
 │ 50  │ twenty remote list     │ twenty remote:list       │ Deprecated → colon       │
 │     │                        │                          │ syntax                   │
 ├─────┼────────────────────────┼──────────────────────────┼──────────────────────────┤
 │ 51  │ twenty remote switch   │ twenty remote:use [name] │ Deprecated → colon       │
 │     │ [name]                 │                          │ syntax + renamed         │
 ├─────┼────────────────────────┼──────────────────────────┼──────────────────────────┤
 │ 52  │ twenty remote status   │ twenty remote:status     │ Deprecated → colon       │
 │     │                        │                          │ syntax                   │
 ├─────┼────────────────────────┼──────────────────────────┼──────────────────────────┤
 │ 53  │ twenty remote remove   │ twenty remote:remove     │ Deprecated → colon       │
 │     │ <name>                 │ <name>                   │ syntax                   │
 └─────┴────────────────────────┴──────────────────────────┴──────────────────────────┘
```

---------

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-05-20 15:12:39 +00:00
WeikoandGitHub 6e5e7963b5 fix(server): map PermissionsException to proper HTTP status on REST API (#20739)
## Summary

`PermissionsException` thrown by `SettingsPermissionGuard` (and other
permission code paths) was bubbling up through every typed REST
exception filter and landing in the global `UnhandledExceptionFilter`,
which falls back to **500** for anything that isn't an `HttpException`.
So a forbidden user (e.g. an API key whose role doesn't have
`DATA_MODEL`) calling `GET /rest/metadata/objects` got:
```
HTTP/1.1 500 Internal Server Error "Entity performing the request does not have permission"
```


GraphQL already had the right plumbing via
`permissionGraphqlApiExceptionHandler` (`ForbiddenError` → 403,
`UserInputError` → 400, `NotFoundError` → 404). This PR mirrors it on
the REST side.

## What

- New util `permissionRestApiExceptionCodeToHttpStatus` mapping every
`PermissionsExceptionCode` → HTTP status, with `assertUnreachable` to
force explicit handling of future codes.
- New filter `PermissionsRestApiExceptionFilter`
(`@Catch(PermissionsException)`) that delegates to
`HttpExceptionHandlerService.handleError(...)` with the resolved status.
- Wired `PermissionsRestApiExceptionFilter` (placed first, so the typed
filter wins over any sibling catch-all) into `@UseFilters(...)` of every
REST controller that uses `SettingsPermissionGuard` or whose service can
throw `PermissionsException`:
  - `object-metadata`, `field-metadata`, `webhook`, `api-key`
- `view`, `view-sort`, `view-group`, `view-filter`, `view-filter-group`,
`view-field`
  - `page-layout`, `page-layout-widget`, `page-layout-tab`
  - `front-component`, `ai-generate-text`
- Unit tests covering 403 / 400 / 404 / 500 mappings.

## Mapping

| Code | Status |
|------|--------|
| `PERMISSION_DENIED`, `NO_AUTHENTICATION_CONTEXT`,
`ROLE_LABEL_ALREADY_EXISTS`, `CANNOT_UNASSIGN_LAST_ADMIN`,
`CANNOT_UPDATE_SELF_ROLE`, `CANNOT_DELETE_LAST_ADMIN_USER`,
`ROLE_NOT_EDITABLE`, `CANNOT_ADD_OBJECT_PERMISSION_ON_SYSTEM_OBJECT`,
`CANNOT_ADD_FIELD_PERMISSION_ON_SYSTEM_OBJECT` | **403** |
| `INVALID_ARG`, `INVALID_SETTING`,
`CANNOT_GIVE_WRITING_PERMISSION_ON_NON_READABLE_OBJECT`,
`CANNOT_GIVE_WRITING_PERMISSION_WITHOUT_READING_PERMISSION`,
`ONLY_FIELD_RESTRICTION_ALLOWED`,
`FIELD_RESTRICTION_ONLY_ALLOWED_ON_READABLE_OBJECT`,
`FIELD_RESTRICTION_ON_UPDATE_ONLY_ALLOWED_ON_UPDATABLE_OBJECT`,
`EMPTY_FIELD_PERMISSION_NOT_ALLOWED`,
`ROLE_MUST_HAVE_AT_LEAST_ONE_TARGET`, `ROLE_CANNOT_BE_ASSIGNED_TO_USERS`
| **400** |
| `ROLE_NOT_FOUND`, `OBJECT_METADATA_NOT_FOUND`,
`FIELD_METADATA_NOT_FOUND`, `FIELD_PERMISSION_NOT_FOUND`,
`PERMISSION_NOT_FOUND` | **404** |
| All remaining "internal" codes (rethrown as-is in GraphQL) | **500** |

## Before
<img width="507" height="216" alt="Screenshot 2026-05-19 at 19 26 07"
src="https://github.com/user-attachments/assets/21d633aa-7ee8-4923-94e4-7ad57258a29e"
/>

## After
<img width="610" height="385" alt="Screenshot 2026-05-19 at 19 26 01"
src="https://github.com/user-attachments/assets/0103b7ee-7df7-4aef-999a-73c22901afd2"
/>
2026-05-20 13:02:58 +00:00
Félix MalfaitandGitHub a2acf88a57 feat(website): per-PR preview deploys via Worker versions (#20762)
## Summary
Adds review apps for the marketing site. Every PR that touches
`packages/twenty-website/**` or `packages/twenty-shared/**` gets a
per-version Worker preview URL, sticky-commented on the PR, auto-cleaned
up when the PR closes.

Same Cloudflare machinery skew protection rides on, just used for
previews — no extra plan, no extra services. Cleaner than the
GitHub-Actions-runner + Cloudflare-tunnel pattern: previews persist for
the life of the version, accessible from anywhere, no warm-up.

## Files
- **`.github/workflows/website-pr-preview.yaml`** — on PR
open/sync/reopen: builds the Worker with a per-PR `DEPLOYMENT_ID`, runs
`wrangler versions upload --tag pr-<N>` (no production traffic),
sticky-comments the preview URL. Skipped on fork PRs because GitHub
doesn't pass secrets to forks anyway.
- **`.github/workflows/website-pr-preview-cleanup.yaml`** — on PR close:
walks the Worker version list via the CF API, deletes anything tagged
`pr-<N>` (with message-based fallback if the annotation key changes),
updates the sticky comment.
- **`open-next.config.ts`** — `maxNumberOfVersions: 10 → 50` to leave
room for PR previews on top of skew protection's prod-version retention.

## How it looks on a PR

The bot leaves a sticky comment like:

> 🔍 **Website preview** is up at
**https://abc12345-twenty-website-dev.twentyhq.workers.dev**
>
> | | |
> |---|---|
> | Version | `abc12345-...` |
> | Commit | `<sha>` |
> | Bindings | shared with the `dev` Worker (R2 cache + secrets) |
>
> Updates on every push. Auto-deleted when the PR closes.

On close it becomes:

> 🧹 Website preview for this PR was cleaned up after close.

## Twenty repo credentials already provisioned
- `secret CLOUDFLARE_API_TOKEN` — same scoped token the `twenty-infra`
workflow uses
- `var CLOUDFLARE_ACCOUNT_ID` = `67b2bbe4381006564d2b0aa6ce6177be`
- `var CF_PREVIEW_DOMAIN` = `twentyhq` (no `.workers.dev` suffix —
OpenNext appends it;
[opennextjs-cloudflare#811](https://github.com/opennextjs/opennextjs-cloudflare/issues/811))

## Known limitations
- **Shared dev bindings**: PR previews use the dev Worker's R2 bucket +
secrets (Stripe test key, JWT private key). Fine for a read-mostly
marketing site; if two simultaneous PRs ever fight over ISR cache state
we can prefix R2 keys per-PR later.
- **Fork PRs don't get previews**. GitHub Actions doesn't pass
`secrets.*` to fork-PR runs (security), and the wrangler upload requires
the CF token. To enable forks, would need to switch to
`pull_request_target` and gate on a maintainer label — not done here
because the security tradeoff isn't worth it for a marketing-site
preview.
- **Version cap**: 50 versions is the new ceiling, and
`maxVersionAgeDays: 14` auto-prunes anything older. Cleanup-on-close
should keep us well under in steady state.

## Test plan
- [ ] CI on this PR triggers the preview workflow itself; check that the
sticky comment appears with a working URL
- [ ] Hit the URL, click around — should look like a fresh
marketing-site build with this PR's changes
- [ ] Close (don't merge) → cleanup workflow should run; sticky comment
switches to the "cleaned up" message; the version is gone from `wrangler
versions list --name twenty-website-dev`
2026-05-20 14:59:42 +02:00
Félix MalfaitandGitHub c002bc52bd fix(ci): repair preview-environment dispatch (use PAT, not GITHUB_TOKEN) (#20773)
## What
One-line token swap on the same-repo dispatch step in
[`preview-env-dispatch.yaml`](.github/workflows/preview-env-dispatch.yaml#L40):
`secrets.GITHUB_TOKEN` → `secrets.CI_PRIVILEGED_DISPATCH_TOKEN`.

## Why
Regression from [#20476](https://github.com/twentyhq/twenty/pull/20476)
("security: harden CI against supply-chain attacks"), merged 2026-05-12.
That PR replaced

```yaml
uses: peter-evans/repository-dispatch@v2
with:
  token: ${{ secrets.GITHUB_TOKEN }}
  ...
```

with a raw `gh api` call but kept `GITHUB_TOKEN`:

```yaml
env:
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
  gh api repos/"$REPOSITORY"/dispatches -f event_type=preview-environment ...
```

The auto-provisioned `GITHUB_TOKEN` can't fire `repository_dispatch` via
`gh api` even when the workflow declares `permissions: contents: write`.
The action used a different code path that worked; the CLI requires a
token with `repo` scope. So every dispatch from this workflow has
returned `403 Resource not accessible by integration` since that PR
merged — except for runs the `author_association` / `preview-app` label
gate skips entirely (which then show "success" because no jobs ran).

Recent failed example:
https://github.com/twentyhq/twenty/actions/runs/26162974597/job/76959379235?pr=20769

## The fix
`secrets.CI_PRIVILEGED_DISPATCH_TOKEN` already exists in repo secrets
and is **already used** by the immediately-following cross-repo dispatch
step in the same file. Using it for the same-repo dispatch too matches
the surrounding code and is consistent with the original hardening
intent (use a scoped PAT, not the auto-provisioned token).

## Test plan
- [ ] Merge this PR
- [ ] Next PR open / sync / reopen on a member's branch → check that
`Preview Environment Dispatch` succeeds (no 403)
- [ ] Confirm `Preview Environment Keep Alive` workflow gets triggered
(the downstream effect of the dispatch)
- [ ] Confirm the tunnel URL sticky comment lands on the PR

Discovered while testing an unrelated PR
([#20762](https://github.com/twentyhq/twenty/pull/20762)). Independent
fix.
2026-05-20 14:57:57 +02:00
martmullandGitHub 127fb2a470 Increase size of tarball upload (#20767)
- check size while reading stream instead of checking after reading all
stream
- move MAX_TARBALL_UPLOAD_SIZE_BYTES to config variables
- increase MAX_TARBALL_UPLOAD_SIZE_BYTES default from 50Mb to 100Mb
2026-05-20 12:39:11 +00:00
Paul RastoinandGitHub 3d49c17e34 [CONNECTED_ACCOUNT_BREAKING_CHANGE] Unify connected account permissions (#20732)
# Introduction
This PR is a followup of https://github.com/twentyhq/twenty/pull/20673

It aims to unify the authentication/permissions layer with all the
connectedAccount interactions across the application

## Deprecate
- findAll
- findById

## Email sync
An user can only sync the message of his own connected account

## Workflow email
- Related https://github.com/twentyhq/private-issues/issues/478
- Only reauthorize owned account
2026-05-20 11:36:58 +00:00
b454ad2aea fix(workflow): restore initial input fields on code step creation (#20756)
## Summary

- Fixes a regression from #20208 where creating a new CODE workflow step
shows no input fields
- The split-triggers PR removed `SEED_LOGIC_FUNCTION_INPUT_SCHEMA` and
replaced `toolInputSchema` with `workflowActionTriggerSettings`, but
`CodeStepBuildService.createCodeStepLogicFunction` was not updated to
pass the seed schema — causing `logicFunctionInput` to default to `{}`
and no fields to render
- Adds `SEED_WORKFLOW_ACTION_TRIGGER_SETTINGS` constant (matching the
seed template's `{ a: string, b: number }` params) and passes it when
creating the seed logic function

## Test plan

- [x] Unit test updated to assert `logicFunctionInput` contains `{ a:
null, b: null }` on code step creation
- [x] Create a new CODE step in the workflow builder and verify input
fields `a` and `b` appear immediately

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 11:21:17 +00:00
fb47e4497a i18n - docs translations (#20764)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-05-20 13:21:44 +02:00
Félix MalfaitandGitHub 00fad657f4 feat(website): enable OpenNext skew protection + tune CF cache (#20760)
## Summary
The original goal of this whole migration: **cross-deployment skew is
now handled by OpenNext's per-version routing instead of by users having
to refresh.**

A client holding a stale tab from deployment X requests assets with
`?dpl=X` — the Worker compares X to the current `DEPLOYMENT_ID`, looks
it up in `CF_DEPLOYMENT_MAPPING`, and routes to the matching old Worker
version via its per-version preview URL
(`<old-version>-twenty-website-<env>.twentyhq.workers.dev`). The old
version serves the old assets / RSC payloads / Server Actions
consistently.

**Verified end-to-end on dev**:
| | Marker in HTML |
|---|---|
| Current Worker (`twenty-main.com/`) | `9npeiytir8EPOtW71cqDZ` |
| Stale request (`twenty-main.com/?dpl=<previous-deploy-id>`) |
`B9OC_TNl1vaGcJ5oUUty6` |
| Direct hit on old preview URL | `B9OC_TNl1vaGcJ5oUUty6` ← matches the
skew-routed response |

## Changes

**`open-next.config.ts`** — enable skew protection
```ts
const baseConfig = defineCloudflareConfig({ incrementalCache: r2IncrementalCache });
export default {
  ...baseConfig,
  cloudflare: {
    ...baseConfig.cloudflare,
    skewProtection: {
      enabled: true,
      maxNumberOfVersions: 10,
      maxVersionAgeDays: 14,
    },
  },
};
```
(`defineCloudflareConfig` doesn't accept `skewProtection` directly — has
to be merged in)

**`next.config.ts`** — `deploymentId: process.env.DEPLOYMENT_ID`. CI
sets `DEPLOYMENT_ID` per-build; Next bakes it into prerendered HTML,
`?dpl=…` on asset URLs, Server Actions, and RSC fetch headers.

**`wrangler.jsonc`**:
- `compatibility_date: 2026-04-15` (was `2025-01-15`; build was warning)
- `assets.run_worker_first: true` — Worker must intercept asset requests
so the skew handler can route stale `/_next/static/*` to the old
version. CF edge cache absorbs hot paths so this isn't a 5×
billable-invocation tax
- `preview_urls: true` — required; skew routes via the per-version
preview URL which only exists when previews are enabled
- Per-env `services: [{ binding: WORKER_SELF_REFERENCE, service:
twenty-website-<env> }]` — OpenNext's recommended setup for
fire-and-forget ISR revalidation
- Per-env `vars`: `CF_WORKER_NAME` + `CF_PREVIEW_DOMAIN` (bare
`twentyhq`, *not* `twentyhq.workers.dev` — OpenNext appends
`.workers.dev` itself, see
[opennextjs-cloudflare#811](https://github.com/opennextjs/opennextjs-cloudflare/issues/811))
- Kept `global_fetch_strictly_public` in compat flags — without it, CF's
optimised intra-account routing self-loops the cross-version fetch and
522s out. With it, the fetch takes the public-Internet path which routes
correctly.

**`public/_headers`** — deleted (with `run_worker_first: true` the
assets pipeline doesn't process it; Next sets the same `Cache-Control:
immutable` on `/_next/static/*` anyway).

## Companion infra PR
https://github.com/twentyhq/twenty-infra/pull/__ — wires the four CF env
vars (`DEPLOYMENT_ID`, `CF_WORKER_NAME`, `CF_PREVIEW_DOMAIN`,
`CF_ACCOUNT_ID`, `CF_WORKERS_SCRIPTS_API_TOKEN`) into the deploy
workflow.

## Known limitation
Skew routing only works for Worker versions deployed AFTER this PR
(older versions don't have `preview_urls: true` and don't have
`DEPLOYMENT_ID` bindings OpenNext can read). Users on tabs older than
the first post-merge deploy still fall through to the current Worker
(same behaviour as today).

OpenNext marks `skewProtection` as **experimental** in their type docs
("might break on minor releases") — worth keeping an eye on.
2026-05-20 12:47:12 +02:00
c800eccc65 Slack workflow connector (#20427)
https://github.com/user-attachments/assets/5a746414-988b-473c-9401-b8863a3e1c15


https://github.com/user-attachments/assets/0cdebdb1-f7c8-43cb-beef-f279387b6ce9



https://github.com/user-attachments/assets/df31c631-0781-42d8-8e6e-e5a16573ee3b



https://github.com/user-attachments/assets/6adaeae4-f3c9-4a5f-b0df-50c1f9a78428

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: martmull <martmull@hotmail.fr>
2026-05-20 10:21:22 +00:00
nitinandGitHub a26fe3bb65 docs(sdk): document DatabaseEventPayload and simplify its type (#20754)
closes
https://discord.com/channels/1130383047699738754/1505967920163983502

Update logic-function docs to match the real `DatabaseEventPayload`
shape.

The docs now show database event payloads as record-level events with
`recordId` and `properties.before/after/diff/updatedFields`, including
compact examples for created, updated, and destroyed events. Route
payload type imports now use the preferred `twenty-sdk/logic-function`
surface.

Also clean up the shared payload type wrapper so it models event
metadata without over-promising actor fields; `userId`,
`userWorkspaceId`, and `workspaceMemberId` remain optional through the
underlying event type.
2026-05-20 09:22:58 +00:00
EtienneandGitHub 8d81496625 fix(ai-chat) - fixes on cost display (#20750)
- total cost conversion
- update metrics at message end
2026-05-20 08:50:23 +00:00
martmullandGitHub f1b7c21b6c Update create twenty app scaffolded front component (#20733)
- Replace inline SVG icons with proper Avatar and icon components
(IconBox, IconHierarchy, IconLayout, IconSettingsAutomation) from
twenty-sdk/ui in the scaffolded front component
  template
- Strip trailing slashes from workspace/API URLs in both
create-twenty-app CLI and twenty-sdk remote commands to prevent
malformed requests
  - Fix the application settings link to navigate to #installed anchor
- Bump twenty-sdk, twenty-client-sdk, and create-twenty-app versions to
2.6.0

<img width="1512" height="824" alt="image"
src="https://github.com/user-attachments/assets/8561d7bb-3458-46c4-b01e-664321634b4c"
/>
2026-05-20 08:23:10 +00:00
Félix MalfaitandGitHub f630ce34fe feat(website): mirror prod hostname pattern on dev (apex + www) (#20753)
## Summary
Drops the `website.` subdomain on dev entirely and serves the marketing
site from the bare zone + `www`, mirroring how prod is served at
`twenty.com` + `www.twenty.com`.

Also fixes a latent root-path substitution bug in the existing www→apex
redirect that was masked on prod by a CF-level redirect.

## What changes
- `wrangler.jsonc` env.dev routes: `twenty-main.com` (apex) +
`www.twenty-main.com` (was `website.twenty-main.com`)
- `next.config.ts`: extends host-based www→apex redirect to also cover
`www.twenty-main.com`, and adds explicit `source: '/'` rules for both
prod + dev before the catch-all `source: '/:path*'` (the `:path*`
parameter doesn't substitute properly when it matches the empty root
path against an absolute destination URL — Next.js leaves the literal
`:path*` in the `Location` header)

## Live verification (after redeploy)
| URL | Status | Notes |
|---|---|---|
| `https://twenty-main.com/` | 200 | `x-opennext: 1`, `x-nextjs-cache:
HIT` |
| `https://twenty-main.com/pricing` | 200 | Worker SSR |
| `https://www.twenty-main.com/` | 308 → `https://twenty-main.com/` |
Root-redirect fix applied |
| `https://www.twenty-main.com/pricing` | 308 →
`https://twenty-main.com/pricing` | Path preserved |
| `https://twenty.com/` | 200 | Unchanged |
| `https://www.twenty.com/` | 301 → `https://twenty.com/` | Still routed
via CF-level redirect, now also covered by the new explicit Next rule as
a defense-in-depth |
| `https://website.twenty-main.com/` | 503 | DNS record removed by
wrangler when route was deleted; hostname effectively retired |

## Companion infra PR
https://github.com/twentyhq/twenty-infra/pull/__ —
`cloudflare/website/dev.env` + `docs/4-environments.md` updated to the
new URL; also bundles the CI fix that should have landed in #683 (was
pushed too late).
2026-05-20 09:54:44 +02:00
martmullandGitHub 7ebcbe8801 Unify oAuth success and failure screen with autorize page (#20746)
Goal, matching authorize page design

<img width="2062" height="1376" alt="image"
src="https://github.com/user-attachments/assets/93d0f77a-c769-4a32-b41b-16459378314f"
/>


## Before

<img width="1540" height="942" alt="image"
src="https://github.com/user-attachments/assets/4de64f37-8519-4fdc-9388-70d98a69663e"
/>


## After

<img width="962" height="657" alt="image"
src="https://github.com/user-attachments/assets/c4fd19aa-13e3-452e-b6b7-c10202cb1edf"
/>

<img width="705" height="437" alt="image"
src="https://github.com/user-attachments/assets/e1f743f1-a862-4629-a3d0-c8e62e429e04"
/>
2026-05-20 07:43:34 +00:00
b821061526 fix(create-twenty-app): preserve .yarnrc.yml in template (#20623)
**Source:** https://sonarly.com/issue/37981?type=bug

## Summary

New apps created with `create-twenty-app@2.5.0` can fail at `yarn twenty
dev` with `Could not resolve "twenty-sdk/define"`, blocking onboarding
for app developers.

## Root cause

Proximate cause: manifest module loading in the SDK fails to resolve
`twenty-sdk/define` when the generated app uses Yarn PnP (no
`node_modules` tree), and esbuild is invoked with normal Node-style
resolution.

- The failing path is `extractManifestFromFile()` → `loadModule()` in
`packages/twenty-sdk/src/cli/utilities/build/manifest/manifest-extract-config-from-file.ts`,
which calls `esbuild.build({ bundle: true, ... })` and does not
stub/mock `twenty-sdk/define` [ref: read
`manifest-extract-config-from-file.ts`].
- The scaffolded template imports `twenty-sdk/define` in
`src/application-config.ts` and `src/default-role.ts` [ref: grep in
`packages/create-twenty-app/src/constants/template/src/*`].
- If esbuild cannot resolve that import from the app environment, the
exact error matches the issue: `src/application-config.ts:1:34: ERROR:
Could not resolve "twenty-sdk/define"`.

Triggering cause (why now): `create-twenty-app@2.5.0` (the current npm
`latest`) ships a template tarball without `.yarnrc.yml`, so new
projects silently default to Yarn PnP instead of `node-modules`.

Evidence:
- Source template contains `.yarnrc.yml` with `nodeLinker: node-modules`
[ref: read
`packages/create-twenty-app/src/constants/template/.yarnrc.yml`].
- Published npm tarball for `create-twenty-app-2.5.0.tgz` does **not**
contain `template/.yarnrc.yml` (but does contain renamed
`gitignore`/`github`) [ref: tarball listing command output: `hasYarnrc:
false`].
- Dotfile-preservation logic in `copyBaseApplicationProject()` only
renames `gitignore` and `github`; it does not preserve `.yarnrc.yml`
[ref: read `packages/create-twenty-app/src/utils/app-template.ts`].
- `npm dist-tags` shows `latest: 2.5.0`, so users following docs with
`@latest` receive this broken scaffold path now [ref: npm registry
query].

Why this is attributable to a specific change:
- Commit `15eb3e7edccdf4e9770a00a07bfbd026420f7c3b` introduced
dotfile-preservation mechanics for template publish
(`gitignore`/`github`) but left out `.yarnrc.yml`, creating the
regression window for newly scaffolded apps [ref: `git show --stat
15eb3e7...`, `git blame` on `renameDotfiles()`].

## Fix

Implemented a targeted fix in `create-twenty-app` so `.yarnrc.yml` is
preserved through npm packaging the same way `.gitignore` and `.github`
are handled.

What changed:
1) Template dotfile preservation
- Removed
`packages/create-twenty-app/src/constants/template/.yarnrc.yml`
- Added `packages/create-twenty-app/src/constants/template/yarnrc.yml`
with identical content:
  - `nodeLinker: node-modules`

This avoids npm stripping the file from the published tarball.

2) Scaffold rename logic
- Updated `packages/create-twenty-app/src/utils/app-template.ts`:
- Added `{ from: 'yarnrc.yml', to: '.yarnrc.yml' }` in
`renameDotfiles()`
  - Updated progress text and inline comment to include `.yarnrc.yml`

So generated apps reliably restore `.yarnrc.yml` after template copy.

3) Regression test
- Updated
`packages/create-twenty-app/src/utils/__tests__/app-template.spec.ts`:
  - Added a test asserting `yarnrc.yml` is renamed to `.yarnrc.yml`
  - Added a small constant for the test path

This locks the behavior and prevents reintroducing the publish omission
regression.

Validation notes:
- Attempted to run the focused Jest test, but execution failed due
missing workspace dependency state (`@nx/jest/preset` / node_modules
state not installed in this environment).

## Original request

fix(create-twenty-app): preserve .yarnrc.yml in template

_Created by Sonarly by autonomous analysis (run 43375)._

---------

Co-authored-by: sonarly-bot <sonarly@sonarly.com>
Co-authored-by: martmull <martmull@hotmail.fr>
2026-05-20 07:39:53 +00:00
f3aadbbb66 chore(server): drop leftover favorite and favoriteFolder workspace objects (#20744)
## Summary

- Adds a 2.7.0 workspace upgrade command
`upgrade:2-7:drop-favorite-objects` that removes the legacy `favorite`
and `favoriteFolder` object metadata (and their workspace tables) from
every active or suspended workspace.
- The records were migrated to `navigationMenuItem` in the 1.17/1.18
upgrades and the entity code was deleted in #19536, but the
per-workspace metadata rows were never cleaned up — so they still
surface in the "Existing objects" settings list and expose stale CRUD
tools to the AI/MCP layer (e.g. the model can hallucinate
`create_favorite_folder` against a real-looking schema).

## Implementation notes

- Modeled on
[`upgrade:2-3:drop-message-direction-field`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/database/commands/upgrade-version-command/2-3/2-3-workspace-command-1777400000000-drop-message-direction-field.command.ts),
but at object granularity.
- Uses `ObjectMetadataService.deleteOneObject({ isSystemBuild: true })`
so all cascading is handled by the existing pipeline: field metadata,
indexes, relation fields on other workspace entities, command menu
items, and the workspace data tables. Views and orphaned
`navigationMenuItem` rows pointing at favorite views are removed by the
existing `onDelete: 'CASCADE'` FKs.
- Deletion order: `favorite` first (holds a relation to
`favoriteFolder`), then `favoriteFolder`.
- Both objects are flagged `isSystem: true`, hence `isSystemBuild: true`
on the call.
- Idempotent: workspaces where the object is already absent are logged
and skipped.
- Honors `--dry-run`.
- Universal identifiers are hard-coded because the matching
`STANDARD_OBJECTS` entries were deleted in #19536.

## Test plan

- [ ] Run on a workspace that still has `favorite` / `favoriteFolder` in
`core.objectMetadata` (verify in prod-like DB beforehand) and confirm
both objects, their fields, indexes, relation fields on linked objects,
views, and the workspace data tables are gone after running.
- [ ] Re-run on the same workspace — confirm it logs "already absent"
and exits clean (idempotency).
- [ ] Run on a workspace where the objects don't exist (e.g. fresh
local) — confirm clean no-op.
- [ ] Run with \`--dry-run\` first — confirm log output and no DB
mutations.
- [ ] Confirm the "Existing objects" settings page no longer lists
Favorites / Favorite Folders after the migration.

## Safety check before rollout

Before running in prod, verify no workspace has live (non-soft-deleted)
favorite data that didn't make it to \`navigationMenuItem\`:

\`\`\`sql
-- Per workspace
SELECT count(*) FROM workspace_xxx.favorite WHERE "deletedAt" IS NULL;
\`\`\`

Should be ~0 in workspaces that ran the 1.17 / 1.18 migrations.

---------

Co-authored-by: prastoin <paul@twenty.com>
2026-05-20 07:21:52 +00:00
e494bc7006 chore: sync AI model catalog from models.dev (#20751)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

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

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

Co-authored-by: FelixMalfait <6399865+FelixMalfait@users.noreply.github.com>
2026-05-20 09:06:14 +02:00
martmullandGitHub 91e0e07af4 fix: render PAGE_LAYOUT nav items with standard icon tile and compute… (#20743)
## Before

<img width="434" height="583" alt="image"
src="https://github.com/user-attachments/assets/a336620f-3f85-4d20-ba58-b20d779ba3b9"
/>


## after

<img width="539" height="600" alt="image"
src="https://github.com/user-attachments/assets/f88e4793-e1a1-4215-baf1-289c413d9dac"
/>
2026-05-20 06:17:39 +00:00
martmullandGitHub 7ab6f5719f Update default widget gridPosition (#20740)
move DEFAULT_WIDGET_SIZE to twenty-shared and use it in sync application
manifest
2026-05-20 06:15:53 +00:00
Félix MalfaitandGitHub d17393e91d feat(website): migrate dev hostname website-new.twenty-main.com → website.twenty-main.com (#20747)
## Summary
Last "-new" trace in the source repo, follow-up to the rename in #20745.
The dev Worker custom domain swaps from `website-new.twenty-main.com` to
`website.twenty-main.com`, matching the prod pattern (no "-new"
anywhere).

## Live operations already performed
- Deleted the legacy CNAME at `website.twenty-main.com` that pointed at
the dev EKS NLB (record id `52b4a4174dfd382ecf38111b7f08e642`, was the
Docusaurus dev deploy that had been 503'ing)
- Redeployed `twenty-website-dev` Worker — Wrangler provisioned the new
custom domain via the CF API
- Verified `https://website.twenty-main.com/` returns 200 with
`x-opennext: 1` and `x-nextjs-cache: HIT`

The old hostname `website-new.twenty-main.com` is now unbound; Wrangler
removed its DNS record when the route disappeared from this file.
Visitors get 522, which is the desired state for a retired hostname.

## Companion infra PR
https://github.com/twentyhq/twenty-infra/pull/683 — removes
`charts/dev/apps/website` Helm chart (the legacy Docusaurus deploy) +
ArgoCD app, updates `cloudflare/website/dev.env` and
`docs/4-environments.md`.

## Out of scope
- Legacy `website.twenty-staging.com` and `website.twenty.com` are still
alive serving Docusaurus content. Decommissioning those is a separate
decision (those URLs may still be linked externally).
2026-05-19 23:55:08 +02:00
Félix MalfaitandGitHub 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
Félix MalfaitandGitHub 24a836cc7d feat(website-new): add Cloudflare Workers deployment via OpenNext (#20741)
## Summary
- Adds `@opennextjs/cloudflare` adapter so `packages/twenty-website-new`
can deploy to Cloudflare Workers
- Two environments (`dev` / `prod`) wired via `wrangler.jsonc` env
blocks
- Existing Docker / EKS build path is untouched in this PR — the cutover
happens in the paired infra PR

Pairs with: https://github.com/twentyhq/twenty-infra/pull/__ (to be
opened, will swap CI + decommission Helm/ArgoCD)

## Files added
- `packages/twenty-website-new/wrangler.jsonc` — Worker config,
`nodejs_compat` flag, R2 incremental cache, Cloudflare `IMAGES` binding,
env-specific routes (`website-new.twenty-main.com` for dev; `twenty.com`
+ `www.twenty.com` for prod)
- `packages/twenty-website-new/open-next.config.ts` — minimal config
using `r2IncrementalCache`
- `packages/twenty-website-new/.dev.vars.example` — local secrets
template (`STRIPE_SECRET_KEY`, `ENTERPRISE_JWT_PRIVATE_KEY`)
- `packages/twenty-website-new/public/_headers` — immutable cache
headers for `/_next/static/*`

## Files modified
- `packages/twenty-website-new/package.json` — adds
`@opennextjs/cloudflare`, `wrangler` to devDeps; adds `preview`,
`deploy:dev`, `deploy:prod`, `cf-typegen` scripts
- `packages/twenty-website-new/next.config.ts` — calls
`initOpenNextCloudflareForDev()` (no-op outside `next dev`); preserves
Linaria CommonJS export
- `packages/twenty-website-new/.gitignore` — ignores `.open-next/`,
`.wrangler/`, `.dev.vars`, generated `cloudflare-env.d.ts`

## Compatibility notes
- `enterprise-jwt.ts` uses Node `crypto` + `Buffer` — works on Workers
with the `nodejs_compat` flag (compat date 2025-01-15, well past the
2024-09-23 minimum)
- `sharp` stays as a build-time dep (Next/Image asset processing);
runtime image optimization routes through the Cloudflare `IMAGES`
binding
- Linaria runs at build time, unaffected
- Stripe SDK is HTTP-based, fine on Workers

## One-time CF setup required before this PR is useful
The infra PR adds GitHub Actions wiring, but the Cloudflare account
itself needs:
- R2 buckets: `twenty-website-cache-dev`, `twenty-website-cache-prod`
- Worker secrets per env (via `wrangler secret put --env <dev|prod>`):
`STRIPE_SECRET_KEY`, `ENTERPRISE_JWT_PRIVATE_KEY`
- An API token with `Workers Scripts:Edit`, `Workers R2 Storage:Edit`,
`Zone DNS:Edit` on the `twenty.com` zone — stored as
`CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` in the infra repo's
GitHub secrets
- The Cloudflare Images subscription enabled on the account (binding is
configured; \$5/mo + per-transformation pricing)

## Follow-up (out of scope)
- Rename `packages/twenty-website-new` → `packages/twenty-website` and
delete the legacy `packages/twenty-website` (mechanical, separate PR to
keep this diff reviewable)
- Remove `packages/twenty-docker/twenty-website-new/` once the EKS
deploy is fully retired

## Test plan
- [ ] `yarn install` resolves new devDeps cleanly
- [ ] `cd packages/twenty-website-new && npx next build` still succeeds
(Linaria path untouched)
- [ ] `yarn preview` builds the Worker locally and serves on
http://localhost:8788
- [ ] Smoke: `/`, `/pricing`, an enterprise-key-signing flow (needs
`.dev.vars` populated)
- [ ] After CF resources are provisioned: `yarn deploy:dev` succeeds and
`website-new.twenty-main.com` serves the new Worker
2026-05-19 23:23:54 +02:00
Charles BochetandGitHub 1a9f786e42 refactor(filters): pass fieldMetadataItems array to dispatcher (#20737)
## Summary

Alternative to #20717. Same goal (clean up the filter dispatcher API
after #20670) but smaller and follows the codebase's "pass data, not
behavior" style.

The dispatcher takes a `fieldMetadataItems: FieldShared[]` array
directly instead of a `findFieldMetadataItemById: (id) => FieldShared |
undefined` callback. The util builds the id lookup internally — once per
call, used for both source-field and relation-target-field lookups. No
new types, no separate hydration step.

## What changes

**`twenty-shared`**
- `computeRecordGqlOperationFilter` /
`turnRecordFilterIntoRecordGqlOperationFilter` /
`turnRecordFilterGroupsIntoGqlOperationFilter`: replace
`findFieldMetadataItemById` param with `fieldMetadataItems` /
`fieldMetadataItemById` (internal Map).
- Remove the exported `FindFieldMetadataItemById` type.
- `turnAnyFieldFilterIntoRecordGqlFilter`: rename its internal
`fieldById` Map for consistency.
- Tests updated to pass arrays.

**Frontend (15 call sites)**
- Switch from `fieldMetadataItemByIdMapSelector` to
`flattenedFieldMetadataItemsSelector`.
- Pass `fieldMetadataItems: flattenedFieldMetadataItems` to the
dispatcher.
- `useFindManyRecordsSelectedInContextStore` keeps the Map selector
because it still does a per-filter lookup for the soft-delete check.

**Server (5 call sites)**
- Pass
`Object.values(flatFieldMetadataMaps.byUniversalIdentifier).filter(isDefined)`.

## Why this over #20717

#20717 moves resolution into a separate hydration step + introduces a
`HydratedRecordFilter` type. The bug that #20717 originally surfaced was
Sentry catching 4 critical runtime errors during review
(`fieldMetadataItemByIdMap` declared but not passed). The added type and
the explicit hydration boundary are extra surface area for not much
benefit — the existing API was a callback wrapping a Map at every call
site, and the natural simplification is to just pass the Map (or its
array) directly.

Net diff: **196 insertions, 203 deletions** (~7 lines net removed). 32
files.

## Test plan
- [x] Shared filter unit tests pass (461 tests)
- [x] Frontend filter/context-store tests pass (13 tests)
- [x] Frontend typecheck passes
- [x] Server typecheck passes
- [x] Lint passes (frontend + server)
- [ ] Integration tests on #20670 still pass — workflow find-records +
chart-data with relation-traversal filter still work end-to-end through
the new array param
2026-05-19 22:49:53 +02:00
WeikoandGitHub 265d2edc83 Fix QueryRunnerAlreadyReleasedError in sign-in-up service (#20734)
## Context

When signing up on a new workspace,
`SignInUpService.signUpOnNewWorkspace`
manually drove a transaction with `createQueryRunner` /
`startTransaction` /
`commitTransaction` / `rollbackTransaction` / `release`.

If the underlying Postgres connection dropped mid-transaction
(`idle_in_transaction_session_timeout`, server-side termination), the
`pg`
client's `'error'` event fires. TypeORM's connect-time listener responds
by
calling `release()` on the `QueryRunner`, which sets `isReleased = true`
but
deliberately does **not** touch `isTransactionActive`.

The `catch` branch then hit:

```ts
if (queryRunner.isTransactionActive) {
  await queryRunner.rollbackTransaction(); // throws QueryRunnerAlreadyReleasedError
}
throw error;
```
Error from Sentry
```typescript
QueryRunnerAlreadyReleasedError: Query runner already released. Cannot run queries anymore.
    at PostgresQueryRunner.query (.../PostgresQueryRunner.js:177)
    at PostgresQueryRunner.rollbackTransaction (.../PostgresQueryRunner.js:167)
    at SignInUpService.signUpOnNewWorkspace (.../sign-in-up.service.js:370)
```

## Changes

Replaced the hand-rolled transaction with
this.dataSource.transaction(...).
TypeORM's built-in wrapper already does what we need:

- starts/commits/rolls back the transaction
- wraps rollback in try { ... } catch { /* ignore */ }, so a connection
drop no longer masks the real error
- releases the QueryRunner unconditionally

## Note
Other fix would have been to do this
```typescript
  if (queryRunner.isTransactionActive && **!queryRunner.isReleased**) {
     try {
       await queryRunner.rollbackTransaction();
     } catch {
```
2026-05-19 15:32:36 +00:00
d345a6b2d6 Twenty fireflies integration (#20618)
Co-authored-by: martmull <martmull@hotmail.fr>
2026-05-19 15:23:36 +00:00
f8605763dd i18n - docs translations (#20736)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-05-19 17:25:12 +02:00
WeikoandGitHub ac432d3195 Add @WasRemovedInUpgrade decorator (#20729)
## Summary

Adds the symmetric counterpart to `@WasIntroducedInUpgrade` for the
upgrade-aware ORM. Today the framework can describe "this column will
exist once upgrade X applies" but not "this
column will stop existing once upgrade X applies". Plain field deletion
only works when nothing writes to the table during the mid-state window
between the binary booting and the drop
migration completing for a given workspace — fine for sparse tables
(`DropWorkspaceVersionColumn`, `DropPostgresCredentialsTable`), risky
for hot-write tables.

This PR ships the primitive on its own so the upcoming
`rolePermissionFlag.flag` drop has the framework support it needs. No
in-tree consumer yet — coverage is via unit tests against
synthetic entities.

### What's in it

- **New `@WasRemovedInUpgrade({ upgradeCommandName })` decorator**
(class- or property-scope) — mirrors `@WasIntroducedInUpgrade`, uses the
shared
`defineUpgradeMetadataOnClassOrProperty` helper, exposes class +
property getters.
- **`resolveEntityShapeAtUpgradeCursor`** now folds applied-removals
into the existing `hiddenPropertyNames` set. Intro-pending and
removal-applied share one hide bucket — both ask
TypeORM for the same thing.
- **`UpgradeAwareEntityMetadataAdapter`** now disables `isSelect`,
`isInsert`, **and** `isUpdate` for any hidden column, restoring
canonical values when the column comes back.
Previously only `isSelect` was flipped, which left an
INSERT-into-nonexistent-column hole the intro path was tacitly relying
on application code to avoid; this PR closes that hole for
both directions.
- **`validateUpgradeAwareEntityDecorators`** validates
`@WasRemovedInUpgrade` `upgradeCommandName` references, and surfaces a
new `removal-before-introduction` problem when a property
has both decorators with the removal step preceding the introduction
step.
2026-05-19 14:57:05 +00:00
e463a09e17 chore(server): remove unused CommandLogger from command module (#20638)
## Summary

This PR removes the unused `CommandLogger` implementation located at:

```
/commands/command-logger.ts
```


The Command application context is bootstrapped using `LoggerService`
from:

```ts
import { LoggerService } from 'src/engine/core-modules/logger/logger.service';
...
const loggerService = app.get(LoggerService);
...
// Inject our logger
app.useLogger(loggerService);
...

```

So `CommandLogger` is not imported, injected, or referenced anywhere in
the Command execution flow and is safe to remove.

## Note
There is another `CommandLogger` class at:
```
/database/commands/logger.ts
```

This one is only used within `database-command` module and is unrelated
to the Command module logger being removed in this PR.

Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
2026-05-19 14:44:34 +00:00
nitinandGitHub 83b10ad698 fix(server): sync command menu item availability expressions on existing workspaces (#20719)
Two fixes via one workspace command:

1. Gates 5 standard command menu items behind `pageType == "INDEX_PAGE"`
--
   `importRecords`, `exportView`, `seeDeletedRecords`, `createNewView`, 
`hideDeletedRecords`. They currently appear (and crash or do nothing) on
   RECORD_PAGE.

2. Fixes Edit Layout missing from older workspaces -- root cause is 
`conditionalAvailabilityExpression` drift between source-of-truth
constants
and the workspace DB (e.g. #20556 removed a feature flag from the
expression
   without syncing existing workspaces).

The 2-6 workspace command iterates all `STANDARD_COMMAND_MENU_ITEMS` and
reconciles any `conditionalAvailabilityExpression` that differs from the
constant. Idempotent -- already-correct rows are skipped.

Deferred: `deleteRecords` doesn't refetch the current record after
deletion
on RECORD_PAGE (mutation fires but UI shows stale state until refresh)
--
different fix shape (frontend handler), separate PR.
2026-05-19 14:42:40 +00:00
Abdul RahmanandGitHub 08e7e4819b use declared outputSchema for logic-function steps (#20679)
When a logic function declares
`workflowActionTriggerSettings.outputSchema`, use it as the step's
initial output schema so downstream steps can pick variables without
first running the Test tab. A successful test run still overrides the
schema with the inferred shape, preserving "test wins" behavior. Falls
back to the existing "Generate Function Output" LINK placeholder when no
schema is declared (custom code steps, older functions).


https://github.com/user-attachments/assets/af9c45ed-d623-4234-be9f-46812fd06e2e
2026-05-19 14:41:00 +00:00
EtienneandGitHub 827f24df2b fix(ai) - add ai model preferences fallback (#20704)
**Problem** 
AI_MODEL_PREFERENCES, JSON env var is not supported +
IS_CONFIG_VARIABLES_IN_DB_ENABLED=false in twenty cloud server
-> No option to set AI_MODEL_PREFERENCES

**Solution** 
AI_MODEL_PREFERENCES supports three override sources beyond the
hardcoded code defaults, in priority order:

- DB (IS_CONFIG_VARIABLES_IN_DB_ENABLED=true), the only writable source;
admin-panel mutations persist here
- ENV not usable in Twenty Cloud, which does not handle JSON-format env
vars
- **Introduced in this PR** --> File
(AI_MODEL_PREFERENCES_STORAGE_PATH), a read-only startup fallback, the
only viable override in Cloud/self-managed deployments where DB config
is disabled and JSON env vars are unsupported.
2026-05-19 13:19:24 +00:00
martmullGitHubcubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
d5ff9eb515 Create twenty app improvements (#20688)
create-twenty-app updates:
- remove --example option
- sync --once when scaffolding an applicaiton
- rename --api-url option to --workspace-url
- create a standalone page when scaffolding an app
<img width="1494" height="765" alt="image"
src="https://github.com/user-attachments/assets/0e35ed0c-b0aa-466c-9f56-7939294fd2cf"
/>

---------

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-05-19 13:12:47 +00:00
71a7a3c42d i18n - website translations (#20724)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-05-19 15:17:23 +02:00
cbac2ba0bf i18n - translations (#20725)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-05-19 15:15:56 +02:00