Commit Graph

13092 Commits

Author SHA1 Message Date
Charles Bochet fb85d29d64 chore: disable dependabot version-update PRs (#22119)
## What

Sets `open-pull-requests-limit: 0` on all three npm entries in
`.github/dependabot.yml`, disabling routine version-update PRs.

## Why

Dependabot's `open-pull-requests-limit` is a *concurrent* cap, not a
weekly throughput cap. With a large dependency backlog, every time a PR
is closed or merged Dependabot backfills the freed slot with the next
outdated dependency — producing an endless trickle of individual PRs
rather than the intended "few per week".

Setting the limit to `0` stops version-update PRs entirely.

## Impact

- **Routine version-bump PRs:** disabled across root + public/internal
apps.
- **Security advisory updates:** unaffected — these are a separate
Dependabot channel not governed by this limit, so vulnerability patches
still open automatically.

The existing `groups:` config on the apps entries is now inert but left
in place, so version updates can be re-enabled later by simply raising
the limit.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22119?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-24 18:34:03 +02:00
Thomas des Francs 9ed0d85954 Update workspace domain card layout (#22108)
## What changed
- Render the Workspace domain cards side by side instead of stacked.
- Keep both domain cards full width within the row.
- Rename the section title from `Workspace Domain` to `Workspace
domain`.
- Use the `www` globe icon for Subdomain while keeping the standard
globe for Custom Domain.
- Export `IconWorldWww` from `twenty-ui/icon` for front-end consumers.

<img width="1029" height="220" alt="image"
src="https://github.com/user-attachments/assets/83ad8a29-d63c-42bb-9233-7754d1e7adf7"
/>


## Why
This matches the updated settings design for the Workspace domain
section and makes the Subdomain and Custom Domain options scan as
sibling actions.

## Validation
- Ran focused `oxlint` and `oxfmt` checks on edited files.
- Built `twenty-ui` successfully.
- Ran `twenty-front` typecheck successfully.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22108?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-24 16:24:39 +00:00
martmull cc21160d83 fix(server): scope server-route target dispatch to the resolver's application (#22101)
## Summary

Security follow-up to #22002 (server-exposed logic functions). That PR's
`ServerRouteTriggerService` resolved the **target** logic function by
`(universalIdentifier, workspaceId)` alone, with no application scoping:

```ts
// before
const logicFunction = await this.logicFunctionRepository.findOne({
  where: { universalIdentifier, workspaceId },
});
```

Both values come straight from the resolver's return value. Because the
only gate was "a function with that UID exists in that workspace", a
resolver (owner-workspace code) could dispatch to a logic function
belonging to a **different application**, or to a workspace where its
own application is **not installed**, and read the target's return value
back in the HTTP response
(`buildRouteTriggerResponse(targetResult.data)`) — a cross-tenant /
cross-application isolation break.

The implementation this replaced (the deleted
`server-webhook-trigger.service.ts`) enforced both checks: the app had
to be installed in the target workspace, and the target function was
scoped by `applicationId`. This PR restores that guarantee.

## Changes

- **Scope the target dispatch to the resolver's
`applicationRegistration`.** `handle()` captures
`resolver.application.applicationRegistration.id` and threads it into
the target `findOne` as `application: { applicationRegistrationId }`
(joining the `application` relation). The target must belong to the same
registration — which also guarantees the application is installed in the
resolved workspace (no installed copy → no matching row). The resolver
lookup itself is unchanged.
- **Stop leaking raw internal error messages.** The `runFunction` catch
block logged the raw executor/`Error.message` *and* returned it to the
(unauthenticated) caller. It now logs the detail server-side and returns
a generic, per-code message.
- **Tests**: fixtures carry an `applicationRegistration.id`; new cases
assert the target lookup is scoped to the resolver's registration, that
a resolver not linked to a registration is rejected, and that a platform
error returns the generic message instead of the raw internal text.

Feature remains gated behind `IS_SERVER_LOGIC_FUNCTION_ENABLED` (default
off).

## Test plan
- [ ] `npx jest server-route-trigger` (verifying locally; environment
dependency install was flaky)
- [ ] `npx nx typecheck twenty-server`
- [ ] `npx nx lint:diff-with-main twenty-server`

https://claude.ai/code/session_014TNdRvQjjR8wN6MLTJ7rTE

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

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22101?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-24 16:22:01 +00:00
martmull b5958fb331 Enforce server route app configuration requirements (#22091)
## Summary
This PR enforces that applications exposing server route logic functions
must be claimed (have an owner workspace) and installed on that owner
workspace to be considered "configured". This ensures server route
resolvers have a valid workspace context to execute in.

## Key Changes
- **ApplicationRegistrationVariableService**: Enhanced
`isConfiguredBatch()` to check server route configuration in addition to
required variables
- Added `ApplicationEntity` repository injection to track app
installations
- Implemented `isServerRouteConfigured()` private method that validates:
- If app exposes server route logic functions, it must have an owner
workspace
- If it has an owner workspace, it must be installed on that workspace
  - Added comprehensive test suite covering all configuration scenarios

- **ServerRouteTriggerService**: Removed feature flag check
(`IS_SERVER_LOGIC_FUNCTION_ENABLED`)
  - Deleted `TwentyConfigService` dependency
  - Removed feature disabled exception handling
- Server route triggers are now always enabled (gated by app
configuration instead)

- **Configuration**: Removed `IS_SERVER_LOGIC_FUNCTION_ENABLED` config
variable from `ConfigVariables`

- **Exception handling**: Removed `FEATURE_DISABLED` exception code from
`ServerRouteTriggerExceptionCode`

- **UI & Documentation**: Updated messaging and docs to reflect that
server route apps require claiming and installation on owner workspace

## Implementation Details
- Server route configuration is checked alongside required variable
validation in `isConfiguredBatch()`
- Uses efficient batch queries with `Promise.all()` to fetch variables,
registrations, and installations in parallel
- Installs are tracked via a Set of `${registrationId}:${workspaceId}`
keys for O(1) lookup
- Apps without server route functions are unaffected by this change

https://claude.ai/code/session_01Ub3K25p2q4XE1LW1LGJbkG

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22091?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-24 16:20:05 +00:00
dependabot[bot] 9574476395 chore(deps): bump @scalar/api-reference-react from 0.9.46 to 0.9.48 (#22115)
Bumps
[@scalar/api-reference-react](https://github.com/scalar/scalar/tree/HEAD/packages/api-reference-react)
from 0.9.46 to 0.9.48.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/scalar/scalar/blob/main/packages/api-reference-react/CHANGELOG.md">@​scalar/api-reference-react's
changelog</a>.</em></p>
<blockquote>
<h2>0.9.48</h2>
<h2>0.9.47</h2>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/scalar/scalar/commits/HEAD/packages/api-reference-react">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@scalar/api-reference-react&package-manager=npm_and_yarn&previous-version=0.9.46&new-version=0.9.48)](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>

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22115?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. -->

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 16:19:16 +00:00
dependabot[bot] 5bb3ff4e43 chore(deps): bump @sentry/react from 10.51.0 to 10.60.0 (#22111)
Bumps [@sentry/react](https://github.com/getsentry/sentry-javascript)
from 10.51.0 to 10.60.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/getsentry/sentry-javascript/releases">@​sentry/react's
releases</a>.</em></p>
<blockquote>
<h2>10.60.0</h2>
<h3>Other Changes</h3>
<ul>
<li>feat(cloudflare): Add R2 bucket auto-instrumentation (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21327">#21327</a>)</li>
<li>feat(core): Add <code>bindScopeToEmitter</code> to bind a scope to
an event emitter (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21594">#21594</a>)</li>
<li>feat(deps): Bump <code>@​hapi/wreck</code> from 18.1.0 to 18.1.2 (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21178">#21178</a>)</li>
<li>fix(browser): Ensure <code>url.full</code> and <code>http.url</code>
attributes have the same values on <code>http.client</code> spans (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21660">#21660</a>)</li>
<li>fix(server-utils): Avoid directly importing
<code>tracingChannel</code> for Node v18 compatibility (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21662">#21662</a>)</li>
<li>fix(server-utils): Remove optional <code>vite</code> peer dependency
(<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21677">#21677</a>)</li>
</ul>
<!-- raw HTML omitted -->
<ul>
<li>chore: Add bundler-plugins to craft (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21701">#21701</a>)</li>
<li>chore: Cleanup unused imports of <code>@opentelemetry/core</code>
(<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21679">#21679</a>)</li>
<li>fix(bundler-plugins): Integration with monorepo build (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21479">#21479</a>)</li>
<li>ref(core): Gate updateName() custom source on an OTel inference
brand (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21649">#21649</a>)</li>
<li>ref(core/opentelemetry): Move OTel span data inference from
<code>captureSpan</code> to <code>SentrySpanProcessor</code> (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21648">#21648</a>)</li>
<li>ref(node): Remove unused sql-common helper and
<code>@opentelemetry/core</code> dep (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21688">#21688</a>)</li>
<li>ref(node): Streamline kafkajs instrumentation (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21647">#21647</a>)</li>
<li>ref(node): Streamline undici (node-fetch) instrumentation (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21650">#21650</a>)</li>
<li>ref(vercel-edge): Drop unused
<code>@opentelemetry/semantic-conventions</code> dependency (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21691">#21691</a>)</li>
<li>ref(vercel-edge): Remove <code>@opentelemetry/resources</code>
dependency (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21690">#21690</a>)</li>
</ul>
<!-- raw HTML omitted -->
<h2>Bundle size 📦</h2>
<table>
<thead>
<tr>
<th>Path</th>
<th>Size</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@​sentry/browser</code></td>
<td>26.83 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> - with treeshaking flags</td>
<td>25.3 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Tracing)</td>
<td>44.89 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Tracing + Span Streaming)</td>
<td>46.6 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Tracing, Profiling)</td>
<td>49.56 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Tracing, Replay)</td>
<td>83.18 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Tracing, Replay) - with
treeshaking flags</td>
<td>73.02 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Tracing, Replay with
Canvas)</td>
<td>87.76 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Tracing, Replay, Feedback)</td>
<td>100.12 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Feedback)</td>
<td>43.61 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. sendFeedback)</td>
<td>31.5 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. FeedbackAsync)</td>
<td>36.52 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Metrics)</td>
<td>27.87 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Logs)</td>
<td>28.11 KB</td>
</tr>
<tr>
<td><code>@​sentry/browser</code> (incl. Metrics &amp; Logs)</td>
<td>28.78 KB</td>
</tr>
<tr>
<td><code>@​sentry/react</code></td>
<td>28.59 KB</td>
</tr>
<tr>
<td><code>@​sentry/react</code> (incl. Tracing)</td>
<td>47.14 KB</td>
</tr>
<tr>
<td><code>@​sentry/vue</code></td>
<td>31.86 KB</td>
</tr>
<tr>
<td><code>@​sentry/vue</code> (incl. Tracing)</td>
<td>46.71 KB</td>
</tr>
<tr>
<td><code>@​sentry/svelte</code></td>
<td>26.85 KB</td>
</tr>
</tbody>
</table>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md">@​sentry/react's
changelog</a>.</em></p>
<blockquote>
<h2>10.60.0</h2>
<h3>Other Changes</h3>
<ul>
<li>feat(cloudflare): Add R2 bucket auto-instrumentation (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21327">#21327</a>)</li>
<li>feat(core): Add <code>bindScopeToEmitter</code> to bind a scope to
an event emitter (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21594">#21594</a>)</li>
<li>feat(deps): Bump <code>@​hapi/wreck</code> from 18.1.0 to 18.1.2 (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21178">#21178</a>)</li>
<li>fix(browser): Ensure <code>url.full</code> and <code>http.url</code>
attributes have the same values on <code>http.client</code> spans (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21660">#21660</a>)</li>
<li>fix(server-utils): Avoid directly importing
<code>tracingChannel</code> for Node v18 compatibility (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21662">#21662</a>)</li>
<li>fix(server-utils): Remove optional <code>vite</code> peer dependency
(<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21677">#21677</a>)</li>
</ul>
<!-- raw HTML omitted -->
<ul>
<li>chore: Add bundler-plugins to craft (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21701">#21701</a>)</li>
<li>chore: Cleanup unused imports of <code>@opentelemetry/core</code>
(<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21679">#21679</a>)</li>
<li>fix(bundler-plugins): Integration with monorepo build (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21479">#21479</a>)</li>
<li>ref(core): Gate updateName() custom source on an OTel inference
brand (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21649">#21649</a>)</li>
<li>ref(core/opentelemetry): Move OTel span data inference from
<code>captureSpan</code> to <code>SentrySpanProcessor</code> (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21648">#21648</a>)</li>
<li>ref(node): Remove unused sql-common helper and
<code>@opentelemetry/core</code> dep (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21688">#21688</a>)</li>
<li>ref(node): Streamline kafkajs instrumentation (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21647">#21647</a>)</li>
<li>ref(node): Streamline undici (node-fetch) instrumentation (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21650">#21650</a>)</li>
<li>ref(vercel-edge): Drop unused
<code>@opentelemetry/semantic-conventions</code> dependency (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21691">#21691</a>)</li>
<li>ref(vercel-edge): Remove <code>@opentelemetry/resources</code>
dependency (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21690">#21690</a>)</li>
</ul>
<!-- raw HTML omitted -->
<h2>10.59.0</h2>
<h3>Important Changes</h3>
<ul>
<li>
<p><strong>feat(react-router): Add support for React Router v8 (<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21633">#21633</a>)</strong></p>
<p>The SDK now supports React Router v8, in both the framework and SPA
(<code>@sentry/react</code>) modes.</p>
</li>
<li>
<p><strong>feat(react): Add version-agnostic React Router SPA exports
(<a
href="https://redirect.github.com/getsentry/sentry-javascript/pull/21633">#21633</a>)</strong></p>
<p><code>@sentry/react</code> now exports version-agnostic wrappers for
React Router v6+ SPA instrumentation.
The new exports replace the version-specific
<code>V6</code>/<code>V7</code> variants, which are now deprecated:</p>
<table>
<thead>
<tr>
<th>Deprecated</th>
<th>New</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>reactRouterV6BrowserTracingIntegration</code> /
<code>V7</code></td>
<td><code>reactRouterBrowserTracingIntegration</code></td>
</tr>
<tr>
<td><code>withSentryReactRouterV6Routing</code> / <code>V7</code></td>
<td><code>wrapReactRouterRouting</code></td>
</tr>
<tr>
<td><code>wrapCreateBrowserRouterV6</code> / <code>V7</code></td>
<td><code>wrapCreateBrowserRouter</code></td>
</tr>
<tr>
<td><code>wrapCreateMemoryRouterV6</code> / <code>V7</code></td>
<td><code>wrapCreateMemoryRouter</code></td>
</tr>
<tr>
<td><code>wrapUseRoutesV6</code> / <code>V7</code></td>
<td><code>wrapUseRoutes</code></td>
</tr>
</tbody>
</table>
<p>The deprecated exports continue to work and will be removed in the
next major version.</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/4548afc27908146dca23db7a6722de714119909c"><code>4548afc</code></a>
test: Make bundler plugins tests work after release</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/499c327ea9240c6daa183ff76a734ce89117c230"><code>499c327</code></a>
chore: fix yarn.lock</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/4d26c19e7367d870e2e0758ba51def5d41637b52"><code>4d26c19</code></a>
release: 10.60.0</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/cc7dea46c1915b4a2a7d39e21248c938f2ed800c"><code>cc7dea4</code></a>
Merge pull request <a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/21703">#21703</a>
from getsentry/prepare-release/10.60.0</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/bcef5d9c1cfb9d58f10fa5e9f5dfb42be1e4ff9c"><code>bcef5d9</code></a>
meta(changelog): Update changelog for 10.60.0</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/8285066e1cfb58493d1434f895bd43f986e4d917"><code>8285066</code></a>
chore: Add bundler-plugins to craft (<a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/21701">#21701</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/b953c6f74d9ac83eecbae0dc65cd09fedabda7a4"><code>b953c6f</code></a>
fix(browser): Ensure <code>url.full</code> and <code>http.url</code>
attributes have the same value...</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/b54777a859f5e8b7bcb90ab218bef1a55d133d7a"><code>b54777a</code></a>
ref(vercel-edge): Drop unused
<code>@opentelemetry/semantic-conventions</code> dependenc...</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/2e29cd32769084a46a5ce66b36a49b1295741a79"><code>2e29cd3</code></a>
ref(vercel-edge): Remove <code>@opentelemetry/resources</code>
dependency (<a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/21690">#21690</a>)</li>
<li><a
href="https://github.com/getsentry/sentry-javascript/commit/c5e245f869eca352e5d11833dd9b3264da448ac9"><code>c5e245f</code></a>
ref(node): Remove unusued sql-common helper and
<code>@opentelemetry/core</code> dep (<a
href="https://redirect.github.com/getsentry/sentry-javascript/issues/2">#2</a>...</li>
<li>Additional commits viewable in <a
href="https://github.com/getsentry/sentry-javascript/compare/10.51.0...10.60.0">compare
view</a></li>
</ul>
</details>
<br />


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

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

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

---

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

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


</details>

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22111?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. -->

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 18:03:37 +02:00
dependabot[bot] f2bed8359d chore(deps): bump @nestjs/schedule from 6.1.0 to 6.1.3 (#22112)
Bumps [@nestjs/schedule](https://github.com/nestjs/schedule) from 6.1.0
to 6.1.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/nestjs/schedule/releases">@​nestjs/schedule's
releases</a>.</em></p>
<blockquote>
<h2>6.1.3</h2>
<h2>What's Changed</h2>
<ul>
<li>feat(cron): add initialDelay option to defer first job execution by
<a
href="https://github.com/kyungseopk1m"><code>@​kyungseopk1m</code></a>
in <a
href="https://redirect.github.com/nestjs/schedule/pull/2251">nestjs/schedule#2251</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/nestjs/schedule/compare/6.1.2...6.1.3">https://github.com/nestjs/schedule/compare/6.1.2...6.1.3</a></p>
<h2>Release 6.1.2</h2>
<ul>
<li>Merge pull request <a
href="https://redirect.github.com/nestjs/schedule/issues/2247">#2247</a>
from kyungseopk1m/feat/cron-initial-delay (a57ce2c)</li>
<li>chore(deps): update dependency prettier to v3.8.3 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2248">#2248</a>)
(bb3490d)</li>
<li>feat(cron): add initialDelay option to defer first job execution
(1c5677f)</li>
<li>Merge pull request <a
href="https://redirect.github.com/nestjs/schedule/issues/2245">#2245</a>
from nestjs/renovate/nest-monorepo (59046bd)</li>
<li>Merge pull request <a
href="https://redirect.github.com/nestjs/schedule/issues/2246">#2246</a>
from nestjs/renovate/oxlint-monorepo (be4eee3)</li>
<li>chore(deps): update dependency oxlint to v1.60.0 (32a9ce2)</li>
<li>chore(deps): update nest monorepo to v11.1.19 (7d3844f)</li>
<li>chore: migrate to oxlint, vitest, ts6 (29de71b)</li>
<li>chore(deps): update dependency globals to v17.5.0 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2244">#2244</a>)
(6c62cca)</li>
<li>chore(deps): update dependency sinon to v21.1.2 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2243">#2243</a>)
(ee3b31a)</li>
<li>chore(deps): update dependency sinon to v21.1.1 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2241">#2241</a>)
(eba9799)</li>
<li>Merge pull request <a
href="https://redirect.github.com/nestjs/schedule/issues/2242">#2242</a>
from nestjs/renovate/prettier-3.x (c3ad0f7)</li>
<li>chore(deps): update dependency prettier to v3.8.2 (798e2a9)</li>
<li>Merge pull request <a
href="https://redirect.github.com/nestjs/schedule/issues/2199">#2199</a>
from nestjs/renovate/cimg-node-24.x (a05354a)</li>
<li>chore(deps): update dependency typescript-eslint to v8.58.1 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2240">#2240</a>)
(0367ac1)</li>
<li>chore(deps): update dependency eslint to v10.2.0 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2239">#2239</a>)
(fa93e06)</li>
<li>chore(deps): update nest monorepo to v11.1.18 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2238">#2238</a>)
(8cd4c02)</li>
<li>chore(deps): update dependency <code>@​types/node</code> to v24.12.2
(<a
href="https://redirect.github.com/nestjs/schedule/issues/2237">#2237</a>)
(01482df)</li>
<li>chore(deps): update dependency <code>@​types/sinon</code> to v21.0.1
(<a
href="https://redirect.github.com/nestjs/schedule/issues/2236">#2236</a>)
(f05b5bd)</li>
<li>chore(deps): update dependency ts-jest to v29.4.9 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2235">#2235</a>)
(af545e6)</li>
<li>chore(deps): update dependency typescript-eslint to v8.58.0 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2233">#2233</a>)
(4dad22a)</li>
<li>chore(deps): update node.js to v24.14.1 (28db9bc)</li>
<li>chore(deps): update dependency eslint to v10.1.0 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2232">#2232</a>)
(413f390)</li>
<li>chore(deps): update nest monorepo to v11.1.17 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2230">#2230</a>)
(46c2bc5)</li>
<li>chore(deps): update dependency typescript-eslint to v8.57.1 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2231">#2231</a>)
(8fd063b)</li>
<li>chore(deps): update dependency sinon to v21.0.3 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2229">#2229</a>)
(1671ad9)</li>
<li>chore(deps): update commitlint monorepo to v20.5.0 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2228">#2228</a>)
(2ecd2f1)</li>
<li>chore(deps): update dependency lint-staged to v16.4.0 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2227">#2227</a>)
(aa0de01)</li>
<li>chore(deps): update commitlint monorepo to v20.4.4 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2226">#2226</a>)
(75034fe)</li>
<li>chore(deps): update dependency lint-staged to v16.3.3 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2225">#2225</a>)
(f1c7d31)</li>
<li>chore(deps): update dependency jest to v30.3.0 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2224">#2224</a>)
(1a208d4)</li>
<li>chore(deps): update dependency typescript-eslint to v8.57.0 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2223">#2223</a>)
(60dd2c9)</li>
<li>chore(deps): update dependency eslint to v10.0.3 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2221">#2221</a>)
(791b6ba)</li>
<li>chore(deps): update dependency <code>@​eslint/eslintrc</code> to
v3.3.5 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2220">#2220</a>)
(0da1ca7)</li>
<li>chore(deps): update dependency <code>@​types/node</code> to v24.12.0
(<a
href="https://redirect.github.com/nestjs/schedule/issues/2219">#2219</a>)
(934a93e)</li>
<li>chore(deps): update nest monorepo to v11.1.16 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2218">#2218</a>)
(5f44e9b)</li>
<li>chore(deps): update dependency sinon to v21.0.2 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2217">#2217</a>)
(b807746)</li>
<li>chore(deps): update dependency lint-staged to v16.3.2 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2216">#2216</a>)
(4ca32bd)</li>
<li>chore(deps): update commitlint monorepo to v20.4.3 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2215">#2215</a>)
(d3ceb76)</li>
<li>chore(deps): update nest monorepo to v11.1.15 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2214">#2214</a>)
(b084ffc)</li>
<li>chore(deps): update dependency lint-staged to v16.3.1 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2213">#2213</a>)
(8a201b2)</li>
<li>chore(deps): update dependency globals to v17.4.0 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2212">#2212</a>)
(6f61793)</li>
<li>chore(deps): update dependency lint-staged to v16.3.0 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2211">#2211</a>)
(aa9213a)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/nestjs/schedule/commit/059f19678aac04fc4132b1aeaebd7a9ae4f34e30"><code>059f196</code></a>
Merge pull request <a
href="https://redirect.github.com/nestjs/schedule/issues/2249">#2249</a>
from nestjs/renovate/release-it-20.x</li>
<li><a
href="https://github.com/nestjs/schedule/commit/557730ee8b898a0e2b03cdd5b207e176b60f8b1e"><code>557730e</code></a>
Merge pull request <a
href="https://redirect.github.com/nestjs/schedule/issues/2251">#2251</a>
from kyungseopk1m/feat/cron-initial-delay-v2</li>
<li><a
href="https://github.com/nestjs/schedule/commit/14f5b80a16f2ce25c77a2f6de9370705b27a2acb"><code>14f5b80</code></a>
feat(cron): add initialDelay option to defer first job execution</li>
<li><a
href="https://github.com/nestjs/schedule/commit/536367da7d59609b3595d440101fc24aaefb7cb5"><code>536367d</code></a>
chore(deps): update dependency release-it to v20</li>
<li><a
href="https://github.com/nestjs/schedule/commit/57e2861f5e8cf5e9e3a709a2918f478d03e57aa5"><code>57e2861</code></a>
Merge pull request <a
href="https://redirect.github.com/nestjs/schedule/issues/2250">#2250</a>
from nestjs/revert-2247-feat/cron-initial-delay</li>
<li><a
href="https://github.com/nestjs/schedule/commit/e08f457e4bddc83801d7bf0c60aff4a821290c9f"><code>e08f457</code></a>
Revert &quot;feat(cron): add initialDelay option to defer first job
execution&quot;</li>
<li><a
href="https://github.com/nestjs/schedule/commit/3198abea06f82b658b5bc4aa1dee6018c92cf04b"><code>3198abe</code></a>
chore(): release v6.1.2</li>
<li><a
href="https://github.com/nestjs/schedule/commit/a57ce2c329b0662cffd56b16d71fb9da3b84c743"><code>a57ce2c</code></a>
Merge pull request <a
href="https://redirect.github.com/nestjs/schedule/issues/2247">#2247</a>
from kyungseopk1m/feat/cron-initial-delay</li>
<li><a
href="https://github.com/nestjs/schedule/commit/bb3490dde2c3852463f231c3c556dd6d5b3a06d7"><code>bb3490d</code></a>
chore(deps): update dependency prettier to v3.8.3 (<a
href="https://redirect.github.com/nestjs/schedule/issues/2248">#2248</a>)</li>
<li><a
href="https://github.com/nestjs/schedule/commit/1c5677f46f100b03e5ae867306f089ba3381fab0"><code>1c5677f</code></a>
feat(cron): add initialDelay option to defer first job execution</li>
<li>Additional commits viewable in <a
href="https://github.com/nestjs/schedule/compare/6.1.0...6.1.3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@nestjs/schedule&package-manager=npm_and_yarn&previous-version=6.1.0&new-version=6.1.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>

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22112?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. -->

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 18:03:13 +02:00
dependabot[bot] 6a7458f20d chore(deps): bump @e2b/code-interpreter from 2.6.0 to 2.6.1 (#22106)
Bumps
[@e2b/code-interpreter](https://github.com/e2b-dev/code-interpreter/tree/HEAD/js)
from 2.6.0 to 2.6.1.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/e2b-dev/code-interpreter/commit/fe3e5db60ba8f1b13623289a1b17a6f7e1a18f67"><code>fe3e5db</code></a>
Throw descriptive error when sandbox is killed mid-request (<a
href="https://github.com/e2b-dev/code-interpreter/tree/HEAD/js/issues/291">#291</a>)</li>
<li><a
href="https://github.com/e2b-dev/code-interpreter/commit/efadb49cc87e06766bdb1cc6f33d3c54cd3e2607"><code>efadb49</code></a>
[skip ci] Release new versions</li>
<li>See full diff in <a
href="https://github.com/e2b-dev/code-interpreter/commits/@e2b/code-interpreter@2.6.1/js">compare
view</a></li>
</ul>
</details>
<br />


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

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

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

---

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

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


</details>

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22106?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. -->

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 15:45:33 +00:00
dependabot[bot] e9d67a4bb3 chore(deps-dev): bump @storybook/addon-a11y from 10.4.1 to 10.4.6 (#22103)
Bumps
[@storybook/addon-a11y](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/a11y)
from 10.4.1 to 10.4.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/releases">@​storybook/addon-a11y's
releases</a>.</em></p>
<blockquote>
<h2>v10.4.6</h2>
<h2>10.4.6</h2>
<ul>
<li>CSF: Allow partial globals overrides in story and meta annotations -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/34985">#34985</a>,
thanks <a
href="https://github.com/TheSeydiCharyyev"><code>@​TheSeydiCharyyev</code></a>!</li>
<li>Dependencies: Upgrade esbuild - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35157">#35157</a>,
thanks <a
href="https://github.com/Kakadus"><code>@​Kakadus</code></a>!</li>
</ul>
<h2>v10.4.5</h2>
<h2>10.4.5</h2>
<ul>
<li>Core: Rework AI checklist feature gate - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35053">#35053</a>,
thanks <a
href="https://github.com/Sidnioulz"><code>@​Sidnioulz</code></a>!</li>
<li>Preview: Stop mixed CSF3+4 stories getting core annotations injected
twice - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35094">#35094</a>,
thanks <a
href="https://github.com/JReinhold"><code>@​JReinhold</code></a>!</li>
</ul>
<h2>v10.4.4</h2>
<h2>10.4.4</h2>
<ul>
<li>Telemetry: Add timeout to event-log POST to prevent build hang - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35085">#35085</a>,
thanks <a
href="https://github.com/badams"><code>@​badams</code></a>!</li>
</ul>
<h2>v10.4.3</h2>
<h2>10.4.3</h2>
<ul>
<li>Addon Docs: Fix Primary and Controls blocks not rendering in custom
MDX pages - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34496">#34496</a>,
thanks <a
href="https://github.com/NYCU-Chung"><code>@​NYCU-Chung</code></a>!</li>
<li>Core: Respect !dev tag on MDX docs in sidebar - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35031">#35031</a>,
thanks <a
href="https://github.com/JReinhold"><code>@​JReinhold</code></a>!</li>
<li>React: Add support for resolving subcomponents attached as
properties of a parent component - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34967">#34967</a>,
thanks <a
href="https://github.com/yatishgoel"><code>@​yatishgoel</code></a>!</li>
<li>UI: Prevent docs page scroll reset on HMR re-render - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35021">#35021</a>,
thanks <a
href="https://github.com/LongTangGithub"><code>@​LongTangGithub</code></a>!</li>
</ul>
<h2>v10.4.2</h2>
<h2>10.4.2</h2>
<ul>
<li>Bug: Fix Windows command resolution for non-Node package managers -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/33534">#33534</a>,
thanks <a
href="https://github.com/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!</li>
<li>Build: Upgrade type-fest to latest version 5.6.0 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34791">#34791</a>,
thanks <a
href="https://github.com/tobiasdiez"><code>@​tobiasdiez</code></a>!</li>
<li>CSF: Fix parsing of string literal export names - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34901">#34901</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Publish: Add npm provenance attestations - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34936">#34936</a>,
thanks <a
href="https://github.com/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md">@​storybook/addon-a11y's
changelog</a>.</em></p>
<blockquote>
<h2>10.4.6</h2>
<ul>
<li>CSF: Allow partial globals overrides in story and meta annotations -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/34985">#34985</a>,
thanks <a
href="https://github.com/TheSeydiCharyyev"><code>@​TheSeydiCharyyev</code></a>!</li>
<li>Dependencies: Upgrade esbuild - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35157">#35157</a>,
thanks <a
href="https://github.com/Kakadus"><code>@​Kakadus</code></a>!</li>
</ul>
<h2>10.4.5</h2>
<ul>
<li>Core: Rework AI checklist feature gate - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35053">#35053</a>,
thanks <a
href="https://github.com/Sidnioulz"><code>@​Sidnioulz</code></a>!</li>
<li>Preview: Stop mixed CSF3+4 stories getting core annotations injected
twice - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35094">#35094</a>,
thanks <a
href="https://github.com/JReinhold"><code>@​JReinhold</code></a>!</li>
</ul>
<h2>10.4.4</h2>
<ul>
<li>Telemetry: Add timeout to event-log POST to prevent build hang - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35085">#35085</a>,
thanks <a
href="https://github.com/badams"><code>@​badams</code></a>!</li>
</ul>
<h2>10.4.3</h2>
<ul>
<li>Addon Docs: Fix Primary and Controls blocks not rendering in custom
MDX pages - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34496">#34496</a>,
thanks <a
href="https://github.com/NYCU-Chung"><code>@​NYCU-Chung</code></a>!</li>
<li>Core: Respect !dev tag on MDX docs in sidebar - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35031">#35031</a>,
thanks <a
href="https://github.com/JReinhold"><code>@​JReinhold</code></a>!</li>
<li>React: Add support for resolving subcomponents attached as
properties of a parent component - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34967">#34967</a>,
thanks <a
href="https://github.com/yatishgoel"><code>@​yatishgoel</code></a>!</li>
<li>UI: Prevent docs page scroll reset on HMR re-render - <a
href="https://redirect.github.com/storybookjs/storybook/pull/35021">#35021</a>,
thanks <a
href="https://github.com/LongTangGithub"><code>@​LongTangGithub</code></a>!</li>
</ul>
<h2>10.4.2</h2>
<ul>
<li>Bug: Fix Windows command resolution for non-Node package managers -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/33534">#33534</a>,
thanks <a
href="https://github.com/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!</li>
<li>Build: Upgrade type-fest to latest version 5.6.0 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34791">#34791</a>,
thanks <a
href="https://github.com/tobiasdiez"><code>@​tobiasdiez</code></a>!</li>
<li>CSF: Fix parsing of string literal export names - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34901">#34901</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Publish: Add npm provenance attestations - <a
href="https://redirect.github.com/storybookjs/storybook/pull/34936">#34936</a>,
thanks <a
href="https://github.com/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/storybookjs/storybook/commit/5496a4270da7f3a8e0203185792685cba671fdc5"><code>5496a42</code></a>
Bump version from &quot;10.4.5&quot; to &quot;10.4.6&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/48e7b20074222ed926d14fb6c678c2edfc86ee7b"><code>48e7b20</code></a>
Bump version from &quot;10.4.4&quot; to &quot;10.4.5&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/5adebe753f29d414d1e214e935c94d6e5451861f"><code>5adebe7</code></a>
Bump version from &quot;10.4.3&quot; to &quot;10.4.4&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/624e6187fd462e56719cbd80c1b4bfb67b68fc89"><code>624e618</code></a>
Bump version from &quot;10.4.2&quot; to &quot;10.4.3&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/298dea20c6370e5c670178d88a79fc9e9ff436b2"><code>298dea2</code></a>
Bump version from &quot;10.4.1&quot; to &quot;10.4.2&quot; [skip
ci]</li>
<li>See full diff in <a
href="https://github.com/storybookjs/storybook/commits/v10.4.6/code/addons/a11y">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@storybook/addon-a11y&package-manager=npm_and_yarn&previous-version=10.4.1&new-version=10.4.6)](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>

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22103?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. -->

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 15:45:11 +00:00
dependabot[bot] fef53b9915 chore(deps): bump react-error-boundary from 4.0.13 to 4.1.2 (#22105)
Bumps
[react-error-boundary](https://github.com/bvaughn/react-error-boundary)
from 4.0.13 to 4.1.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/bvaughn/react-error-boundary/releases">react-error-boundary's
releases</a>.</em></p>
<blockquote>
<h2>4.1.2</h2>
<ul>
<li>Remove <code>engines</code> field from Package JSON entirely</li>
</ul>
<h2>4.1.1</h2>
<ul>
<li>Remove node constraint from engines</li>
</ul>
<h2>4.1.0</h2>
<ul>
<li>Relax fallback prop to support broader ReactNode type</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/bvaughn/react-error-boundary/commit/9688d9f80d47834011dccfa9d1f1377968a4108f"><code>9688d9f</code></a>
4.1.1 -&gt; 4.1.2</li>
<li><a
href="https://github.com/bvaughn/react-error-boundary/commit/8f48596c6702107ad0bffee105ed9eb95c30f869"><code>8f48596</code></a>
Remove engines field</li>
<li><a
href="https://github.com/bvaughn/react-error-boundary/commit/434282742a2f14190aa8c0b27d0d1292d082a914"><code>4342827</code></a>
4.1.0 -&gt; 4.1.1</li>
<li><a
href="https://github.com/bvaughn/react-error-boundary/commit/e3d6eb9962d1a6515756f7af7994302d2cb566c6"><code>e3d6eb9</code></a>
Remove node constraint from engines</li>
<li><a
href="https://github.com/bvaughn/react-error-boundary/commit/defdae05746cb6571152414661e8c78592608465"><code>defdae0</code></a>
style(types.ts): remove unused imports (<a
href="https://redirect.github.com/bvaughn/react-error-boundary/issues/200">#200</a>)</li>
<li><a
href="https://github.com/bvaughn/react-error-boundary/commit/a1e634faef0fc4fd23a731143b5ae6e2c69f8c55"><code>a1e634f</code></a>
chore(package.json): add rimraf (<a
href="https://redirect.github.com/bvaughn/react-error-boundary/issues/199">#199</a>)</li>
<li><a
href="https://github.com/bvaughn/react-error-boundary/commit/96bb33370f9b9f0c9c6f3733a90d55dd7a1c34d2"><code>96bb333</code></a>
4.0.12 -&gt; 4.1.0</li>
<li><a
href="https://github.com/bvaughn/react-error-boundary/commit/206bdbad362737480ebd39cefb945c8cec11c1ce"><code>206bdba</code></a>
Upgrade pnpm v8 -&gt; v9 (<a
href="https://redirect.github.com/bvaughn/react-error-boundary/issues/198">#198</a>)</li>
<li><a
href="https://github.com/bvaughn/react-error-boundary/commit/23167c532dd6da0b8f106ab6ff8705ff64de81eb"><code>23167c5</code></a>
Relax fallback prop to support broader ReactNode type</li>
<li><a
href="https://github.com/bvaughn/react-error-boundary/commit/4aaf9b023a20fbfda67db74bf550124e8bbfa00c"><code>4aaf9b0</code></a>
chore: update CI workflows version to v4 and node version to 20 (<a
href="https://redirect.github.com/bvaughn/react-error-boundary/issues/194">#194</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/bvaughn/react-error-boundary/compare/4.0.13...4.1.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=react-error-boundary&package-manager=npm_and_yarn&previous-version=4.0.13&new-version=4.1.2)](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>

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22105?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. -->

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 15:45:07 +00:00
Félix Malfait ea3090e553 docs: rewrite billing credits page to clarify credit value and usage (#22099)
Rewrites the billing **Credits** doc so it actually explains what a
credit is worth and how far it goes — the previous version listed bare
credit counts and described AI cost only as "variable based on usage."

What changed:
- Leads with **1 credit = $1 of usage**, so the balance is easy to
reason about.
- Adds a "How far does a credit go?" table grounded in how billing
actually works: standard workflow steps cost ~$0.0001 each, quick AI
messages a fraction of a cent, while large multi-step agent tasks (e.g.
configuring several objects) can run to ~$1 or more.
- Explains that AI usage is metered at the model providers' published
token rates and converted straight to credits — no marked-up internal
rate.
- Reframes allocation (5/mo, 50/yr) in terms of equivalent dollar usage,
and tightens the rollover, monitoring, and top-up sections.

Docs-only change; no code or behavior affected.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22099?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-24 17:36:58 +02:00
Raphaël Bosi 6b460da622 Add backend primitive to credit a workspace's billing balance (#22094)
Adds `BillingCreditService.creditWorkspaceBalance({ workspaceId,
amountMicro })`, an internal, server-side primitive to grant spendable
resource credits to a workspace. This is the backend foundation for
awarding free credits during the new onboarding steps; there was no
existing way to add credits to a workspace.

What it does:
- Increments `billingCustomer.creditBalanceMicro` atomically
(workspace-scoped), then flushes the Redis available-credits cache so
the credit is immediately spendable, not just shown in the gauge.
- No-ops when billing is disabled or no billing customer exists; rejects
non-positive/non-finite amounts.
- Pure primitive with no GraphQL/REST surface; the caller owns
idempotency.

Notes for reviewers:
- Credits use the existing `RESOURCE_CREDIT` currency (micro units, 1
display credit = 1,000,000 micro).
- The credited balance is overwritten by the rollover job at the next
billing-period renewal, so it is not guaranteed to persist across
periods (intentional for onboarding bonuses).

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22094?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-24 17:28:24 +02:00
martmull c71663946e chore(apps): move public apps to packages/twenty-apps/public and generalize CI workflow (#22096)
## What

Introduces a `packages/twenty-apps/public/` folder and moves the
publicly publishable apps into it, then generalizes the apps CI workflow
to cover both folders.

### Moves
The following apps were moved from `packages/twenty-apps/internal/` to
`packages/twenty-apps/public/` (via `git mv`, history preserved):
- `people-data-labs`
- `twenty-discord`
- `twenty-exa`
- `twenty-fireflies`
- `twenty-last-contact`
- `twenty-linear`
- `twenty-meeting-bot`
- `twenty-slack`

These remain in `internal/`: `self-hosting`, `twenty-for-twenty`,
`twenty-partners`.

### Workflow
- Renamed `.github/workflows/ci-internal-apps.yaml` →
`.github/workflows/ci-twenty-apps.yaml`.
- The discover job now scans **both** `packages/twenty-apps/internal`
and `packages/twenty-apps/public`:
  - the "no nested `.github`" guard checks both folders,
  - `changed-files` watches both globs,
- the matrix builder iterates over both roots (guarded with `existsSync`
so a missing folder is a no-op).
- Each matrix entry still carries its own `path`, so the `ci` job works
unchanged regardless of which folder an app lives in.

## Notes
- The apps are standalone packages (own `yarn.lock`, not part of the
root Nx workspaces), so no root `package.json` / `nx.json` / `tsconfig`
changes were needed.
- The companion publish workflow lives in `twentyhq/twenty-infra`
(`publish-internal-apps.yaml` → `publish-public-apps.yaml`) and is
updated in a paired PR.

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

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

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22096?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-24 17:24:16 +02:00
github-actions[bot] 00b7d7c74a i18n - docs translations (#22102)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-06-24 17:22:42 +02:00
Rashad Karanouh 53bfc6ab1c fix: update skill to fit requirements (#22097)
<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22097?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-24 17:02:43 +02:00
nitin 0bccbb5035 rename twenty meeting bot to call recorder (#22093)
<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22093?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->

---------

Co-authored-by: martmull <martmull@hotmail.fr>
2026-06-24 17:02:34 +02:00
Félix Malfait 7d3cd5ed00 feat(front): add search to the language picker (#22095)
## What

Adds a search bar to the **Settings → Experience → Language** picker,
and makes languages searchable across languages.

Each option is matched against:
- its displayed label (the name in the current UI language)
- its name **in English** — typing `chinese` finds "Chinois — Simplifié"
- its **native name** — typing `中文` finds the same option

Matching is also accent-insensitive (`francais` finds "Français").

## How

- The shared `Select` already supports search via `withSearchInput`
(used by the currency/country pickers) — the picker just opts in.
- Cross-language matching uses the platform `Intl.DisplayNames` API to
derive each language's English and native names — no hardcoded
translation tables, no extra requests.
- A generic optional `searchKeywords` field on `SelectOption` lets the
`Select` filter match synonyms on top of the label; the filter now runs
through the existing `normalizeSearchText`, hence the
accent-insensitivity. Behavior is unchanged for every existing `Select`
(strict superset for ASCII labels).

## Test

- `nx typecheck` / `nx lint` pass for `twenty-front` and `twenty-ui`.
- Open the Language dropdown and try `chinese`, `中文`, or `francais`.


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22095?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-24 16:58:24 +02:00
Raphaël Bosi dd9ad876a4 Reduce published twenty-ui npm package size (#22087)
The published `twenty-ui@1.0.0-alpha.0` tarball was ~181 MB unpacked (27
MB compressed, 2,701 files). This was a build-config issue, so a clean
CI build would reproduce the same size.

Main fix: externalize `@tabler/icons-react` instead of bundling it. It
was forced into the bundle and aliased to the full icon barrel, inlining
the entire icon set into every entry point in both ESM and CJS (~81% of
the package). It stays a `dependency`, so consumers still get it; the
dynamic `<Icon name>` registry still resolves icons at runtime.

Also:
- Stop emitting/shipping declaration maps (`declarationMap: false`).
- Exclude the internal `dist/individual` build and `*.map` from the
tarball via `files` (it still builds locally for
`twenty-front-component-renderer`).
- Clean up the stale `files` / `project.json` build outputs at their
source, `scripts/generateBarrels.ts`.
- Add a `pack-size` CI guard (30 MB unpacked budget) and wire `size` +
`pack-size` into `ci-ui.yaml`.

Result: ~181 MB to ~2.3 MB unpacked (0.40 MB tarball, 400 files). All
export subpaths, types, and icon rendering verified intact in both
module formats.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22087?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-24 14:53:14 +00:00
RISHAV DEWAN 1cdede89de fix(email-settings): enable independent message folder and subfolder selection (#21853)
## Summary

Fixes #21840

Currently, selecting a root folder in **Settings → Accounts → Emails →
Folders** automatically selects all of its subfolders, and selecting a
subfolder automatically selects all of its ancestor folders. Users have
no granular control over individual folder sync.

This PR replaces the cascade selection logic with fully independent
per-node selection, matching standard tree-select UX patterns used in
file explorers and permission trees.

## Changes

### Bug Fix
- **`computeFolderIdsForSyncToggle.ts`**: Removed `collectChildren` and
`collectParents` cascade helpers. The function now returns only the
toggled folder's ID, enabling fully independent selection.
- **`SettingsAccountsMessageFoldersCard.tsx`**: Updated call site to
match simplified function signature (removed unused `allFolders` and
`isSynced` args).

### Tests
- **`computeFolderIdsForSyncToggle.test.ts`**: Rewrote tests to reflect
new per-node behavior. Removed tests asserting old cascade behavior;
replaced with tests verifying only the toggled folder is affected.
- **`isFolderTreePartiallySelected.test.ts`** *(new)*: Added 9 tests for
`isFolderTreePartiallySelected`, which is now the primary mechanism
driving the indeterminate checkbox state on parent folders.

## Behavior Before / After

| Action | Before | After |
|--------|--------|-------|
| Check a root folder | Checks root + all subfolders | Checks root only
|
| Check a subfolder | Checks subfolder + all ancestors | Checks
subfolder only |
| Uncheck a root folder | Unchecks root + all subfolders | Unchecks root
only |
| Parent with partial children | No indeterminate state (broken) | Shows
`–` indeterminate correctly |

## What Was Already Correct

The indeterminate checkbox UI was already fully implemented:
- `isFolderTreePartiallySelected` correctly detects mixed sync states in
subtrees
- `SettingsMessageFoldersTreeItem` already passes `indeterminate` to the
`Checkbox` component
- The `Checkbox` component in `twenty-ui` already supports the
`indeterminate` prop

Only the toggle cascade logic needed fixing.

## Testing

```bash
# Unit tests
cd packages/twenty-front && yarn jest --testPathPattern="computeFolderIdsForSyncToggle|isFolderTreePartiallySelected"

# Lint
npx nx lint:diff-with-main twenty-front

# Type check
npx nx typecheck twenty-front

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

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: neo773 <62795688+neo773@users.noreply.github.com>
Co-authored-by: neo773 <neo773@protonmail.com>
2026-06-24 14:32:18 +00:00
Etienne 90acecfbd9 feat(billing): invoice on seat increase (#22083)
## Context

Two billing improvements around workspace seat changes:

1. **Delay subscription quantity updates.** Every workspace member
create/delete/destroy event used to enqueue an
`UpdateSubscriptionQuantityJob` immediately.

2. **Invoice immediately when seats increase.** Seat increases
previously used `create_prorations`, which defers the charge to the next
billing cycle. We now bill the proration right away on increases, while
keeping deferred prorations on decreases / no-ops.

## Changes

### Job delaying
- `BillingWorkspaceMemberListener` now enqueues the job with the
per-workspace id and a 24h delay. Re-adds within the window coalesce to
a single delayed run per workspace, collapsing bursts of member changes
into one Stripe update.

### Proration behavior
- `computeSubscriptionUpdateOptions` now accepts an optional `{
currentSeats }` context. For `SEATS` updates it returns `always_invoice`
when `newSeats > currentSeats`, otherwise `create_prorations` (decrease
or unchanged).
- `BillingSubscriptionUpdateService` passes `currentSeats:
licensedItem.quantity` so the decision is based on the actual current
subscription quantity.

## Tests
- `compute-subscription-update-options.util.spec.ts`: added cases for
seat increase (`always_invoice`), decrease (`create_prorations`), and
unchanged (`create_prorations`).
- `billing-subscription-update.service.spec.ts`: updated expectations to
`always_invoice` for the seat-increase paths.


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22083?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-24 14:31:15 +00:00
twenty-pr[bot] 965a2753d1 chore: bump version to 2.17.0 (#22088)
## Summary

- Moves current version to previous versions array
- Sets TWENTY_CURRENT_VERSION to the new version
- Updates TWENTY_NEXT_VERSIONS with the next minor version
- Bumps twenty-client-sdk, twenty-sdk, and create-twenty-app to the same
version

## Checklist

- [ ] Verify version constants are correct
- [ ] Verify npm package versions match

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

Co-authored-by: Github Action Deploy <github-action-deploy@twenty.com>
2026-06-24 16:14:42 +02:00
nitin 411aee8b96 update readme file for meeting bot (#22069)
<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22069?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-24 19:34:30 +05:30
Félix Malfait 614bc7b7e6 feat: serve HTTP logic functions on isolated *.withtwenty.com domain (#22045)
## Summary

Implements
[core-team-issues#2473](https://github.com/twentyhq/core-team-issues/issues/2473):
serve HTTP-triggered logic functions from a dedicated, **cookieless**
public domain (`{workspaceSubdomain}.withtwenty.com`) instead of the
same-site `/s/` route, so functions can safely return **arbitrary
headers** — custom headers, `Permissions-Policy`
(camera/mic/geolocation), `Cross-Origin-Opener-Policy: same-origin`,
`Cross-Origin-Embedder-Policy: require-corp`, `Set-Cookie`, etc.

The `/s/` route stays the strict, same-site path it is today.
**Self-hosting is unchanged** — everything new is gated on
`PUBLIC_DOMAIN_URL` being set.

### Why

Today user-authored function responses are served same-site with the
Twenty app, so the response-header allow-list is restricted to 5 safe
headers and request headers are limited to a per-function allow-list.
Serving from an origin that shares nothing with `*.twenty.com` removes
that constraint safely — the same "user content domain" pattern as
GitHub (`*.githubusercontent.com`) and CodeSandbox (`*.csb.app`).

## What's in here

**Routing**
- The **root-path → `/s` rewrite happens at the nginx ingress**, not in
app code. The existing `api-ingress.yaml` already rewrites root paths
onto `/s` (host-agnostically) when the edge sets
`X-Twenty-Public-Domain: true`, so `*.withtwenty.com` and registered
custom public domains are handled by the same mechanism. (An earlier
in-app middleware was removed as a redundant, wrong-layer duplicate.)
- `WorkspaceDomainsService.resolveWorkspaceAndPublicDomain` recognizes
`*.` subdomains, resolves the workspace by subdomain, and returns
`isIsolatedOrigin`. Explicitly registered public-domain rows still take
precedence and keep their application scoping. The ingress preserves the
`Host` header, so this resolution still fires.

**Headers (server)**
- Isolated origin → all response headers pass through and all request
headers are forwarded. Same-site `/s/` keeps the strict allow-lists.
(Global CORS already handles preflight/ACAO.)

**`/s/` deprecation for new routes (cloud only)**
- New `LOGIC_FUNCTION_LEGACY_ROUTE_CUTOFF` config var (ISO date,
optional). When `PUBLIC_DOMAIN_URL` is set, functions created on/after
the cutoff return **410 Gone** on `/s/` with the new URL. Existing
routes and self-hosted instances are untouched.

**Frontend education**
- `publicFunctionDomain` added to `ClientConfig` (from
`PUBLIC_DOMAIN_URL`).
- The logic-function **Live URL** now resolves to
`https://{workspaceSubdomain}.{publicFunctionDomain}{path}` on cloud,
falling back to `/s/` for self-hosting.
- Front components call their functions through the SDK
(`RestApiClient`), which now targets the isolated domain via the
injected `TWENTY_FUNCTIONS_URL`.
- New **"Public URL"** section on the application **Settings** tab
explaining the isolated domain (shown when the app exposes
HTTP-triggered functions).

**Docs**: note the `withtwenty.com` domain for external callers in the
apps guide.

## Infra prerequisites (not code — needs dashboard work)
- Wildcard DNS `*.withtwenty.com` (proxied) + wildcard TLS in the
public-domain Cloudflare zone.
- Edge (Cloudflare) sets `X-Twenty-Public-Domain: true` for
`*.withtwenty.com` requests, so the existing nginx ingress rewrites them
onto `/s` (same header the custom-domain flow already relies on).
- Set `PUBLIC_DOMAIN_URL=https://withtwenty.com` on cloud.
- Submit `withtwenty.com` to the **Public Suffix List** (required for
cross-tenant cookie isolation before relying on `Set-Cookie`).

## Test plan
- [x] `nx typecheck twenty-server`, `nx typecheck twenty-front`
- [x] `lint:diff-with-main` + oxfmt clean (server + front)
- [x] `npx jest route-trigger public-function-domain
domain-server-config workspace-domains build-logic-function-event
client-config` → server unit tests passing (resolution tiers, header
passthrough vs allow-list, `/s/` cutoff 410)
- [x] `npx jest getLogicFunctionHttpUrl` (front) and `nx test
twenty-client-sdk` (RestApiClient routing) passing
- [x] CI green (server, front, sdk, renderer, ui, zapier, example apps)
- [ ] Manual: hit `{subdomain}.withtwenty.com/` end-to-end once infra is
provisioned

<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22045?utm_source=github"
rel="nofollow noreferrer noopener" target="_blank">``&lt;img alt="Review
in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"&gt;``</a>
2026-06-24 15:57:01 +02:00
Paul Rastoin 5e5c8e0956 ci(server,emails): run lingui extract & compile on PRs to gate i18n breakage (#22086)
## Why

Translations for `twenty-server` and `twenty-emails` are only extracted
**after merge** — in `i18n-push.yaml` (push to `main`). Their PR
workflows (`ci-server.yaml`, `ci-emails.yaml`) never run `lingui
extract`, so a change that crashes extraction passes every PR check and
only fails post-merge — the same process gap that let the frontend crash
through (fixed in #22080, frontend gate in #22084).

Both projects have a `lingui:extract` target and are extracted by
`i18n-push.yaml`, so the equivalent guard applies.

## What

- **`ci-server.yaml`** — add `lingui:extract` to the existing
`server-lint-typecheck` job's `nx-affected` tasks (`tag:
scope:backend`). That job already builds `twenty-shared` and is already
part of `ci-server-status-check`, so no new job/wiring is needed:
  ```
  tasks: lint,typecheck  ->  tasks: lint,typecheck,lingui:extract
  ```
- **`ci-emails.yaml`** — add a `lingui:extract` step to the
`emails-test` job (this workflow has no `nx-affected` job, so a direct
target run fits):
  ```yaml
  - name: Extract translations (lingui)
    run: npx nx run twenty-emails:lingui:extract
  ```

Both run the same extraction command as the post-merge `i18n-push`
workflow, so failures are caught before merge.

## Notes

- `lingui extract` exits non-zero on extraction failures (verified on
the frontend crash: exit code 1), so these steps genuinely fail the job.
- Both jobs already gate on `changed-files-check`, so extract only runs
when the respective package changes.
- `nx affected -t=lingui:extract` only runs for projects that have the
target; `lingui:extract`'s `^build` dependency is resolved automatically
by nx.

Completes the extract-gate coverage started for the frontend in #22084.


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22086?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-24 15:55:57 +02:00
Paul Rastoin 7820665006 ci(front): run lingui extract & compile on PRs to gate i18n breakage (#22084)
## Why

`lingui extract` currently only runs **after merge** — in
`i18n-push.yaml`, which triggers on push to `main`. PR CI
(`ci-front.yaml`) runs `lint`, `typecheck`, `test`, and `build`, but
never `lingui extract`. So a change that crashes extraction passes every
PR check and only blows up later in the CD `build-front / s3-build` job.

That's exactly what happened with the spread-in-`i18n._()` crash fixed
in #22080:

```
Cannot process file .../build-crud-tool-status-message.util.ts:
Cannot read properties of undefined (reading 'name')
  at @lingui/babel-plugin-extract-messages/dist/index.cjs:88:22
```

## What

Add `lingui:extract` to the `front-task` matrix in `ci-front.yaml`. It
now runs alongside `lint`/`typecheck`/`test` via the existing
`nx-affected` action:

```
npx nx affected -t=lingui:extract --exclude='*,!tag:scope:frontend'
```

This runs the **exact command that fails** in the CD build, so it
catches this bug class — and any other change that breaks extraction —
before merge, not after.

## Notes / verification

- Confirmed `lingui extract --overwrite --clean` exits **non-zero** on
the crash (verified locally on the pre-fix source: exit code 1), so the
matrix job fails as intended.
- The job only runs when frontend files change (`changed-files-check`
gate), and `nx affected -t=lingui:extract` only runs for projects that
actually have the target, so non-frontend projects are skipped.
- Extract writes to `.po` files in the runner; that's ephemeral and not
committed — the gate only asserts the command succeeds, it does not
check catalog diffs.
- Scope is intentionally frontend-only (this workflow is `ci-front`).
`twenty-server` / `twenty-emails` extraction is not gated on PRs by this
change; a follow-up could add the equivalent to the backend CI if
desired.

Companion to #22080 (the actual fix); this PR closes the process gap
that let it through.


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22084?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-24 15:55:42 +02:00
souheyl gouadria bf345bb177 Allow workflows listing in MCP (#22013)
This resolves https://github.com/twentyhq/twenty/issues/21986

Add `list_workflows `MCP tool

Workflow objects are excluded from the generic database CRUD tools
exposed via MCP, which meant the only way to list workflows was through
a direct API call.

This adds a `list_workflows `tool to the `WorkflowToolProvider`, making
it available via MCP alongside the existing workflow builder tools. It
supports optional filtering by status (`DRAFT`, `ACTIVE`, `DEACTIVATED`)
and pagination (`limit`/`offset`). The status filter uses an
array-membership predicate (`ANY`) since `statuses `is a multi-value
field.

---------

Co-authored-by: Souheyl Gouadria <souheyl.gouadria@medius.com>
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2026-06-24 15:52:29 +02:00
Weiko 56e20a81ea Revert 21949 (#22081)
#21949 introduced deterministic uuid utils with usage in the same PR. 
Usage was not uniform and expected a backfill command as well. 
Since we want to release I'm reverting all the changes from that PR that
concerns twenty-server and only keeping the unused utils in
twenty-shared and I'll introduce usages within the same PR as backfill
command
2026-06-24 15:37:16 +02:00
martmull b5a1aed24b feat(server): run server-exposed logic functions in the owner workspace (#22002)
## Summary

Implements the server-level logic-function tier in the simplest shape: a
logic function is "server-exposed" iff its manifest entry carries
`serverWebhookTriggerSettings`. Execution delegates to the
owner-workspace copy of that function — billing, throttling, env vars,
and the existing executor all apply uniformly against that workspace.

Supersedes #21971 with the simplified design from that discussion (no
`applicationRegistrationLogicFunction` registry, no dedicated manifest
type, no separate SDK helper, no special throttling).

## Design

- **Manifest**: `LogicFunctionManifest` gains
`serverWebhookTriggerSettings?`. The declarative `workspaceIdResolver`
shape is dropped.
- **Materialization**: those settings become two new jsonb columns on
`LogicFunctionEntity`. The manifest → flat converter and the
create-from-source DTO/util forward them; the property-config map and
editable-properties list are extended.
- **Lookup**: a single QB query joins `logicFunction → application →
applicationRegistration` and filters on `lf.workspaceId =
reg.workspaceId` to get only the owner workspace's copy.
- **Webhook**: `POST /webhooks/server/:logicFunctionUniversalIdentifier`
→ `ServerWebhookTriggerService.handle` → join lookup →
`LogicFunctionTriggerService.run`. No registry table, no
`:applicationRegistrationUniversalIdentifier` segment, no resolver.
- **Gate**: `IS_SERVER_LOGIC_FUNCTION_ENABLED` config var (disabled by
default).

## Test plan
- [x] `npx jest server-webhook-trigger` — 9 unit tests across the
webhook service.
- [x] `npx jest logic-function` — 88 existing tests stay green.
- [x] `npx nx typecheck twenty-server`.
- [x] `npx nx lint:diff-with-main twenty-server`.
- [x] Reset DB → init → run `database:migrate:prod` → run
`database:migrate:generate --name pending-migration-check` → no drift.
- [ ] Manual: hit `/webhooks/server/<uid>` end-to-end against a manifest
carrying `serverWebhookTriggerSettings`.

https://claude.ai/code/session_01GgsnCGmYJ26xRirx8va1Yh

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

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22002?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-24 13:34:12 +00:00
Abdullah. 20ac0a52bf fix(deps): scope js-yaml to 4.2.0 under the mintlify/verdaccio pinners (#22078)
## Summary

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

## Why scoped resolutions (not a global pin)

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

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

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

## Verification

- `yarn install --immutable` passes.
- No `js-yaml@4.1.1` remains; js-yaml is now `4.2.0` (+ the documented
`3.14.2` remnant).
- Diff is js-yaml-only; matching `"//resolutions"` doc entry included.
2026-06-24 18:24:00 +05:00
Paul Rastoin ad3c82bd15 fix(front): prevent lingui extract crash in buildCrudToolStatusMessage (#22080)
## Problem

The `build-front / s3-build` CD job fails during the `Build frontend`
step, in the `twenty-front:lingui:extract` target (`lingui extract
--overwrite --clean`):

```
Cannot process file .../build-crud-tool-status-message.util.ts:
Cannot read properties of undefined (reading 'name')
  at @lingui/babel-plugin-extract-messages/dist/index.cjs:88:22
  at extractFromObjectExpression (...index.cjs:87:18)
  at extractFromMessageDescriptor (...index.cjs:121:19)
  at PluginPass.CallExpression (...index.cjs:189:11)
```

## Root cause

`buildCrudToolStatusMessage` called `i18n._()` with an inline object
literal containing a spread:

```ts
i18n._({ ...verbs.loading, values: { objectLabel } })
```

Lingui's `extract-messages` babel plugin fires on every `i18n._(...)`
call. When the first argument is an `ObjectExpression`, it runs
`extractFromObjectExpression`, which reads `key.name` for **every**
property. The spread element `...verbs.loading` has no `key`, so
`key.name` throws `Cannot read properties of undefined (reading
'name')`, crashing `lingui extract` and failing the whole S3 publish
job.

## Fix

Hoist the descriptors into variables so `i18n._()` receives an
identifier rather than an inline object expression. The plugin then
skips extraction (no statically-extractable id), so no crash. Runtime
behavior is unchanged — the translatable strings are still extracted
from the `msg` macros in `CRUD_TOOL_OPERATION_VERBS`.

## Testing

- Reproduced the **exact** CI crash locally on `main` by running `lingui
extract --overwrite --clean` (same file, message, and stack frames).
- After the fix, `lingui extract --overwrite --clean` runs clean (exit
0).
- `build-crud-tool-status-message.util.test.ts` passes (2/2).
- `nx lint:diff-with-main twenty-front` passes (0 warnings, 0 errors,
formatting clean).


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22080?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-24 15:21:43 +02:00
Raphaël Bosi a575ef56c3 Add logo to twenty-ui README (#22077)
<img width="408" height="408" alt="Twenty_UI"
src="https://github.com/user-attachments/assets/f69fb630-97fb-4c21-ad44-d924e4bd72f5"
/>


Adds the Twenty UI logo to the top of the `twenty-ui` package README.

- New `packages/twenty-ui/logo.png` (rasterized at 3x for retina).
- README references it via an absolute raw GitHub URL so it renders on
both the GitHub repo page and the npmjs.com package page (npm strips SVG
images from READMEs, so PNG is used).

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22077?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-24 13:19:03 +00:00
Thomas des Francs 9e57ec3153 Update data model object settings labels (#22070)
## Summary

- Update Data Model object list copy: rename the section to **Objects**
and the count column to **Records**.
- Improve relation rows by showing the related object name with the
field name as a secondary label, including morph relation-specific
labels/icons.
- Hide relations to system objects unless Advanced mode is enabled, and
default the System objects filter to on while Advanced mode is on.
- Reuse a shared secondary-label component for the light
subtitle/deactivated text treatment.

## Screenshots

### Before

Mix of field name & object name. Not all relations are navigable

<img width="1642" height="950" alt="image"
src="https://github.com/user-attachments/assets/e04fb710-e333-4dd7-a29f-82c226202e77"
/>


### After

<img width="1690" height="1112" alt="image"
src="https://github.com/user-attachments/assets/f7d75974-a5cc-401b-bbd2-ab82a2006cf9"
/>
2026-06-24 15:15:41 +02:00
nitin 73e9374ef8 [BREAKING CHANGE] harden call recording failure handling (#22062)
<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22062?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-24 15:08:26 +02:00
Charles Bochet 0df83eceb2 fix(front): restore loading state on third-party app command menu actions (#22073)
## Problem

Headless command-menu actions provided by third-party applications (e.g.
the "Twenty Eng" app actions like *Fetch Pull Requests*, *Recompute
Build Tasks*) no longer show a loading/progress indicator while they
run, so users can't see that the action is in progress.

## Root cause

In `CommandMenuItemSelectableRenderer`,
[#21020](https://github.com/twentyhq/twenty/pull/21020) added an
early-return branch for third-party application actions that renders
`AppMenuItem`:

```tsx
if (isThirdPartyApp) {
  return (
    <SelectableListItem ...>
      <AppMenuItem ... />   // no loader passed
    </SelectableListItem>
  );
}
```

This branch returns **before** the `listItem` path that builds the
`loaderComponent` (spinner + progress %), and `AppMenuItem` had no way
to render a right-side loader. So `progress` / `showDisabledLoader` from
`useCommandMenuItemClick` were computed but dropped for third-party app
actions. Native (non third-party) actions kept their loader because they
go through the `listItem` path.

## Fix

- Add an optional `RightComponent` prop to `AppMenuItem`, forwarded to
the underlying `MenuItem` (which already renders it).
- Hoist the `loaderComponent` computation in
`CommandMenuItemSelectableRenderer` above the branches and pass it to
both the third-party `AppMenuItem` path and the existing `listItem` path
(no behavior change for the latter).

The loader now appears for third-party app actions exactly as it does
for native ones — `<CommandListItemLoader progress={progress} />` once
progress is reported, falling back to a `<Loader />` spinner before the
first progress update.

## Verification

- `oxlint --type-aware` clean on both changed files.
- `typecheck` clean for the changed files.
- Manual browser repro requires a third-party application with a
progress-reporting headless action installed in the workspace (as in the
reported screenshot), which isn't available in a stock dev workspace.
The fix mirrors the already-working native `listItem` loader path.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22073?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-24 15:05:28 +02:00
Paul Rastoin 0f2ea47335 Twenty standard backfill non searchable object search field metadata (#22063)
# Introduction

This PR https://github.com/twentyhq/twenty/pull/21964 introduces a
search field metadata workspace command backfill that will recompute all
the standard search field metadata but only for the searchable object

Whereas the non searchable object still have a search vector as they can
still be searched but internally
Preserving their search vector by computing their search field metadata


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22063?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-24 12:44:59 +00:00
Charles Bochet dd7435b807 fix: normalize date-time field input on backend to prevent timeline crash (#22035)
## Context

Reported via support
([private-issues#477](https://github.com/twentyhq/private-issues/issues/477)):
a customer saw **"Invalid Configuration"** in red on a record's
**Timeline** tab. The dev console was flooded with:

```
RangeError: Cannot parse: 2026-05-07
    at Temporal.Instant.from (...)
    at RecordFieldComponent ...
```

## Root cause

A `DATE_TIME` field in their workspace holds **date-only** values like
`2026-05-07`.

`validateDateTimeFieldOrThrow` (the write-path validator) **accepts**
date-only formats — `'yyyy-MM-dd'` is in `ACCEPTED_DATE_TIME_FORMATS` —
and **returns the raw input string unchanged**, with no normalization.
So a date-only string passes validation and propagates verbatim into the
mutation response and the timeline event payload.

On render, `DateTimeDisplay` builds the timezone hint with
`Temporal.Instant.from(value)`. That's strict — it requires a full
instant (time + offset/`Z`) and throws `RangeError` on a bare date. The
throw escapes into the page-layout widget error boundary, which renders
the **"Invalid Configuration"** fallback and breaks the whole timeline.

## Fix

**Backend (root cause) — normalize on write.**
`validateDateTimeFieldOrThrow` now canonicalizes every accepted value to
a full ISO 8601 instant, so a date-only value can never reach storage,
the mutation response, or timeline events for a `DATE_TIME` field:

- strict ISO-8601 carrying an offset/`Z` -> kept as its exact instant
(server-timezone-independent)
- zoneless / date-only / lenient formats -> interpreted as **UTC**
(date-only -> midnight UTC), deterministically

Lenient input is preserved — parsing still uses date-fns for the ~20
accepted formats (which `Temporal.Instant.from` cannot parse); only the
*output* is canonicalized, via Temporal.

| input | before (stored raw) | after (normalized) |
|---|---|---|
| `2026-05-07` | `2026-05-07` | `2026-05-07T00:00:00Z` |
| `2026-05-07T12:00:00+02:00` | `2026-05-07T12:00:00+02:00` |
`2026-05-07T10:00:00Z` |
| `2026-05-07T12:00:00.000Z` | `2026-05-07T12:00:00.000Z` |
`2026-05-07T12:00:00Z` |
| `January 15, 2024` | `January 15, 2024` | `2024-01-15T00:00:00Z` |

**Frontend (existing data) — Temporal-native guard.** Existing
workspaces already have date-only values stored in events, so the
backend fix alone won't un-break the reporting customer's timeline.
`DateTimeDisplay` now parses the value via a new
`parseStringToInstantOrNull` helper (Temporal `Instant.from` with a
`PlainDate` start-of-day-UTC fallback) and only renders the timezone
hint when valid — so stored bad data renders gracefully instead of
crashing. This replaces the initial `new Date()` guard with a
Temporal-native one, in line with the codebase's Temporal migration.

## Tests

- `validate-date-time-field-or-throw.util.spec.ts` updated to assert the
normalized instant output, incl. explicit date-only -> midnight-UTC
cases.
- `parseStringToInstantOrNull.test.ts` — unit coverage for the frontend
helper (instant, offset, date-only, unparseable).
- `DateTimeDisplay.stories.tsx` — story rendering a date-only value
under a non-system timezone (the previously-crashing path).
2026-06-24 12:42:05 +00:00
Paul Rastoin 8842a80a44 ci(server): cross-version upgrade check on PRs (v1.22 → from source) (#22065)
## What

Adds a pre-merge CI check that proves a database created and seeded by
the **oldest supported release** (`twentycrm/twenty:v1.22` from Docker
Hub) can be upgraded by the **current version built from source**, and
that the upgraded instance comes up healthy with its data still
queryable.

Runs only on PRs touching the upgrade path (`upgrade-version-command/**`
+ `core-modules/upgrade/**`), and blocks the PR via
`ci-server-status-check`.

## How

New reusable workflow `ci-cross-version-upgrade.yaml` (`workflow_call` +
`workflow_dispatch`), called from `ci-server.yaml` after `server-build`
so the build cache is populated in-run:

1. **Services** — `postgres:16` (prod parity) + `redis:7` on a docker
network.
2. **Old version** — pull `twentycrm/twenty:v1.22`, boot it against the
DB, `workspace:seed:dev`, sanity-check the seed via `psql`.
3. **New version (from source)** — restore the `server-build` nx cache
(best-effort: a miss just cold-builds), `nx build`, run the `upgrade`
command against the same DB, `start:ci`, poll `/healthz`.
4. **Smoke** — assert `upgrade:status` shows `Instance: Up to date` / `0
behind, 0 failed`, then run companies/people/metadata GraphQL queries.

The job is always invoked but gated by a `skip` input (computed from the
upgrade-paths `changed-files` check), with a `no-op` job reporting
success when skipped — so the status check always resolves instead of
leaving a dangling skipped job, mirroring the twenty-infra pattern.

Unlike the equivalent post-merge gate in infra-twenty, this is
**pre-merge**, uses **native PR path filtering** (no compare API), and
**reuses the from-source build cache** instead of pulling an ECR image —
no cross-repo plumbing, no skipped-commit gap.

## Security note

No credentials are committed. `APP_SECRET` is generated fresh per run
(`openssl rand`, `::add-mask::`'d) and shared between the old container
and the from-source server within the job; the smoke-test API token is
minted at runtime via `workspace:generate-api-key` against the upgraded
server and masked in logs.

## Verified with a real run

Validated end-to-end by temporarily touching the upgrade path to trigger
the job (trigger commit since dropped), in [CI Server run
`28097035272`](https://github.com/twentyhq/twenty/actions/runs/28097035272)
→ [`cross-version-upgrade`
job](https://github.com/twentyhq/twenty/actions/runs/28097035272/job/83189453451)
 **all steps green**:

- v1.22 container boot → `workspace:seed:dev` → `psql` seed sanity check

- from-source build (nx cache restored) → `upgrade` → **56 workspace(s)
succeeded, 0 failed** 
- server healthy → API token minted at runtime via
`workspace:generate-api-key` 
- `upgrade:status` → `Instance: Up to date`, `0 behind, 0 failed` 
- companies / people / metadata GraphQL smoke queries 
- `no-op` job correctly skipped (real job ran because the gate matched)


The three assumptions originally flagged for first-run all held; one bug
was found and fixed in the process — `upgrade:status` colorizes via
`chalk` even with `NO_COLOR`, so the assertion now strips ANSI escapes
before grepping.

> Note: the overall `ci-server` run shows a failure from an **unrelated
flaky integration test** (`if-else-workflow.integration-spec.ts`,
`column workspaceMember.region does not exist` in shard 11). The same
trigger commit passed all 16 integration shards in the prior run — it's
a pre-existing flake, not caused by this PR.

## Note

Still keeping the equivalent one inside infra-twenty as an final
bottleneck just in case

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22065?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-light.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-24 14:20:38 +02:00
Raphaël Bosi 558e2e4107 Add new onboarding login screen at /welcome-v2 (#22027)
Stands up the new onboarding login screen at a new route `/welcome-v2`,
as the foundation for the new onboarding flow (future PRs build the
post-login steps on top of it).

There is no feature flag: feature flags are per-workspace and read from
`currentWorkspaceState`, which is null on the pre-auth welcome screen,
so they can't cleanly gate it. A dedicated route is used instead.
`/welcome` is untouched and stays the default for logged-out users;
`/welcome-v2` is reachable only by navigating to it directly (nothing
links or redirects to it yet), so this is fully non-breaking.

The new page reuses all existing auth logic and behavior components
(`useSignInUp`, `useSignInUpForm`, step state, the
Google/Microsoft/credentials forms, `Logo`, `Title`, `ModalContent`) and
mirrors `SignInUp.tsx` almost exactly. The only intentional design delta
from today's screen is the footer wording, per Figma: "Data Processing
Agreement" (linking to `/legal/dpa`) instead of "Privacy Policy".

Notable:
- Added an optional `to` prop to the shared `Logo` (defaults to
`AppPath.SignInUp`, backward-compatible) so the logo on `/welcome-v2`
doesn't bounce users back to `/welcome`.
- The remaining changes are single-line additions to the pre-auth
allowlists next to the existing `AppPath.SignInUp` entries (router,
redirect guard, auth modal, metadata gater, captcha, page title, focus).



https://github.com/user-attachments/assets/abfc96ec-a87d-4608-b92a-87e2322e4874


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22027?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-24 12:13:55 +00:00
Thomas des Francs 1589b9b912 Add search to new sidebar item picker (#22041)
## Summary
- Add search to the custom layout “New menu item” side panel.
- Group search results by Objects, Views, and Records.
- Reuse the existing record search behavior through a shared hook and
preserve add-to-navigation drag/select flows.

## Video
- Recording:
https://gist.githubusercontent.com/Bonapara/c78107650efd94b580e38426b9fc2dbd/raw/755c87fab253281a9c68e5a24cbfdff6c9248af1/search-nav-item-custom-layout.webm

## Verification
- Browser plugin: opened layout customization, clicked `Add menu item`,
searched `o`, and verified `Objects`, `Views`, and `Records` result
groups with object/view/record results.
- `npx oxlint --type-aware -c packages/twenty-front/.oxlintrc.json
packages/twenty-front/src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemPage.tsx
packages/twenty-front/src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
packages/twenty-front/src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemSearchResults.tsx
packages/twenty-front/src/modules/navigation-menu-item/edit/side-panel/hooks/useAvailableNavigationMenuItemSearchRecords.ts`
- `npx nx typecheck twenty-front`
- `npx nx lint twenty-front`

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22041?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-24 14:05:23 +02:00
github-actions[bot] 5ff1d997c7 i18n - docs translations (#22068)
Created by Github action

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

Co-authored-by: github-actions <github-actions@twenty.com>
2026-06-24 13:41:48 +02:00
Etienne 5ca41d55fb feat(ai): humanize tool-call (#21976)
# Humanize tool-call labels

cc: https://github.com/twentyhq/twenty/pull/21462

## Preview
<img width="459" height="156" alt="Screenshot 2026-06-22 at 19 13 11"
src="https://github.com/user-attachments/assets/e7a2f5f5-cd09-4ec6-920b-5eb16b98285c"
/>
<img width="461" height="156" alt="Screenshot 2026-06-22 at 19 14 54"
src="https://github.com/user-attachments/assets/c2114d2e-2aa8-499a-9801-68e3bb7c45f8"
/>
<img width="461" height="505" alt="Screenshot 2026-06-22 at 19 15 01"
src="https://github.com/user-attachments/assets/ee9ca5d0-8e79-4c63-a2ff-ed5e359a9a9c"
/>

## Why

In the AI chat, tool steps were displayed using raw tool identifiers
(`find_many_companies`, `create_one_task`, `send_email`...) and labels
were partially reconstructed/humanized on the frontend. This was hard to
localize and inconsistent across tool categories.

This PR makes the **backend the single source of truth for
human-readable, localized tool labels**, exposes them through
`getToolIndex`, and reduces the frontend to a thin resolver that picks
the right label for the current status (in-progress / completed).

## What changed

### Backend

- `ToolIndexEntry` (and the `getToolIndex` GraphQL DTO) now carry
`label`, `inProgressLabel?`, `completedLabel?`.
- New `getCrudToolLabels(operation, objectLabel, i18nService, locale)`
builds CRUD labels from a verb table (Search / Find / Group / Create /
Update / Upsert / Delete × imperative / in-progress / completed) + the
(translated, lowercased) object label.
- New `translate-tool-label.util.ts` translates a source label via
`I18nService` (`generateMessageId` → fallback to source when no
translation exists).
- Action tools: labels extracted to the `ACTION_TOOL_LABELS` constant
(`msg` + `i18nLabel`) and translated in
`ActionToolProvider.buildDescriptor`.
- Logic-function tools use the function name as label;
`toolSetToDescriptors` (workflow / view / metadata / dashboard) accepts
an optional `labels` map and falls back to a humanized tool name.
- Labels are localized server-side using the request locale
(`@RequestLocale` → `buildToolIndex` → `context.locale`, threaded
through `ToolContext` / `ToolProviderContext`).
- `code_interpreter` schema now asks the model for `loadingMessage`
(present tense) and `completedMessage` (past tense), so its status text
is model-generated.
- Removed the old generic `loadingMessage` injection mechanism
(`wrap-tool-for-execution.util.ts` deleted; `wrapJsonSchemaForExecution`
/ `stripLoadingMessage` no longer wrap every tool).

### Frontend

- New `useToolLabelMap()` hook builds a `Map<name, { label,
inProgressLabel, completedLabel }>` from `getToolIndex`.
- `getToolDisplayMessage` → `resolveToolDisplayMessage({ input,
toolName, isFinished, labelMap, output })`: a small resolver registry
keyed by tool name (`execute_tool`, `web_search`, `learn_tools`,
`load_skills`, `code_interpreter`, default).
- Default resolver prefers backend `completedLabel` / `inProgressLabel`,
falling back to `Ran X` / `Running X`.
- `learn_tools` / `load_skills` resolve their inner tool/skill names to
labels (label map → tool output labels via `getToolOutputLabelEntries` →
raw name).
- `code_interpreter` step is now expandable to show the code even while
running.

## How tool labelling flows (BE → FE)

```text
BACKEND
┌───────────────────────────────────────────────────────────────────────────┐
│ Tool providers (per category) → ToolIndexEntry                              │
│                                                                             │
│  DatabaseToolProvider                                                       │
│    getCrudToolLabels(operation, object.labelPlural/Singular, i18n, locale)  │
│      verb table (Search/Create/Update/Delete…) + translateToolLabel(object) │
│      → { label, inProgressLabel, completedLabel }                           │
│                                                                             │
│  ActionToolProvider                                                         │
│    ACTION_TOOL_LABELS[toolId] (msg) → translateToolLabel(…, locale)         │
│      → { label, inProgressLabel?, completedLabel? }                         │
│                                                                             │
│  LogicFunctionToolProvider   → label = logicFunction.name                   │
│  toolSetToDescriptors        → label = labels[name] ?? humanize(name)       │
│  (workflow / view / metadata / dashboard)                                   │
└───────────────────────────────────────────────────────────────────────────┘
            │ 
            ▼
┌───────────────────────────────────────────────────────────────────────────┐
│ GraphQL  Query getToolIndex : [ToolIndexEntry]                              │
│   { name, label, inProgressLabel, completedLabel, description,              │
│     category, objectName, icon }                                            │
└───────────────────────────────────────────────────────────────────────────┘
            │
            ▼
FRONTEND ─ resolve the right label for the current status
┌───────────────────────────────────────────────────────────────────────────┐
│ useGetToolIndex() → useToolLabelMap()                                       │
│   Map<name, { label, inProgressLabel?, completedLabel? }>                   │
└───────────────────────────────────────────────────────────────────────────┘
            │
            ▼
┌───────────────────────────────────────────────────────────────────────────┐
│ resolveToolDisplayMessage({ input, toolName, isFinished, labelMap, output })│
│                                                                             │
│   TOOL_LABEL_RESOLVERS[toolName] ?? defaultResolver                         │
│   ├─ execute_tool     → unwrap { toolName, arguments } then re-resolve      │
│   ├─ web_search       → "Searching/Searched the web for <query>"           │
│   ├─ learn_tools      → "Learning/Learned <labels>"                         │
│   ├─ load_skills      → "Loading/Loaded <labels>"                           │
│   │     inner names resolved via: labelMap → output labels → raw name       │
│   ├─ code_interpreter → model's loadingMessage / completedMessage           │
│   └─ default          → isFinished                                          │
│                           ? completedLabel ?? "Ran <label>"                 │
│                           : inProgressLabel ?? "Running <label>"            │
└───────────────────────────────────────────────────────────────────────────┘
            │
            ▼
   Rendered by ThinkingStepsDisplay / ToolStepRenderer
```

## Localization notes

- Standard object labels and action/CRUD verbs are translated
server-side via `I18nService` using the requester's locale.
- Custom object labels are not translated unless a workspace custom
translation exists (matched by `generateMessageId`); otherwise the
source label is used as-is.

## Tests

- **FE:** `resolveToolDisplayMessage` / `getToolOutputLabelEntries`
(status selection, inner-name resolution, `code_interpreter` model
labels, fallbacks).
- **BE:** `toolSetToDescriptors` (label map + humanized fallback) and
`database-tool.provider` label generation.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21976?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-24 13:41:09 +02:00
Vincent Vu 680e4a712b feat(ui): additional social providers to link components (#21716)
The current link component matches only to linkedin, twitter and
facebook.

It is currently missing the x handle. In addition to this, we should
also accomodate for instagram, bluesky and tiktok.

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

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-06-24 12:21:17 +02:00
Paul Rastoin d2387430a1 Factorize from entity to flat entity utils (#21972)
## What

Factorizes the two responsibilities that were copy‑pasted across every
`from-<entity>-entity-to-flat-<entity>` util into two reusable tools.

### `fromEntityToScalarEntity`
Projects a TypeORM entity into its scalar flat shape using an
**allow‑list** driven by
`ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME` (plus the base
columns `id`/`workspaceId`/`applicationId`/`universalIdentifier`). Only
registered scalar columns are forwarded, `Date`s are serialized to ISO
strings, and absent values are normalized to `null`. Replaces the
previous deny‑list (`removePropertiesFromRecord`) approach, so
unregistered/deprecated columns can no longer silently leak into the
flat entity.

### `resolveManyToOneRelationIdsToUniversalIdentifiers`
Resolves an entity's many‑to‑one foreign keys to their universal
identifiers, driven by `ALL_MANY_TO_ONE_METADATA_RELATIONS`. Handles the
always‑present `application`, nullable relations, and throws a
`FlatEntityMapsException` when a referenced id is missing from its
identifier map. Mirrors `resolveUniversalRelationIdentifiersToIds` in
the opposite direction.

Each `from-<entity>` util now reduces to: scalar spread + relation
spread (+ explicit one‑to‑many id/universalIdentifier arrays where
applicable).

### Note
The allow‑list drops `isUIReadOnly` (a `WasRemovedInUpgrade` column not
in the config) from `fieldMetadata`, which is the only
integration‑snapshot change.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21972?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-24 10:20:09 +00:00
Thomas des Francs 41d1b478b0 Fix Opportunity email timeline relation traversal (#22064)
## Summary
- Stop the related-person path walker from traversing system objects
while deriving timeline people.
- Keep direct `person` terminal paths valid so CRM relations still
resolve.
- Add a regression test covering the bad Opportunity owner -> workspace
member -> message participant path.

## Root Cause
PR #21684 introduced generic relation traversal for email and calendar
timelines. That traversal walks relation paths from the current record
to `person`, then the Emails tab loads message threads for those derived
people.

For Opportunities, the traversal was too broad because it could enter
internal/system objects. In particular, it could follow:

`opportunity.owner -> workspaceMember.messageParticipants ->
messageParticipant.person`

That path does not describe people related to the Opportunity. It
describes people who appeared in messages involving the Opportunity
owner. As a result, an Opportunity owned by Josh could show threads from
Josh's broader mailbox activity, which matches the customer report:
recently communicated people appeared in the Opportunity Emails tab even
though they were not specifically related to that Opportunity.

## Behavior Before
On an Opportunity record, the Emails tab could include message threads
for:
- the Opportunity point of contact;
- people related through the Opportunity company;
- people reached through internal/system relations, including the owner
workspace member's message participants.

The last category was the regression. It made the Opportunity Emails tab
look like a broad inbox for the owner instead of a timeline for people
related to the CRM record.

## Behavior After
The traversal still allows valid CRM person paths, including:

`opportunity.pointOfContact -> person`

and non-system CRM paths such as:

`opportunity.company -> company.people -> person`

But it now stops before traversing system objects such as
`workspaceMember` and `messageParticipant`. This blocks the bad
owner-mailbox expansion path:

`opportunity.owner -> workspaceMember.messageParticipants ->
messageParticipant.person`

Email sync is unchanged. This only changes which synced emails are
displayed on a record timeline.

## Video


https://github.com/user-attachments/assets/26de4cee-06d9-4f42-b91e-32e60a260b5b

## Validation
- `yarn nx jest twenty-server
src/engine/core-modules/related-person-ids/utils/__tests__/find-relation-paths-to-person.util.spec.ts
--runInBand`
- Focused `oxlint` and `oxfmt` on the touched files.
- GitHub `server-lint-typecheck` passes on the updated branch.
- Browser verification on local Apple seed workspace: fixed relation set
renders `Inbox 280`; the excluded owner-derived path would have resolved
`300` threads.
2026-06-24 12:06:37 +02:00
Rashad Karanouh eb53dee3be fix(twenty-partners): opportunity stage constants + Partners per Stage table (v1.1.9) (#22052)
## Summary

Two related cleanup items for the partners workspace:

### 1. Opportunity `stage` field — shared constant + reference catalog

- Adds `src/constants/opportunity-stage-options.ts` exporting
`OPPORTUNITY_STAGE_FIELD_UNIVERSAL_IDENTIFIER` and an
`OPPORTUNITY_STAGE_OPTIONS` catalog (stock stages + **Done** /
**Dead**).
- **`deals-board.view.ts`** imports the shared field id instead of
inlining `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`.
- The catalog is **not** synced by the app manifest — it documents
planned option ids for scripts/reference only.

**Done / Dead on prod:** added manually in Settings → Objects →
Opportunity → Stage (not via app sync). `defineField` extension of the
standard `stage` field was attempted and rejected
(`FIELD_ALREADY_EXISTS`). Deals kanban groups in the manifest stay
NEW–CUSTOMER only; Done/Dead columns appear when the workspace has those
options.

**Prod data cleanup (outside this PR):** all opportunities moved to
**Done** except `ed95573c-cbe6-4dcc-a459-5369a7449636` (Aranya CRM
Migration, kept in **New**).

### 2. Partners per Stage view — TABLE with stage grouping

Replaces the old KANBAN board with a **grouped TABLE** (same pattern as
Partners per Country / Applications):

- **Type:** `TABLE` (was `KANBAN`)
- **Group by:** `validationStage` — Application, Potential, Validated,
Former, Rejected
- **Columns:** Name, Country, Categories (`partnerScope`), Tier
(`partnerTier`)
- **Nav icon:** `IconTable`

View / view-field / group universal ids were aligned to prod after
KANBAN→TABLE install recreated the view (Twenty cannot change view type
in place).

## Version

**`1.1.9`** in this branch. Pre-merge deploys to `partner-twenty-com`
went through **1.1.5 → 1.1.11** while iterating on the view; prod may be
ahead of this branch’s pinned view id — one more id-alignment install
after merge may be needed if nav doesn’t land on the grouped table.

## Files touched (twenty-partners only)

| File | Change |
|---|---|
| `src/constants/opportunity-stage-options.ts` | New — stage field id +
option catalog |
| `src/views/deals-board.view.ts` | Import shared stage field constant |
| `src/views/partners-per-stage.view.ts` | KANBAN → grouped TABLE +
columns |
| `src/navigation-menu-items/partners-per-stage.navigation-menu-item.ts`
| Icon → `IconTable` |
| `package.json` | **1.1.9** |

## Test plan

- [x] `yarn lint` in `packages/twenty-apps/internal/twenty-partners` —
0/0
- [x] Prod: Done/Dead stage options present; Deals kanban shows 7
columns, no duplicates
- [x] Prod: Partners per Stage — TABLE grouped by validation stage with
Name / Country / Categories / Tier
- [x] Prod: Opportunity cleanup — 20 → Done, 1 stays New (Aranya CRM
Migration)
- [ ] After merge + install on fresh workspace: Partners per Stage
grouping renders without manual view fixes
2026-06-24 11:52:23 +02:00
Weiko b7850a6c64 feat(metadata): deterministic universalIdentifiers for server-generated side-effects (#21949)
## Context

Server-generated "side-effect" entities created for every object (system
fields, INDEX view, record-page fields view + view fields, search-vector
index, navigation command, record page layout/tabs/widgets) were minted
with random v4() ids. Because they were non-deterministic, nothing could
reference them by id (e.g. point a view field at an object's createdAt
field).

This PR introduces a single shared rule for deriving these ids
deterministically via uuid v5, so the same (owner app, parent, kind)
always yields the same id, making side-effects referable and
reproducible.

This is the **forward-only foundation** (PR1). Follow-ups:
- PR2: SDK with optional universalIdentifier + expose helpers to app
authors.
- PR3: regenerate the standard-app constants to the same scheme +
workspace backfill.

## The rule
```ts
universalIdentifier = computeOwnerScopedUniversalIdentifier({ ownerAppUID, namespace, value })
                    = v5(value, v5(ownerAppUID, ENTITY_TYPE_NAMESPACE))

value = `${parentUID}:${discriminator}`   // entity scoped under a parent
      = `${discriminator}`                // top-level, app-parented entity
```
- ownerAppUID: The application that owns the entity (already threaded
through every generator as applicationUniversalIdentifier); folded into
the namespace so it both owns and scopes
the id — two apps adding the same-named entity to a shared parent never
collide.
- namespace: Per entity type (ENTITY_TYPE_NAMESPACE_BY_TYPE), so
different types with the same parent+discriminator never collide.
- parentUID: The immediate parent's actual universalIdentifier (omitted
for top-level entities, since the owner app already scopes them).
- discriminator: A stable semantic key (field name, tab/widget title,
generated index name, select-option value, …).

Scope boundary: deterministic v5 applies to system side-effects (unique
by construction) and, later, app-authored manifest entities (uniqueness
enforced at SDK build time).
Entities created through the UI by the workspace "Custom" app (custom
objects/views/fields) keep v4, their natural keys aren't unique and
aren't enforced. A UI-created custom object keeps its v4 id; its
side-effects are deterministic relative to that v4 parent.

Changes

twenty-shared: new application/deterministic-identifier/ module:
- computeDeterministicUuid(value, namespace) primitive + a thin
computeOwnerScopedUniversalIdentifier wrapper (boilerplate only), and
frozen ENTITY_TYPE_NAMESPACE_BY_TYPE.
- One self-contained util per usecase (no central registry, no generic
engine): each util bakes in its own discriminator + namespace, so a key
lives next to the code that uses it and is individually testable. ~28
utils covering side-effect and (future) app-authored entities, e.g.
getFieldUniversalIdentifier, getIndexViewUniversalIdentifier,
getFieldsWidgetViewUniversalIdentifier, getViewFieldUniversalIdentifier,
getIndexUniversalIdentifier, getRecordPageLayoutUniversalIdentifier,
getPageLayoutTab/WidgetUniversalIdentifier,
getNavigationCommandUniversalIdentifier, plus the general
getViewUniversalIdentifier / getPageLayoutUniversalIdentifier and
app-authored
getObject/Role/PermissionFlag/Agent/Skill/…UniversalIdentifier.
- Golden snapshot test locking every util's output for fixed inputs,
plus a cross-type no-collision test.

twenty-server: side-effect generators now derive universalIdentifier via
the helpers (local id PKs stay v4()): system fields + name, INDEX view,
record-page fields (fields-widget) view, default view fields,
search-vector index, nav command, page layout/tabs/widgets. Index ids
key off the generated Postgres index name; extracted
computeFlatIndexNameOrThrow so the name (and therefore the id) is
computed once with no placeholder.

## Timeline

### What actually changes

- New objects (custom objects created via Settings/metadata API) and
fresh standard installs now get deterministic v5 universalIdentifiers
for all side-effect entities (system fields,
views, view fields, search index, nav command, page layout/tabs/widgets)
instead of random v4().
- The nav-command id formula changed (new owner-scoped) for new objects,
fresh standard installs, and the runtime lookup.

### What does NOT change

- Existing objects' side-effect ids — untouched (no migration;
forward-only).
- Standard object UIDs — untouched
- UI-created custom entities' own ids stay v4 (see scope boundary
above).
- Fresh installs are behaviorally a no-op — ids are internal; re-sync
produces no diff (verified). Nothing user-visible.

### The one real-world impact / risk (existing workspaces)

The nav-command runtime lookup (findNavigationCommandMenuItemForObject)
now computes the new formula, but existing workspaces' nav commands were
stored with the old formula. So on an upgraded existing workspace, until
the PR3 backfill:
- Object activate/deactivate toggle for existing objects won't find the
nav command → re-activating can create a duplicate nav command;
deactivating may no-op.
- Object deletion won't find/clean up the old nav command → orphaned
nav-command row.

### What app developers get right now

Nothing usable yet. The helpers exist in twenty-shared but aren't
re-exported from twenty-sdk (PR2), and app-authored objects still get
SDK-derived ids in the old format until PR2
re-mints them. So "reference a server entity by deterministic id"
doesn't work end-to-end until PR2
2026-06-24 11:47:44 +02:00
martmull 21c3574f05 docs(apps): add key-value store guide for logic functions (#22061)
## What

Adds a new docs page under **Developers → Extend → Apps → Logic**
explaining how to give logic functions key-value storage (to persist
intermediate results, cache data, and share state across runs).

Rather than introducing a dedicated storage primitive, the guide shows
how to achieve this with a small **technical object** ("KV Store") that
has a unique `key` field and a `RAW_JSON` `value` field — queried
through the existing typed `CoreApiClient`.

Closes the documentation part of
[core-team-issues#2427](https://github.com/twentyhq/core-team-issues/issues/2427).

## Contents of the new page

- `defineObject` for the `kvStore` object (`key` + `value`)
- A unique index on `key` (the recommended uniqueness primitive)
- `get` / `set` (upsert) / `del` helpers built on `CoreApiClient`
- A worked example: caching an expensive third-party call with a TTL
- Patterns & tips: namespacing, expiry, what to store,
visibility/permissions, per-record scoping

## Files

- `developers/extend/apps/logic/key-value-store.mdx` — the new page
- `navigation/base-structure.json` — navigation source-of-truth
- `docs.json` + `twenty-shared/.../DocumentationPaths.ts` — regenerated
from base-structure

## Notes

- Documentation only — no code/behavior changes.
- This is a convention (a regular custom object), not a new feature, so
it inherits the same sync, permissions, and tooling as the rest of an
app's data.

https://claude.ai/code/session_01XAgXy1mUUMff5BFkFPjtfZ

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

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22061?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-24 11:45:35 +02:00
Rashad Karanouh 6ae6703e7d Map TFT useCase to partners need on opportunity import (#22054)
## Summary
- Accept optional `useCase` in the TFT → partners
`import-opportunity-from-tft` webhook payload
- Map it to `Opportunity.need` on create (TFT Use Case → partners Needs)
- Add unit tests for happy path and null `useCase` handling
- Bump twenty-partners to 1.1.4 (patch)

## Test plan
- [x] `yarn test:unit` (43 tests passing)
- [x] `yarn lint` (0 errors)
- [ ] Deploy to local/partners workspace with `yarn twenty dev --once`
- [ ] POST smoke test with `useCase` in body; confirm **Need** field
populated
- [ ] TFT workflow: add `"useCase": "{{record.useCase}}"` to HTTP body
(manual)

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22054?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-24 11:43:46 +02:00
martmull 269c8ef400 feat(front): allow advanced relation fields in FieldWidget selector (#22005)
## After

<img width="706" height="760" alt="image"
src="https://github.com/user-attachments/assets/d118285f-baab-4187-988c-d0180d61a629"
/>
<img width="707" height="372" alt="image"
src="https://github.com/user-attachments/assets/5676d829-2ec1-494e-a8f0-5998f1f0c3c8"
/>


## Summary

The FieldWidget field-selection dropdown currently filters out relation
fields whose target is a system object, so users can't pick fields like
`calendarEventParticipants` on the CalendarEvent record page. The widget
itself can render them just fine as boxed relations — the restriction
only lives in the picker.

This unblocks the consistency story from #22003 (revert of #21857): once
shipped, participants can be added to the calendar event record page via
the existing FieldWidget mechanism instead of a bespoke side-panel page.

## Changes

- `isFieldCellSupported`: adds an opt-in `includeSystemObjectRelations`
option that skips the `isObjectMetadataAvailableForRelation` system
check.
- `useFieldListFieldMetadataItems`: forwards the option through to
`isFieldCellSupported`. Default is `false`, so all existing callers keep
current behavior.
- `useFieldWidgetEligibleFields`: turns the option on, so the
FieldWidget selector now surfaces fields like
`calendarEventParticipants`, `messageParticipants`, etc.

## Test plan

- [x] `nx typecheck twenty-front`
- [x] `nx lint:diff-with-main twenty-front`
- [ ] CI
- [ ] Manually verify the FieldWidget dropdown now lists
`calendarEventParticipants` on a CalendarEvent record page, and that
selecting it renders a participants list via the existing relation
card/field widget.

https://claude.ai/code/session_01RnMcjL35wdCRzpXN257RLJ

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

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22005?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-24 10:30:42 +02:00
Paul Rastoin f98f514640 Introduce search field metadata in 2 16 (#22055)
# Introduction

The devpx wasn't prepare for an already existing entity becoming a
syncable entity
Though the search field metadata entity was dormant anw
So considering it has been introduced starting from 2.16 is the quickest
and easiest tradeoff we can get

This PR is also reverting this one
https://github.com/twentyhq/twenty/pull/22039 that was introducing a new
way to decorate an entity at class level. But it did not fixed the issue

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22055?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-24 08:18:59 +00:00