mirror of
https://github.com/twentyhq/twenty
synced 2026-04-21 13:37:22 +00:00
543 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
83bc6d1a1b
|
[Website] Self-host billing migration and some responsiveness fixes. (#19894)
Closes the following issues. https://github.com/twentyhq/core-team-issues/issues/2371 https://github.com/twentyhq/core-team-issues/issues/2379 https://github.com/twentyhq/core-team-issues/issues/2383 |
||
|
|
fd2288bfff
|
fix: prototype pollution via parse in nodejs flatted (#19870)
Resolves [Dependabot Alert 686](https://github.com/twentyhq/twenty/security/dependabot/686). |
||
|
|
75848ff8ea
|
feat: move admin panel to dedicated /admin-panel GraphQL endpoint (#19852)
Some checks are pending
CD deploy main / deploy-main (push) Waiting to run
CI Create App E2E minimal / changed-files-check (push) Waiting to run
CI Create App E2E minimal / create-app-e2e-minimal (push) Blocked by required conditions
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Blocked by required conditions
CI Emails / emails-test (push) Blocked by required conditions
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Blocked by required conditions
CI Example App Postcard / changed-files-check (push) Waiting to run
CI Example App Postcard / example-app-postcard (push) Blocked by required conditions
CI Example App Postcard / ci-example-app-postcard-status-check (push) Blocked by required conditions
Push translations to Crowdin / Extract and upload translations (push) Waiting to run
CI Create App / changed-files-check (push) Waiting to run
CI Create App / create-app-test (lint) (push) Blocked by required conditions
CI Create App / create-app-test (test) (push) Blocked by required conditions
CI Create App / create-app-test (typecheck) (push) Blocked by required conditions
CI Create App / ci-create-app-status-check (push) Blocked by required conditions
CI Docs / changed-files-check (push) Waiting to run
CI Docs / docs-lint (push) Blocked by required conditions
CI Emails / changed-files-check (push) Waiting to run
CI Emails / ci-emails-status-check (push) Blocked by required conditions
CI Example App Hello World / changed-files-check (push) Waiting to run
CI Example App Hello World / example-app-hello-world (push) Blocked by required conditions
## Summary Splits admin-panel resolvers off the shared `/metadata` GraphQL endpoint onto a dedicated `/admin-panel` endpoint. The backend plumbing mirrors the existing `metadata` / `core` pattern (new scope, decorator, module, factory), and admin types now live in their own `generated-admin/graphql.ts` on the frontend — dropping 877 lines of admin noise from `generated-metadata`. ## Why - **Smaller attack surface on `/metadata`** — every authenticated user hits that endpoint; admin ops don't belong there. - **Independent complexity limits and monitoring** per endpoint. - **Cleaner module boundaries** — admin is a cross-cutting concern that doesn't match the "shared-schema configuration" meaning of `/metadata`. - **Deploy / blast-radius isolation** — a broken admin query can't affect `/metadata`. Runtime behavior, auth, and authorization are unchanged — this is a relocation, not a re-permissioning. All existing guards (`WorkspaceAuthGuard`, `UserAuthGuard`, `SettingsPermissionGuard(SECURITY)` at class level; `AdminPanelGuard` / `ServerLevelImpersonateGuard` at method level) remain on `AdminPanelResolver`. ## What changed ### Backend - `@AdminResolver()` decorator with scope `'admin'`, naming parallels `CoreResolver` / `MetadataResolver`. - `AdminPanelGraphQLApiModule` + `adminPanelModuleFactory` registered at `/admin-panel`, same Yoga hook set as the metadata factory (Sentry tracing, error handler, introspection-disabling in prod, complexity validation). - Middleware chain on `/admin-panel` is identical to `/metadata`. - `@nestjs/graphql` patch extended: `resolverSchemaScope?: 'core' | 'metadata' | 'admin'`. - `AdminPanelResolver` class decorator swapped from `@MetadataResolver()` to `@AdminResolver()` — no other changes. ### Frontend - `codegen-admin.cjs` → `src/generated-admin/graphql.ts` (982 lines). - `codegen-metadata.cjs` excludes admin paths; metadata file shrinks by 877 lines. - `ApolloAdminProvider` / `useApolloAdminClient` follow the existing `ApolloCoreProvider` / `useApolloCoreClient` pattern, wired inside `AppRouterProviders` alongside the core provider. - 37 admin consumer files migrated: imports switched to `~/generated-admin/graphql` and `client: useApolloAdminClient()` is passed to `useQuery` / `useMutation`. - Three files intentionally kept on `generated-metadata` because they consume non-admin Documents: `useHandleImpersonate.ts`, `SettingsAdminApplicationRegistrationDangerZone.tsx`, `SettingsAdminApplicationRegistrationGeneralToggles.tsx`. ### CI - `ci-server.yaml` runs all three `graphql:generate` configurations and diff-checks all three generated dirs. ## Authorization (unchanged, but audited while reviewing) Every one of the 38 methods on `AdminPanelResolver` has a method-level guard: - `AdminPanelGuard` (32 methods) — requires `canAccessFullAdminPanel === true` - `ServerLevelImpersonateGuard` (6 methods: user/workspace lookup + chat thread views) — requires `canImpersonate === true` On top of the class-level guards above. No resolver method is accessible without these flags + `SECURITY` permission in the workspace. ## Test plan - [ ] Dev server boots; `/graphql`, `/metadata`, `/admin-panel` all mapped as separate GraphQL routes (confirmed locally during development). - [ ] `nx typecheck twenty-server` passes. - [ ] `nx typecheck twenty-front` passes. - [ ] `nx lint:diff-with-main twenty-server` and `twenty-front` both clean. - [ ] Manual smoke test: log in with a user who has `canAccessFullAdminPanel=true`, open the admin panel at `/settings/admin-panel`, verify each tab loads (General, Health, Config variables, AI, Apps, Workspace details, User details, chat threads). - [ ] Manual smoke test: log in with a user who has `canImpersonate=false` and `canAccessFullAdminPanel=false`, hit `/admin-panel` directly with a raw GraphQL request, confirm permission error on every operation. - [ ] Production deploy note: reverse proxy / ingress must route the new `/admin-panel` path to the Nest server. If the proxy has an explicit allowlist, infra change required before cutover. ## Follow-ups (out of scope here) - Consider cutting over the three `SettingsAdminApplicationRegistration*` components to admin-scope versions of the app-registration operations so the admin page is fully on the admin endpoint. - The `renderGraphiQL` double-assignment in `admin-panel.module-factory.ts` is copied from `metadata.module-factory.ts` — worth cleaning up in both. |
||
|
|
dbf43d792c
|
[Website] Fix testimonials shape, diamond direction, and integrate partner application form. (#19835)
Closes the following issues. https://github.com/twentyhq/core-team-issues/issues/2368 https://github.com/twentyhq/core-team-issues/issues/2369 https://github.com/twentyhq/core-team-issues/issues/2374 https://github.com/twentyhq/core-team-issues/issues/2375 |
||
|
|
ce2a0bfbe5
|
fix: socket.io allows an unbounded number of binary attachments (#19812)
Resolves [Dependabot Alert 683](https://github.com/twentyhq/twenty/security/dependabot/683). |
||
|
|
cdc7339da1
|
Fix testimonials background, faq clickability and some case-studies page edits. (#19657)
As title. Also copied release-notes related files from `twenty-website` to `twenty-website-new`. |
||
|
|
84b325876d
|
More website updates. (#19624)
This PR introduces more updates to the website, such as real testimonials, case studies, copy of pricing plans table. It also adds modals for "Talk to Us" and "Become a Partner". |
||
|
|
6e259d3ded
|
Inline twenty-shared types in SDK declarations (#19605)
## Summary - `twenty-shared` is private and never published to npm, so SDK consumers couldn't resolve type imports like `from 'twenty-shared/types'` in the generated `.d.ts` files - Replace `vite.config.sdk.ts` with `rollup-plugin-dts` which compiles `src/sdk/index.ts` directly into a self-contained `dist/sdk/index.d.ts` with all `twenty-shared` types inlined - The JS output from `vite.config.sdk.ts` (`dist/sdk/*.js`) was unused — the main export already maps to `dist/index.mjs` from the node Vite config ## Changes - **Deleted** `vite.config.sdk.ts` — its preserved-module JS output wasn't referenced by any `package.json` export - **Added** `rollup.config.dts.mjs` — uses `rollup-plugin-dts` to compile SDK types from source with `twenty-shared` inlined (~850ms) - **Updated** `project.json` — build/dev/build:sdk targets now use rollup instead of the removed vite config - **Updated** `tsconfig.json` — removed `vite.config.sdk.ts` from include ## Test plan - [ ] Run `npx nx build twenty-sdk` and verify `dist/sdk/index.d.ts` contains no `twenty-shared` references - [ ] Verify `dist/index.mjs` and `dist/index.cjs` are still produced correctly - [ ] Verify CLI (`dist/cli.cjs`) still works - [ ] Verify `npx nx build:sdk twenty-sdk` works standalone Made with [Cursor](https://cursor.com) |
||
|
|
5116002ca2
|
chore: replace glb files and lottie with optimized variants (#19503)
As per title. Replaced .json file with .lottie file - it is 10x smaller. Illustrations folder went from 150mb to 5.9mb with compressed variants of 3D models. The DracoLoader, GLTFLoader and some other logic logic is repetitive across files, but Thomas is working on the same files at the moment, so not touching too much to avoid conflicts with his PR. Once he's done styling, we can extract shared logic into helpers. |
||
|
|
1b8f26323a
|
Bump @babel/preset-react from 7.26.3 to 7.28.5 (#19475)
Bumps [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) from 7.26.3 to 7.28.5. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/babel/babel/releases"><code>@babel/preset-react</code>'s releases</a>.</em></p> <blockquote> <h2>v7.28.5 (2025-10-23)</h2> <p>Thank you <a href="https://github.com/CO0Ki3"><code>@CO0Ki3</code></a>, <a href="https://github.com/Olexandr88"><code>@Olexandr88</code></a>, and <a href="https://github.com/youthfulhps"><code>@youthfulhps</code></a> for your first PRs!</p> <h4>👓 Spec Compliance</h4> <ul> <li><code>babel-parser</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17446">#17446</a> Allow <code>Runtime Errors for Function Call Assignment Targets</code> (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> <li><code>babel-helper-validator-identifier</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17501">#17501</a> fix: update identifier to unicode 17 (<a href="https://github.com/fisker"><code>@fisker</code></a>)</li> </ul> </li> </ul> <h4>🐛 Bug Fix</h4> <ul> <li><code>babel-plugin-proposal-destructuring-private</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17534">#17534</a> Allow mixing private destructuring and rest (<a href="https://github.com/CO0Ki3"><code>@CO0Ki3</code></a>)</li> </ul> </li> <li><code>babel-parser</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17521">#17521</a> Improve <code>@babel/parser</code> error typing (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> <li><a href="https://redirect.github.com/babel/babel/pull/17491">#17491</a> fix: improve ts-only declaration parsing (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> <li><code>babel-plugin-proposal-discard-binding</code>, <code>babel-plugin-transform-destructuring</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17519">#17519</a> fix: <code>rest</code> correctly returns plain array (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> <li><code>babel-helper-create-class-features-plugin</code>, <code>babel-helper-member-expression-to-functions</code>, <code>babel-plugin-transform-block-scoping</code>, <code>babel-plugin-transform-optional-chaining</code>, <code>babel-traverse</code>, <code>babel-types</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17503">#17503</a> Fix <code>JSXIdentifier</code> handling in <code>isReferencedIdentifier</code> (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> <li><code>babel-traverse</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17504">#17504</a> fix: ensure scope.push register in anonymous fn (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> </ul> <h4>🏠 Internal</h4> <ul> <li><code>babel-types</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17494">#17494</a> Type checking babel-types scripts (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> </ul> <h4>🏃♀️ Performance</h4> <ul> <li><code>babel-core</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17490">#17490</a> Faster finding of locations in <code>buildCodeFrameError</code> (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> </ul> <h4>Committers: 8</h4> <ul> <li>Babel Bot (<a href="https://github.com/babel-bot"><code>@babel-bot</code></a>)</li> <li>Byeongho Yoo (<a href="https://github.com/youthfulhps"><code>@youthfulhps</code></a>)</li> <li>Huáng Jùnliàng (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> <li>Hyeon Dokko (<a href="https://github.com/CO0Ki3"><code>@CO0Ki3</code></a>)</li> <li>Nicolò Ribaudo (<a href="https://github.com/nicolo-ribaudo"><code>@nicolo-ribaudo</code></a>)</li> <li><a href="https://github.com/Olexandr88"><code>@Olexandr88</code></a></li> <li><a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a></li> <li>fisker Cheung (<a href="https://github.com/fisker"><code>@fisker</code></a>)</li> </ul> <h2>v7.28.4 (2025-09-05)</h2> <p>Thanks <a href="https://github.com/gwillen"><code>@gwillen</code></a> and <a href="https://github.com/mrginglymus"><code>@mrginglymus</code></a> for your first PRs!</p> <h4>🏠 Internal</h4> <ul> <li><code>babel-core</code>, <code>babel-helper-check-duplicate-nodes</code>, <code>babel-traverse</code>, <code>babel-types</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17493">#17493</a> Update Jest to v30.1.1 (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> <li><code>babel-plugin-transform-regenerator</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17455">#17455</a> chore: Clean up <code>transform-regenerator</code> (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/babel/babel/blob/main/CHANGELOG.md"><code>@babel/preset-react</code>'s changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <blockquote> <p><strong>Tags:</strong></p> <ul> <li>💥 [Breaking Change]</li> <li>👓 [Spec Compliance]</li> <li>🚀 [New Feature]</li> <li>🐛 [Bug Fix]</li> <li>📝 [Documentation]</li> <li>🏠 [Internal]</li> <li>💅 [Polish]</li> </ul> </blockquote> <p><em>Note: Gaps between patch versions are faulty, broken or test releases.</em></p> <p>This file contains the changelog starting from v8.0.0-alpha.0.</p> <ul> <li>See <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v7.15.0-v7.28.5.md">CHANGELOG - v7.15.0 to v7.28.5</a> for v7.15.0 to v7.28.5 changes (the last common release between the v8 and v7 release lines was v7.28.5).</li> <li>See <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v7.0.0-v7.14.9.md">CHANGELOG - v7.0.0 to v7.14.9</a> for v7.0.0 to v7.14.9 changes.</li> <li>See <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v7-prereleases.md">CHANGELOG - v7 prereleases</a> for v7.0.0-alpha.1 to v7.0.0-rc.4 changes.</li> <li>See <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v4.md">CHANGELOG - v4</a>, <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v5.md">CHANGELOG - v5</a>, and <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v6.md">CHANGELOG - v6</a> for v4.x-v6.x changes.</li> <li>See <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-6to5.md">CHANGELOG - 6to5</a> for the pre-4.0.0 version changelog.</li> <li>See <a href="https://github.com/babel/babel/blob/main/packages/babel-parser/CHANGELOG.md">Babylon's CHANGELOG</a> for the Babylon pre-7.0.0-beta.29 version changelog.</li> <li>See <a href="https://github.com/babel/babel-eslint/releases"><code>babel-eslint</code>'s releases</a> for the changelog before <code>@babel/eslint-parser</code> 7.8.0.</li> <li>See <a href="https://github.com/babel/eslint-plugin-babel/releases"><code>eslint-plugin-babel</code>'s releases</a> for the changelog before <code>@babel/eslint-plugin</code> 7.8.0.</li> </ul> <!-- raw HTML omitted --> <!-- raw HTML omitted --> <h2>v8.0.0-rc.3 (2026-03-16)</h2> <h4>👓 Spec Compliance</h4> <ul> <li><code>babel-parser</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17839">#17839</a> Fix(parser): async x => {} must be in leading pos (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> <li><a href="https://redirect.github.com/babel/babel/pull/17803">#17803</a> Disallow non-leading solo await within F# pipeline (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> </ul> <h4>💥 Breaking Change</h4> <ul> <li><code>babel-parser</code>, <code>babel-plugin-proposal-do-expressions</code>, <code>babel-plugin-proposal-pipeline-operator</code>, <code>babel-plugin-transform-exponentiation-operator</code>, <code>babel-plugin-transform-instanceof</code>, <code>babel-traverse</code>, <code>babel-types</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17867">#17867</a> [Babel 8] Remove <code>Import</code> from the <code>Expression</code> alias (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> <li><code>babel-plugin-transform-react-jsx-development</code>, <code>babel-plugin-transform-react-jsx</code>, <code>babel-preset-react</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17845">#17845</a> Gate jsxDEV source/self with <code>developmentSourceSelf</code> option (<a href="https://github.com/rootvector2"><code>@rootvector2</code></a>)</li> </ul> </li> <li><code>babel-generator</code>, <code>babel-parser</code>, <code>babel-types</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17835">#17835</a> fix: Remove <code>decorators</code> from <code>TSDeclareMethod</code> (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> <li><code>babel-helper-import-to-platform-api</code>, <code>babel-plugin-proposal-import-wasm-source</code>, <code>babel-plugin-transform-json-modules</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17816">#17816</a> Pass <code>file</code> instead of <code>path</code> to importToPlatformApi builders (<a href="https://github.com/nicolo-ribaudo"><code>@nicolo-ribaudo</code></a>)</li> </ul> </li> </ul> <h4>🚀 New Feature</h4> <ul> <li><code>babel-plugin-transform-react-jsx-development</code>, <code>babel-plugin-transform-react-jsx</code>, <code>babel-preset-react</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17862">#17862</a> Add <code>sourceSelf</code> option to <code>@babel/plugin-transform-react-jsx-development</code> (<a href="https://github.com/nicolo-ribaudo"><code>@nicolo-ribaudo</code></a>)</li> </ul> </li> <li><code>babel-parser</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/16935">#16935</a> feat: Add <code>locations</code> option to parser (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
80337d5c37
|
Bump tsdav from 2.1.5 to 2.1.8 (#19476)
Bumps [tsdav](https://github.com/natelindev/tsdav) from 2.1.5 to 2.1.8. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/natelindev/tsdav/releases">tsdav's releases</a>.</em></p> <blockquote> <h2>v2.1.8</h2> <h5>improvements</h5> <ul> <li>fixed <a href="https://redirect.github.com/natelindev/tsdav/issues/272">#272</a> malformed expand request in fetchCalendarObjects</li> <li>optimized fetchCalendarObjects to reduce redundant requests when expand is true</li> <li>added Bearer auth support for token-based providers (e.g., Nextcloud OIDC)</li> <li>added fetch overrides across account, request, and collection helpers for custom transports</li> <li>prefer native fetch in Cloudflare Workers to avoid cross-fetch incompatibilities</li> <li>collectionQuery now rejects on non-OK responses instead of returning empty arrays</li> <li>fetchVCards filters out collection URLs to avoid empty/invalid entries (Radicale-compatible)</li> <li>docs updates for iCal feed import, providers, and custom transport guidance</li> </ul> <h2>v2.1.7</h2> <h2>What's Changed</h2> <ul> <li>Fix: Handle empty body responses in davRequest to prevent crash by <a href="https://github.com/hsvtslv"><code>@hsvtslv</code></a> in <a href="https://redirect.github.com/natelindev/tsdav/pull/267">natelindev/tsdav#267</a></li> <li>Fix npm authentication in auto-release workflow by <a href="https://github.com/Copilot"><code>@Copilot</code></a> in <a href="https://redirect.github.com/natelindev/tsdav/pull/271">natelindev/tsdav#271</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/hsvtslv"><code>@hsvtslv</code></a> made their first contribution in <a href="https://redirect.github.com/natelindev/tsdav/pull/267">natelindev/tsdav#267</a></li> <li><a href="https://github.com/Copilot"><code>@Copilot</code></a> made their first contribution in <a href="https://redirect.github.com/natelindev/tsdav/pull/271">natelindev/tsdav#271</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/natelindev/tsdav/compare/v2.1.6...v2.1.7">https://github.com/natelindev/tsdav/compare/v2.1.6...v2.1.7</a></p> <h2>v2.1.6</h2> <h5>improvements</h5> <ul> <li>added AGENTS.md</li> <li>updated dependencies</li> <li>fixed docs build issues</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/natelindev/tsdav/blob/main/CHANGELOG.md">tsdav's changelog</a>.</em></p> <blockquote> <h2>v2.1.8</h2> <h5>improvements</h5> <ul> <li>fixed <a href="https://redirect.github.com/natelindev/tsdav/issues/272">#272</a> malformed expand request in fetchCalendarObjects</li> <li>optimized fetchCalendarObjects to reduce redundant requests when expand is true</li> <li>added Bearer auth support for token-based providers (e.g., Nextcloud OIDC)</li> <li>added fetch overrides across account, request, and collection helpers for custom transports</li> <li>prefer native fetch in Cloudflare Workers to avoid cross-fetch incompatibilities</li> <li>collectionQuery now rejects on non-OK responses instead of returning empty arrays</li> <li>fetchVCards filters out collection URLs to avoid empty/invalid entries (Radicale-compatible)</li> <li>docs updates for iCal feed import, providers, and custom transport guidance</li> </ul> <h2>v2.1.7</h2> <h5>improvements</h5> <ul> <li>docs: add browser usage example and clarify class-based login</li> <li>docs: add Nextcloud connection guidance and Apple password reference</li> </ul> <h2>v2.1.6</h2> <h5>improvements</h5> <ul> <li>added AGENTS.md</li> <li>updated dependencies</li> <li>fixed docs build issues</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
91b40b391d
|
Bump graphql-sse from 2.5.4 to 2.6.0 (#19477)
Bumps [graphql-sse](https://github.com/enisdenjo/graphql-sse) from 2.5.4 to 2.6.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/enisdenjo/graphql-sse/releases">graphql-sse's releases</a>.</em></p> <blockquote> <h2>v2.6.0</h2> <h1><a href="https://github.com/enisdenjo/graphql-sse/compare/v2.5.4...v2.6.0">2.6.0</a> (2025-10-22)</h1> <h3>Features</h3> <ul> <li><strong>client:</strong> Support dynamic URLs and headers per request for distinct connection mode (<a href="https://redirect.github.com/enisdenjo/graphql-sse/issues/124">#124</a>) (<a href=" |
||
|
|
8a84e32cf6
|
fix(ai): use @ai-sdk/openai-compatible for third-party providers (#19438)
## Summary: I found a bug: 404 call when I use third-party providers (I used deepseek). I found the final request url is: `https://api.deepseek.com/v1/responses' `if we use createOpenAI. But the correct one should be `https://api.provider.com/v1/chat/completions` for the thirty provider. So I replace createOpenAI with createOpenAICompatible in the openai-compatible provider path. **Reproduction**: Add DeepSeek as a new AI provider (deepseek-chat, deepseek-reasoner) Also check the source code in Open Code project, they also use createOpenAICompatible for the @ai-sdk/openai-compatible scenario <img width="703" height="369" alt="image" src="https://github.com/user-attachments/assets/90c4f924-6f1a-4fe7-821b-f13ee86a7a39" /> official docs: https://ai-sdk.dev/providers/openai-compatible-providers https://ai-sdk.dev/providers/ai-sdk-providers/openai <img width="860" height="293" alt="image" src="https://github.com/user-attachments/assets/283b9b91-f1d6-4b1c-bb91-16ddccdff8b4" /> ## Before <img width="473" height="750" alt="deepseek before" src="https://github.com/user-attachments/assets/f6b89294-1fa7-4ddc-a6a8-d396070caaca" /> ## After <img width="468" height="753" alt="deepseek after" src="https://github.com/user-attachments/assets/0d170b70-e829-4a4c-abad-38879427c2df" /> ## Backend error log ```json [1] [Nest] 50907 - 07/04/2026, 23:48:57 LOG [ChatExecutionService] Starting chat execution with model deepseek/deepseek-chat, 4 active tools [1] APICallError [AI_APICallError]: Not Found [1] at /Users/abel/Documents/Code/twenty/node_modules/@ai-sdk/provider-utils/dist/index.js:2512:14 [1] at process.processTicksAndRejections (node:internal/process/task_queues:105:5) [1] at async postToApi (/Users/abel/Documents/Code/twenty/node_modules/@ai-sdk/provider-utils/dist/index.js:2373:28) [1] at async OpenAIResponsesLanguageModel.doStream (/Users/abel/Documents/Code/twenty/node_modules/@ai-sdk/openai/dist/index.js:4925:50) [1] at async fn (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:7106:27) [1] at async /Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:2340:24 [1] at async _retryWithExponentialBackoff (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:2599:12) [1] at async streamStep (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:7063:17) [1] at async fn (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:7455:9) [1] at async /Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:2340:24 { [1] cause: undefined, [1] url: 'https://api.deepseek.com/v1/responses', [1] requestBodyValues: { [1] model: 'deepseek-chat', [1] input: [ [Object], [Object] ], [1] temperature: undefined, [1] top_p: undefined, [1] max_output_tokens: undefined, [1] conversation: undefined, [1] max_tool_calls: undefined, [1] metadata: undefined, [1] parallel_tool_calls: undefined, [1] previous_response_id: undefined, [1] store: undefined, [1] user: undefined, [1] instructions: undefined, [1] service_tier: undefined, [1] include: undefined, [1] prompt_cache_key: undefined, [1] prompt_cache_retention: undefined, [1] safety_identifier: undefined, [1] top_logprobs: undefined, [1] truncation: undefined, [1] tools: [ [Object], [Object], [Object], [Object] ], [1] tool_choice: 'auto', [1] stream: true [1] }, [1] statusCode: 404, [1] responseHeaders: { [1] 'access-control-allow-credentials': 'true', [1] connection: 'keep-alive', [1] 'content-length': '0', [1] date: 'Tue, 07 Apr 2026 22:48:57 GMT', [1] server: 'elb', [1] 'strict-transport-security': 'max-age=31536000; includeSubDomains; preload', [1] vary: 'origin, access-control-request-method, access-control-request-headers', [1] via: '1.1 83867089cd39052cd05f9e04909bedde.cloudfront.net (CloudFront)', [1] 'x-amz-cf-id': 'O4b0VTi9Q1VVmTmq6czGlEWst7IPnAQl544hB7uIvfnSphBvUKbZTw==', [1] 'x-amz-cf-pop': 'DUB56-P3', [1] 'x-cache': 'Error from cloudfront', [1] 'x-content-type-options': 'nosniff', [1] 'x-ds-trace-id': 'a90e91809d285170338ef077f67ae2be' [1] }, [1] responseBody: '', [1] isRetryable: false, [1] data: undefined, [1] Symbol(vercel.ai.error): true, [1] Symbol(vercel.ai.error.AI_APICallError): true [1] } [1] Exception Captured [1] undefined [1] [ [1] NoOutputGeneratedError [AI_NoOutputGeneratedError]: No output generated. Check the stream for errors. [1] at Object.flush (/Users/abel/Documents/Code/twenty/node_modules/ai/dist/index.js:6656:103) [1] at invokePromiseCallback (node:internal/webstreams/util:172:10) [1] at Object.<anonymous> (node:internal/webstreams/util:177:23) [1] at transformStreamDefaultSinkCloseAlgorithm (node:internal/webstreams/transformstream:621:43) [1] at node:internal/webstreams/transformstream:379:11 [1] at writableStreamDefaultControllerProcessClose (node:internal/webstreams/writablestream:1162:28) [1] at writableStreamDefaultControllerAdvanceQueueIfNeeded (node:internal/webstreams/writablestream:1253:5) [1] at writableStreamDefaultControllerClose (node:internal/webstreams/writablestream:1220:3) [1] at writableStreamClose (node:internal/webstreams/writablestream:722:3) [1] at writableStreamDefaultWriterClose (node:internal/webstreams/writablestream:1091:10) { [1] cause: undefined, [1] Symbol(vercel.ai.error): true, [1] Symbol(vercel.ai.error.AI_NoOutputGeneratedError): true [1] } [1] ] [1] [Nest] 50907 - 07/04/2026, 23:48:59 LOG [BullMQDriver] Job 24 with name StreamAgentChatJob processed on queue ai-stream-queue in 2756.63ms |
||
|
|
1b14e7e1f1
|
Fix - Update package.json (#19390)
https://github.com/twentyhq/twenty/pull/19383#discussion_r3044330450 |
||
|
|
68cd2f6d61
|
fix: node-tar symlink path traversal via drive-relative linkpath (#19360)
Resolves [Dependabot Alert 619](https://github.com/twentyhq/twenty/security/dependabot/619) and [Dependabot Alert 629](https://github.com/twentyhq/twenty/security/dependabot/629). |
||
|
|
8c9228cb2b
|
fix: SVGO DoS through entity expansion in DOCTYPE (#19359)
Resolves [Dependabot Alert 604](https://github.com/twentyhq/twenty/security/dependabot/604) and [Dependabot Alert 605](https://github.com/twentyhq/twenty/security/dependabot/605). |
||
|
|
35b76539cc
|
fix: minimatch related dependabot alerts. (#19357)
Resolves [Dependabot Alert 491](https://github.com/twentyhq/twenty/security/dependabot/491). Expecting it to resolve a few other minimatch generated alerts too, but merging shall confirm which ones since minimatch has a lot of different versions being imported by different packages as a transitive dependency. |
||
|
|
ea572975d8
|
feat: generic web search driver abstraction with Exa support and billing (#19341)
## Summary - Introduces a pluggable `WebSearchDriver` abstraction (interface, factory, service, module) so web search is no longer tied to native provider tools (Anthropic/OpenAI) - **Exa** is the first driver implementation with support for category-filtered search (company, people, news, research paper, etc.) — particularly useful for CRM workflows - Per-query billing for both Exa ($0.007/query) and native provider surcharges ($0.01/query for Anthropic/OpenAI) via the existing `USAGE_RECORDED` pipeline - New config variables: `WEB_SEARCH_DRIVER` (EXA/DISABLED), `EXA_API_KEY`, `WEB_SEARCH_PREFER_NATIVE` (default false — prefers Exa over native when both available) - `WEB_SEARCH` operation type added for usage tracking and Stripe metering ### Architecture ``` WebSearchDriver (interface) ├── ExaDriver — Exa neural search with category support └── DisabledDriver — throws when search is disabled WebSearchDriverFactory (extends DriverFactoryBase) └── creates driver based on WEB_SEARCH_DRIVER config WebSearchService (facade) ├── search(query, options?, billingContext?) ├── isEnabled() └── emits USAGE_RECORDED events per query WebSearchTool (Tool implementation) └── registered in ActionToolProvider, available via tool catalog ``` ### Native search billing gap fixed Anthropic and OpenAI both charge $0.01/search on top of token costs. The token costs were already billed, but the per-call surcharge was not. Added `countNativeWebSearchCallsFromSteps` utility + `billNativeWebSearchUsage` to `AiBillingService`, wired into both chat and workflow agent paths. ## Test plan - [ ] Set `WEB_SEARCH_DRIVER=EXA` + `EXA_API_KEY=...` and verify AI chat can search the web - [ ] Verify category parameter works (ask about a specific company/person) - [ ] Set `WEB_SEARCH_DRIVER=DISABLED` and verify search tool is not exposed - [ ] Set `WEB_SEARCH_PREFER_NATIVE=true` with Anthropic model and verify native search is used - [ ] Verify usage events are emitted in ClickHouse for both Exa and native search paths - [ ] Verify existing billing tests pass (`npx jest ai-billing.service.spec.ts`) Made with [Cursor](https://cursor.com) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> |
||
|
|
3a1e112b86
|
Fixes and updates to the website. (#19350)
This PR implements a whole lot of fixes and updates to the website. It adds a release-notes page, terms and conditions page, privacy policy page, while fixing HomeStepper, ProductStepper, and WhyTwentyStepper. 3D models still need to be styled and their sizes need to be fixed. |
||
|
|
2ae6a9bb98
|
fix: bump handlebars to 4.7.9 (CVE-2026-33937) (#19288)
## Summary - Bumps `handlebars` from `^4.7.8` to `^4.7.9` in `packages/twenty-shared` ## Why - **CVE-2026-33937** — Prototype pollution via crafted template input - **GHSA-2w6w-674q-4c4q** — Related handlebars security advisory - Severity: **Critical** (CVSS 9.8) - Detected by Trivy and Grype scanning `twentycrm/twenty:v1.20.0` ## What changed - `packages/twenty-shared/package.json`: `"handlebars": "^4.7.8"` → `"^4.7.9"` - `yarn.lock`: updated accordingly ## Impact `handlebars` is used in `packages/twenty-shared` for template evaluation. The fix patches the prototype pollution vector without any API changes. ## Test plan - [ ] `yarn build` passes - [ ] `yarn test` passes in twenty-shared - [ ] Template evaluation works as before --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Abdullah <125115953+mabdullahabaid@users.noreply.github.com> |
||
|
|
d7e31ab2f0
|
Interactive home visual for website. (#19261)
This PR makes the Home Visual interactive. Not the perfect code, but does the trick for now to convey what we're trying to do. As per the conversation with Thomas, we will iterate over it and make it better when we get past the first release. --------- Co-authored-by: Thomas des Francs <tdesfrancs@gmail.com> |
||
|
|
2c73d47555
|
Bump @storybook/react-vite from 10.2.13 to 10.3.3 (#19232)
Bumps [@storybook/react-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/react-vite) from 10.2.13 to 10.3.3. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/storybookjs/storybook/releases"><code>@storybook/react-vite</code>'s releases</a>.</em></p> <blockquote> <h2>v10.3.3</h2> <h2>10.3.3</h2> <ul> <li>Addon-Vitest: Streamline vite(st) config detection across init and postinstall - <a href="https://redirect.github.com/storybookjs/storybook/pull/34193">#34193</a>, thanks <a href="https://github.com/valentinpalkovic"><code>@valentinpalkovic</code></a>!</li> </ul> <h2>v10.3.2</h2> <h2>10.3.2</h2> <ul> <li>CLI: Shorten CTA link messages - <a href="https://redirect.github.com/storybookjs/storybook/pull/34236">#34236</a>, thanks <a href="https://github.com/shilman"><code>@shilman</code></a>!</li> <li>React Native Web: Fix vite8 support by bumping vite-plugin-rnw - <a href="https://redirect.github.com/storybookjs/storybook/pull/34231">#34231</a>, thanks <a href="https://github.com/dannyhw"><code>@dannyhw</code></a>!</li> </ul> <h2>v10.3.1</h2> <h2>10.3.1</h2> <ul> <li>CLI: Use npm info to fetch versions in repro command - <a href="https://redirect.github.com/storybookjs/storybook/pull/34214">#34214</a>, thanks <a href="https://github.com/yannbf"><code>@yannbf</code></a>!</li> <li>Core: Prevent story-local viewport from persisting in URL - <a href="https://redirect.github.com/storybookjs/storybook/pull/34153">#34153</a>, thanks <a href="https://github.com/ghengeveld"><code>@ghengeveld</code></a>!</li> </ul> <h2>v10.3.0</h2> <h2>10.3.0</h2> <p><em>> Improved developer experience, AI-assisting tools, and broader ecosystem support</em></p> <p>Storybook 10.3 contains hundreds of fixes and improvements including:</p> <ul> <li>🤖 Storybook MCP: Agentic component dev, docs, and test (Preview release for React)</li> <li>⚡ Vite 8 support</li> <li>▲ Next.js 16.2 support</li> <li>📝 ESLint 10 support</li> <li>〰️ Addon Pseudo-States: Tailwind v4 support</li> <li>🔧 Addon-Vitest: Simplified configuration - no more setup files required</li> <li>♿ Numerous accessibility improvements across the UI</li> </ul> <!-- raw HTML omitted --> <ul> <li>A11y: Add ScrollArea prop focusable for when it has static children - <a href="https://redirect.github.com/storybookjs/storybook/pull/33876">#33876</a>, thanks <a href="https://github.com/Sidnioulz"><code>@Sidnioulz</code></a>!</li> <li>A11y: Ensure popover dialogs have an ARIA label - <a href="https://redirect.github.com/storybookjs/storybook/pull/33500">#33500</a>, thanks <a href="https://github.com/gayanMatch"><code>@gayanMatch</code></a>!</li> <li>A11y: Make resize handles for addon panel and sidebar accessible <a href="https://redirect.github.com/storybookjs/storybook/pull/33980">#33980</a></li> <li>A11y: Underline MDX links for WCAG SC 1.4.1 compliance - <a href="https://redirect.github.com/storybookjs/storybook/pull/33139">#33139</a>, thanks <a href="https://github.com/NikhilChowdhury27"><code>@NikhilChowdhury27</code></a>!</li> <li>Actions: Add expandLevel parameter to configure tree depth - <a href="https://redirect.github.com/storybookjs/storybook/pull/33977">#33977</a>, thanks <a href="https://github.com/mixelburg"><code>@mixelburg</code></a>!</li> <li>Actions: Fix HandlerFunction type to support async callback props - <a href="https://redirect.github.com/storybookjs/storybook/pull/33864">#33864</a>, thanks <a href="https://github.com/mixelburg"><code>@mixelburg</code></a>!</li> <li>Addon-Docs: Add React as optimizeDeps entry - <a href="https://redirect.github.com/storybookjs/storybook/pull/34176">#34176</a>, thanks <a href="https://github.com/valentinpalkovic"><code>@valentinpalkovic</code></a>!</li> <li>Addon-Docs: Add support for `sourceState: 'none'` to canvas block parameters - <a href="https://redirect.github.com/storybookjs/storybook/pull/33627">#33627</a>, thanks <a href="https://github.com/quisido"><code>@quisido</code></a>!</li> <li>Addon-docs: Restore `docs.components` overrides for doc blocks <a href="https://redirect.github.com/storybookjs/storybook/pull/34111">#34111</a></li> <li>Addon-Vitest: Add channel API to programmatically trigger test runs - <a href="https://redirect.github.com/storybookjs/storybook/pull/33206">#33206</a>, thanks <a href="https://github.com/JReinhold"><code>@JReinhold</code></a>!</li> <li>Addon-Vitest: Handle additional vitest config export patterns in postinstall - <a href="https://redirect.github.com/storybookjs/storybook/pull/34106">#34106</a>, thanks <a href="https://github.com/copilot-swe-agent"><code>@copilot-swe-agent</code></a>!</li> <li>Addon-Vitest: Make Playwright `--with-deps` platform-aware to avoid `sudo` prompt on Linux <a href="https://redirect.github.com/storybookjs/storybook/pull/34121">#34121</a></li> <li>Addon-Vitest: Refactor Vitest setup to eliminate the need for a dedicated setup file - <a href="https://redirect.github.com/storybookjs/storybook/pull/34025">#34025</a>, thanks <a href="https://github.com/valentinpalkovic"><code>@valentinpalkovic</code></a>!</li> <li>Addon-Vitest: Support Vitest canaries - <a href="https://redirect.github.com/storybookjs/storybook/pull/33833">#33833</a>, thanks <a href="https://github.com/valentinpalkovic"><code>@valentinpalkovic</code></a>!</li> <li>Angular: Add moduleResolution: bundler to tsconfig - <a href="https://redirect.github.com/storybookjs/storybook/pull/34085">#34085</a>, thanks <a href="https://github.com/valentinpalkovic"><code>@valentinpalkovic</code></a>!</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md"><code>@storybook/react-vite</code>'s changelog</a>.</em></p> <blockquote> <h2>10.3.3</h2> <ul> <li>Addon-Vitest: Streamline vite(st) config detection across init and postinstall - <a href="https://redirect.github.com/storybookjs/storybook/pull/34193">#34193</a>, thanks <a href="https://github.com/valentinpalkovic"><code>@valentinpalkovic</code></a>!</li> </ul> <h2>10.3.2</h2> <ul> <li>CLI: Shorten CTA link messages - <a href="https://redirect.github.com/storybookjs/storybook/pull/34236">#34236</a>, thanks <a href="https://github.com/shilman"><code>@shilman</code></a>!</li> <li>React Native Web: Fix vite8 support by bumping vite-plugin-rnw - <a href="https://redirect.github.com/storybookjs/storybook/pull/34231">#34231</a>, thanks <a href="https://github.com/dannyhw"><code>@dannyhw</code></a>!</li> </ul> <h2>10.3.1</h2> <ul> <li>CLI: Use npm info to fetch versions in repro command - <a href="https://redirect.github.com/storybookjs/storybook/pull/34214">#34214</a>, thanks <a href="https://github.com/yannbf"><code>@yannbf</code></a>!</li> <li>Core: Prevent story-local viewport from persisting in URL - <a href="https://redirect.github.com/storybookjs/storybook/pull/34153">#34153</a>, thanks <a href="https://github.com/ghengeveld"><code>@ghengeveld</code></a>!</li> </ul> <h2>10.3.0</h2> <p><em>> Improved developer experience, AI-assisting tools, and broader ecosystem support</em></p> <p>Storybook 10.3 contains hundreds of fixes and improvements including:</p> <ul> <li>🤖 Storybook MCP: Agentic component dev, docs, and test (Preview release for React)</li> <li>⚡ Vite 8 support</li> <li>▲ Next.js 16.2 support</li> <li>📝 ESLint 10 support</li> <li>〰️ Addon Pseudo-States: Tailwind v4 support</li> <li>🔧 Addon-Vitest: Simplified configuration - no more setup files required</li> <li>♿ Numerous accessibility improvements across the UI</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
6d5580c6fd
|
Bump qs from 6.14.2 to 6.15.0 (#19233)
Bumps [qs](https://github.com/ljharb/qs) from 6.14.2 to 6.15.0. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/ljharb/qs/blob/main/CHANGELOG.md">qs's changelog</a>.</em></p> <blockquote> <h2><strong>6.15.0</strong></h2> <ul> <li>[New] <code>parse</code>: add <code>strictMerge</code> option to wrap object/primitive conflicts in an array (<a href="https://redirect.github.com/ljharb/qs/issues/425">#425</a>, <a href="https://redirect.github.com/ljharb/qs/issues/122">#122</a>)</li> <li>[Fix] <code>duplicates</code> option should not apply to bracket notation keys (<a href="https://redirect.github.com/ljharb/qs/issues/514">#514</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
1af7ac5fc4
|
Bump react-hotkeys-hook from 4.5.0 to 4.6.2 (#19231)
Bumps [react-hotkeys-hook](https://github.com/JohannesKlauss/react-keymap-hook) from 4.5.0 to 4.6.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/JohannesKlauss/react-keymap-hook/releases">react-hotkeys-hook's releases</a>.</em></p> <blockquote> <h2>v4.6.2</h2> <h2>What's Changed</h2> <ul> <li>Update advanced-usage.mdx by <a href="https://github.com/VladimirTambovtsev"><code>@VladimirTambovtsev</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1232">JohannesKlauss/react-hotkeys-hook#1232</a></li> <li>feature(addEventListener): passthrough event listener options by <a href="https://github.com/wiserockryan"><code>@wiserockryan</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1234">JohannesKlauss/react-hotkeys-hook#1234</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/VladimirTambovtsev"><code>@VladimirTambovtsev</code></a> made their first contribution in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1232">JohannesKlauss/react-hotkeys-hook#1232</a></li> <li><a href="https://github.com/wiserockryan"><code>@wiserockryan</code></a> made their first contribution in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1234">JohannesKlauss/react-hotkeys-hook#1234</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/JohannesKlauss/react-hotkeys-hook/compare/v4.6.1...v4.6.2">https://github.com/JohannesKlauss/react-hotkeys-hook/compare/v4.6.1...v4.6.2</a></p> <h2>v4.6.1</h2> <h2>What's Changed</h2> <ul> <li>Consider custom element when checking if event is by <a href="https://github.com/HJK181"><code>@HJK181</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1164">JohannesKlauss/react-hotkeys-hook#1164</a></li> <li>Bump http-proxy-middleware from 2.0.6 to 2.0.7 in /documentation by <a href="https://github.com/dependabot"><code>@dependabot</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1217">JohannesKlauss/react-hotkeys-hook#1217</a></li> <li>Bump express from 4.19.2 to 4.21.0 in /documentation by <a href="https://github.com/dependabot"><code>@dependabot</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1210">JohannesKlauss/react-hotkeys-hook#1210</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/HJK181"><code>@HJK181</code></a> made their first contribution in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1164">JohannesKlauss/react-hotkeys-hook#1164</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/JohannesKlauss/react-hotkeys-hook/compare/v4.6.0...v4.6.1">https://github.com/JohannesKlauss/react-hotkeys-hook/compare/v4.6.0...v4.6.1</a></p> <h2>v4.6.0</h2> <h2>What's Changed</h2> <ul> <li>chore(deps): update all non-major dependencies by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1204">JohannesKlauss/react-hotkeys-hook#1204</a></li> <li>Feat: Helps to identify which Shortcut was triggered exactly by <a href="https://github.com/prostoandrei"><code>@prostoandrei</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1219">JohannesKlauss/react-hotkeys-hook#1219</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/prostoandrei"><code>@prostoandrei</code></a> made their first contribution in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1219">JohannesKlauss/react-hotkeys-hook#1219</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/JohannesKlauss/react-hotkeys-hook/compare/v4.5.1...v4.6.0">https://github.com/JohannesKlauss/react-hotkeys-hook/compare/v4.5.1...v4.6.0</a></p> <h2>v4.5.1</h2> <h2>What's Changed</h2> <ul> <li>chore(deps): update all non-major dependencies by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1136">JohannesKlauss/react-hotkeys-hook#1136</a></li> <li>chore(deps): update dependency <code>@types/react</code> to v18.2.56 by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1140">JohannesKlauss/react-hotkeys-hook#1140</a></li> <li>fix: example code in use-hotkeys docs by <a href="https://github.com/jvn4dev"><code>@jvn4dev</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1142">JohannesKlauss/react-hotkeys-hook#1142</a></li> <li>chore(deps): update actions/setup-node action to v4 by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1141">JohannesKlauss/react-hotkeys-hook#1141</a></li> <li>chore(deps): update actions/checkout action to v4 by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1137">JohannesKlauss/react-hotkeys-hook#1137</a></li> <li>chore(deps): update all non-major dependencies by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1147">JohannesKlauss/react-hotkeys-hook#1147</a></li> <li>chore(deps): update all non-major dependencies by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1149">JohannesKlauss/react-hotkeys-hook#1149</a></li> <li>chore(deps): update all non-major dependencies by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1156">JohannesKlauss/react-hotkeys-hook#1156</a></li> <li>chore(deps): update all non-major dependencies by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1158">JohannesKlauss/react-hotkeys-hook#1158</a></li> <li>chore(deps): update all non-major dependencies by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1162">JohannesKlauss/react-hotkeys-hook#1162</a></li> <li>chore(deps): update all non-major dependencies by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1166">JohannesKlauss/react-hotkeys-hook#1166</a></li> <li>chore(deps): update dependency <code>@types/react</code> to v18.2.79 by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1169">JohannesKlauss/react-hotkeys-hook#1169</a></li> <li>chore(deps): update all non-major dependencies by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1171">JohannesKlauss/react-hotkeys-hook#1171</a></li> <li>chore(deps): update all non-major dependencies to v7.24.5 by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1173">JohannesKlauss/react-hotkeys-hook#1173</a></li> <li>chore(deps): update dependency <code>@types/react</code> to v18.3.2 by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1175">JohannesKlauss/react-hotkeys-hook#1175</a></li> <li>chore(deps): update all non-major dependencies by <a href="https://github.com/renovate"><code>@renovate</code></a> in <a href="https://redirect.github.com/JohannesKlauss/react-hotkeys-hook/pull/1178">JohannesKlauss/react-hotkeys-hook#1178</a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
fd7387928c
|
feat: queue messages + replace AI SDK with GraphQL SSE subscription (#19203)
## Summary - **Queue messages while streaming**: Messages sent during active AI streaming are queued server-side and auto-flushed when the current stream completes. Frontend renders queued messages optimistically in a dedicated queue UI. - **Drop `@ai-sdk/react` + `resumable-stream`**: Replace the dual HTTP SSE + AI SDK client architecture with a single GraphQL SSE subscription per thread. All events (token chunks, message persistence, queue updates, errors) flow through Redis PubSub → GraphQL subscription. - **Server-driven architecture**: The server decides whether to queue or stream (via `POST /:threadId/message`). The frontend mirrors this decision for optimistic rendering but defers to the server response. - **Reuse AI SDK accumulation logic**: `readUIMessageStream` from the `ai` package handles chunk-to-message accumulation on the frontend, avoiding a custom 780-line accumulator. ## Key files **Backend:** - `agent-chat-event-publisher.service.ts` — publishes events to Redis PubSub - `agent-chat-subscription.resolver.ts` — GraphQL subscription resolver - `stream-agent-chat.job.ts` — publishes chunks via PubSub instead of resumable-stream - `agent-chat.controller.ts` — unified `POST /:threadId/message` endpoint **Frontend:** - `useAgentChatSubscription.ts` — subscribes to `onAgentChatEvent`, bridges to `readUIMessageStream` - `useAgentChat.ts` — send/stop/optimistic rendering (no more AI SDK) - `AgentChatStreamSubscriptionEffect.tsx` — replaces `AgentChatAiSdkStreamEffect.tsx` ## Test plan - [ ] Send message on new thread → optimistic render, streaming response appears - [ ] Send message while streaming → queued instantly (no flash in main thread) - [ ] Queued message auto-flushes after current stream completes - [ ] Remove queued message via queue UI - [ ] Stop streaming mid-response - [ ] Leave chat idle for several minutes → streaming still works after (SSE client recycling) - [ ] Token refresh during session → requests succeed (authenticated fetch) - [ ] Switch threads while streaming → clean subscription handoff Made with [Cursor](https://cursor.com) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
36dece43c7
|
Fix: Upgrade Nodemailer to address SMTP command injection vulnerability (#19151)
📄 Summary This PR upgrades the nodemailer dependency to a secure version (≥ 8.0.4) to fix a known SMTP command injection vulnerability (GHSA-c7w3-x93f-qmm8). 🚨 Issue The current version used in twenty-server (^7.0.11, resolved to 7.0.11 / 7.0.13) is vulnerable to SMTP command injection due to improper sanitization of the envelope.size parameter. This could allow CRLF injection, potentially enabling attackers to add unauthorized recipients to outgoing emails. 🔍 Root Cause The vulnerability originates from insufficient validation of user-controlled input in the SMTP envelope, specifically the size field, which can be exploited via crafted input containing CRLF sequences. ✅ Changes Upgraded nodemailer to version ^8.0.4 Ensured compatibility with existing email sending logic Verified that no breaking changes affect current usage 🔐 Security Impact This update mitigates the risk of: SMTP command injection Unauthorized email recipient manipulation Potential data leakage via crafted email payloads 📎 References GHSA: GHSA-c7w3-x93f-qmm8 CVE: (see linked report in issue) --------- Co-authored-by: Félix Malfait <felix.malfait@gmail.com> Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com> |
||
|
|
37908114fc
|
[SDK] Extract twenty-front-component-renderer outside of twenty-sdk ( 2.8MB ) (#19021)
Followup https://github.com/twentyhq/twenty/pull/19010 ## Dependency diagram ``` ┌─────────────────────┐ │ twenty-front │ │ (React frontend) │ └─────────┬───────────┘ │ imports runtime: │ FrontComponentRenderer │ FrontComponentRendererWithSdkClient │ useFrontComponentExecutionContext ▼ ┌──────────────────────────────────┐ ┌─────────────────────────┐ │ twenty-front-component-renderer │────────▶│ twenty-sdk │ │ (remote-dom host + worker) │ │ (app developer SDK) │ │ │ │ │ │ imports from twenty-sdk: │ │ Public API: │ │ • types only: │ │ defineFrontComponent │ │ FrontComponentExecutionContext│ │ navigate, closeSide… │ │ NavigateFunction │ │ useFrontComponent… │ │ CloseSidePanelFunction │ │ Command components │ │ CommandConfirmation… │ │ conditional avail. │ │ OpenCommandConfirmation… │ │ │ │ EnqueueSnackbarFunction │ │ Internal only: │ │ etc. │ │ frontComponentHost… │ │ │ │ front-component-build │ │ owns locally: │ │ esbuild plugins │ │ • ALLOWED_HTML_ELEMENTS │ │ │ │ • EVENT_TO_REACT │ └────────────┬────────────┘ │ • HTML_TAG_TO_CUSTOM_ELEMENT… │ │ │ • SerializedEventData │ │ types │ • PropertySchema │ ▼ │ • frontComponentHostComm… │ ┌─────────────────────────┐ │ (local ref to globalThis) │ │ twenty-shared │ │ • setFrontComponentExecution… │ │ (common types/utils) │ │ (local impl, same keys) │ │ AppPath, SidePanelP… │ │ │ │ EnqueueSnackbarParams │ └──────────────────────────────────┘ │ isDefined, … │ │ └─────────────────────────┘ │ also depends on ▼ twenty-shared (types) @remote-dom/* (runtime) @quilted/threads (runtime) react (runtime) ``` **Key points:** - **`twenty-front`** depends on the renderer, **not** on `twenty-sdk` directly (for rendering) - **`twenty-front-component-renderer`** depends on `twenty-sdk` for **types only** (function signatures, `FrontComponentExecutionContext`). The runtime bridge (`frontComponentHostCommunicationApi`) is shared via `globalThis` keys, not module imports - **`twenty-sdk`** has no dependency on the renderer — clean one-way dependency - The renderer owns all remote-dom infrastructure (element schemas, event mappings, custom element tags) that was previously leaking through the SDK's public API - The SDK's `./build` entry point was removed entirely (unused) |
||
|
|
8fa3962e1c
|
feat: add resumable stream support for agent chat (#19107)
## Overview Add resumable stream support for agent chat to allow clients to reconnect and resume streaming responses if the connection is interrupted (e.g., during page refresh). ## Changes ### Backend (Twenty Server) - Add `activeStreamId` column to `AgentChatThreadEntity` to track ongoing streams - Create `AgentChatResumableStreamService` to manage Redis-backed resumable streams using the `resumable-stream` library with ioredis - Extend `AgentChatController` with: - `GET /:threadId/stream` endpoint to resume an existing stream - `DELETE /:threadId/stream` endpoint to stop an active stream - Update `AgentChatStreamingService` to store streams in Redis and track active stream IDs - Add `resumable-stream@^2.2.12` dependency to package.json ### Frontend (Twenty Front) - Update `useAgentChat` hook to: - Use a persistent transport with `prepareReconnectToStreamRequest` for resumable streams - Export `resumeStream` function from useChat - Add `handleStop` callback to clear active stream on DELETE endpoint - Use thread ID as stable message ID instead of including message count - Add stream resumption logic in `AgentChatAiSdkStreamEffect` component to automatically call `resumeStream()` when switching threads ## Database Migration New migration `1774003611071-add-active-stream-id-to-agent-chat-thread` adds the `activeStreamId` column to store the current resumable stream identifier. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
22c9693ce5
|
First PR to bring in the new twenty website. (#19035)
This PR contains Menu, Hero, TrustedBy, Problem, ThreeCards and Footer sections of the new website. Most components in there match the Figma designs, except for two things. - Zoom levels on 3D illustrations from Endless Tools. - Menu needs to have the same color as Hero - it's not happening at the moment since Menu is in the layout, not nested inside pages or Hero. Images are placeholders (same as Figma). |
||
|
|
dfe9cb4346
|
chore(deps): bump @microsoft/microsoft-graph-types from 2.40.0 to 2.43.1 (#18985)
Bumps [@microsoft/microsoft-graph-types](https://github.com/microsoftgraph/msgraph-typescript-typings) from 2.40.0 to 2.43.1. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/microsoftgraph/msgraph-typescript-typings/releases"><code>@microsoft/microsoft-graph-types</code>'s releases</a>.</em></p> <blockquote> <h2>v2.43.1</h2> <h2><a href="https://github.com/microsoftgraph/msgraph-typescript-typings/compare/v2.43.0...v2.43.1">2.43.1</a> (2025-09-30)</h2> <h3>Bug Fixes</h3> <ul> <li>moves pipeline to governed template. (<a href=" |
||
|
|
91374262f2
|
chore(deps): bump @ai-sdk/xai from 3.0.59 to 3.0.74 (#18986)
Bumps [@ai-sdk/xai](https://github.com/vercel/ai) from 3.0.59 to 3.0.74. <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
7335d352a9
|
chore(deps): bump @linaria/core from 6.2.0 to 6.3.0 (#18984)
Bumps [@linaria/core](https://github.com/callstack/linaria) from 6.2.0 to 6.3.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/callstack/linaria/releases"><code>@linaria/core</code>'s releases</a>.</em></p> <blockquote> <h2><code>@linaria/core</code><a href="https://github.com/6"><code>@6</code></a>.3.0</h2> <h3>Minor Changes</h3> <ul> <li>281ca4f5: The new version of wyw-in-js, with the support of a configurable code remover, can help prevent compilation errors and improve build time.</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
790a58945b
|
Migrate twenty-companion from npm to yarn workspaces (#18946)
## Summary - Migrates twenty-companion from standalone npm to the repo yarn workspaces - Removes package-lock.json (resolves Oneleet security finding about npm lifecycle scripts) - Converts npm overrides to yarn resolutions - Updates scripts from npm run to yarn ## Test plan - [x] Verified yarn install succeeds at root - [x] Verified yarn start in twenty-companion launches the Electron app - [ ] Verify Oneleet finding is resolved after merge |
||
|
|
4ea2e32366
|
Refactor twenty client sdk provisioning for logic function and front-component (#18544)
## 1. The `twenty-client-sdk` Package (Source of Truth)
The monorepo package at `packages/twenty-client-sdk` ships with:
- A **pre-built metadata client** (static, generated from a fixed
schema)
- A **stub core client** that throws at runtime (`CoreApiClient was not
generated...`)
- Both ESM (`.mjs`) and CJS (`.cjs`) bundles in `dist/`
- A `package.json` with proper `exports` map for
`twenty-client-sdk/core`, `twenty-client-sdk/metadata`, and
`twenty-client-sdk/generate`
## 2. Generation & Upload (Server-Side, at Migration Time)
**When**: `WorkspaceMigrationRunnerService.run()` executes after a
metadata schema change.
**What happens in `SdkClientGenerationService.generateAndStore()`**:
1. Copies the stub `twenty-client-sdk` package from the server's assets
(resolved via `SDK_CLIENT_PACKAGE_DIRNAME` — from
`dist/assets/twenty-client-sdk/` in production, or from `node_modules`
in dev)
2. Filters out `node_modules/` and `src/` during copy — only
`package.json` + `dist/` are kept (like an npm publish)
3. Calls `replaceCoreClient()` which uses `@genql/cli` to introspect the
**application-scoped** GraphQL schema and generates a real
`CoreApiClient`, then compiles it to ESM+CJS and overwrites
`dist/core.mjs` and `dist/core.cjs`
4. Archives the **entire package** (with `package.json` + `dist/`) into
`twenty-client-sdk.zip`
5. Uploads the single archive to S3 under
`FileFolder.GeneratedSdkClient`
6. Sets `isSdkLayerStale = true` on the `ApplicationEntity` in the
database
## 3. Invalidation Signal
The `isSdkLayerStale` boolean column on `ApplicationEntity` is the
invalidation mechanism:
- **Set to `true`** by `generateAndStore()` after uploading a new client
archive
- **Checked** by both logic function drivers before execution — if
`true`, they rebuild their local layer
- **Set back to `false`** by `markSdkLayerFresh()` after the driver has
successfully consumed the new archive
Default is `false` so existing applications without a generated client
aren't affected.
## 4a. Logic Functions — Local Driver
**`ensureSdkLayer()`** is called before every execution:
1. Checks if the local SDK layer directory exists AND `isSdkLayerStale`
is `false` → early return
2. Otherwise, cleans the local layer directory
3. Calls `downloadAndExtractToPackage()` which streams the zip from S3
directly to disk and extracts the full package into
`<tmpdir>/sdk/<workspaceId>-<appId>/node_modules/twenty-client-sdk/`
4. Calls `markSdkLayerFresh()` to set `isSdkLayerStale = false`
**At execution time**, `assembleNodeModules()` symlinks everything from
the deps layer's `node_modules/` **except** `twenty-client-sdk`, which
is symlinked from the SDK layer instead. This ensures the logic
function's `import ... from 'twenty-client-sdk/core'` resolves to the
generated client.
## 4b. Logic Functions — Lambda Driver
**`ensureSdkLayer()`** is called during `build()`:
1. Checks if `isSdkLayerStale` is `false` and an existing Lambda layer
ARN exists → early return
2. Otherwise, deletes all existing layer versions for this SDK layer
name
3. Calls `downloadArchiveBuffer()` to get the raw zip from S3 (no disk
extraction)
4. Calls `reprefixZipEntries()` which streams the zip entries into a
**new zip** with the path prefix
`nodejs/node_modules/twenty-client-sdk/` — this is the Lambda layer
convention path. All done in memory, no disk round-trip
5. Publishes the re-prefixed zip as a new Lambda layer via
`publishLayer()`
6. Calls `markSdkLayerFresh()`
**At function creation**, the Lambda is created with **two layers**:
`[depsLayerArn, sdkLayerArn]`. The SDK layer is listed last so it
overwrites the stub `twenty-client-sdk` from the deps layer (later
layers take precedence in Lambda's `/opt` merge).
## 5. Front Components
Front components are built by `app:build` with `twenty-client-sdk/core`
and `twenty-client-sdk/metadata` as **esbuild externals**. The stored
`.mjs` in S3 has unresolved bare import specifiers like `import {
CoreApiClient } from 'twenty-client-sdk/core'`.
SDK import resolution is split between the **frontend host** (fetching &
caching SDK modules) and the **Web Worker** (rewriting imports):
**Server endpoints**:
- `GET /rest/front-components/:id` —
`FrontComponentService.getBuiltComponentStream()` returns the **raw
`.mjs`** directly from file storage. No bundling, no SDK injection.
- `GET /rest/sdk-client/:applicationId/:moduleName` —
`SdkClientController` reads a single file (e.g. `dist/core.mjs`) from
the generated SDK archive via
`SdkClientGenerationService.readFileFromArchive()` and serves it as
JavaScript.
**Frontend host** (`FrontComponentRenderer` in `twenty-front`):
1. Queries `FindOneFrontComponent` which returns `applicationId`,
`builtComponentChecksum`, `usesSdkClient`, and `applicationTokenPair`
2. If `usesSdkClient` is `true`, renders
`FrontComponentRendererWithSdkClient` which calls the
`useApplicationSdkClient` hook
3. `useApplicationSdkClient({ applicationId, accessToken })` checks the
Jotai atom family cache for existing blob URLs. On cache miss, fetches
both SDK modules from `GET /rest/sdk-client/:applicationId/core` and
`/metadata`, creates **blob URLs** for each, and stores them in the atom
family
4. Once the blob URLs are cached, passes them as `sdkClientUrls`
(already blob URLs, not server URLs) to `SharedFrontComponentRenderer` →
`FrontComponentWorkerEffect` → worker's `render()` call via
`HostToWorkerRenderContext`
**Worker** (`remote-worker.ts` in `twenty-sdk`):
1. Fetches the raw component `.mjs` source as text
2. If `sdkClientUrls` are provided and the source contains SDK import
specifiers (`twenty-client-sdk/core`, `twenty-client-sdk/metadata`),
**rewrites** the bare specifiers to the blob URLs received from the host
(e.g. `'twenty-client-sdk/core'` → `'blob:...'`)
3. Creates a blob URL for the rewritten source and `import()`s it
4. Revokes only the component blob URL after the module is loaded — the
SDK blob URLs are owned and managed by the host's Jotai cache
This approach eliminates server-side esbuild bundling on every request,
caches SDK modules per application in the frontend, and keeps the
worker's job to a simple string rewrite.
## Summary Diagram
```
app:build (SDK)
└─ twenty-client-sdk stub (metadata=real, core=stub)
│
▼
WorkspaceMigrationRunnerService.run()
└─ SdkClientGenerationService.generateAndStore()
├─ Copy stub package (package.json + dist/)
├─ replaceCoreClient() → regenerate core.mjs/core.cjs
├─ Zip entire package → upload to S3
└─ Set isSdkLayerStale = true
│
┌────────┴────────────────────┐
▼ ▼
Logic Functions Front Components
│ │
├─ Local Driver ├─ GET /rest/sdk-client/:appId/core
│ └─ downloadAndExtract │ → core.mjs from archive
│ → symlink into │
│ node_modules ├─ Host (useApplicationSdkClient)
│ │ ├─ Fetch SDK modules
└─ Lambda Driver │ ├─ Create blob URLs
└─ downloadArchiveBuffer │ └─ Cache in Jotai atom family
→ reprefixZipEntries │
→ publish as Lambda ├─ GET /rest/front-components/:id
layer │ → raw .mjs (no bundling)
│
└─ Worker (browser)
├─ Fetch component .mjs
├─ Rewrite imports → blob URLs
└─ import() rewritten source
```
## Next PR
- Estimate perf improvement by implementing a redis caching for front
component client storage ( we don't even cache front comp initially )
- Implem frontent blob invalidation sse event from server
---------
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
|
||
|
|
0626f3e469
|
Fix deploy: remove stale @ai-sdk/groq from yarn.lock (#18863)
## Summary - The front deploy to S3 is failing because `@ai-sdk/groq` was removed from `packages/twenty-server/package.json` but the `yarn.lock` was never updated |
||
|
|
0d27a255a9
|
chore(deps): bump nodemailer from 7.0.11 to 7.0.13 (#18754)
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 7.0.11 to 7.0.13. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/nodemailer/nodemailer/releases">nodemailer's releases</a>.</em></p> <blockquote> <h2>v7.0.13</h2> <h2><a href="https://github.com/nodemailer/nodemailer/compare/v7.0.12...v7.0.13">7.0.13</a> (2026-01-27)</h2> <h3>Bug Fixes</h3> <ul> <li>downgrade transient connection error logs to warn level (<a href=" |
||
|
|
ef2a113a16
|
chore(deps): bump @dagrejs/dagre from 1.1.3 to 1.1.8 (#18753)
Bumps [@dagrejs/dagre](https://github.com/dagrejs/dagre) from 1.1.3 to 1.1.8. <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
e0e25eac2b
|
chore(deps): bump @ai-sdk/mistral from 3.0.20 to 3.0.25 (#18755)
Bumps [@ai-sdk/mistral](https://github.com/vercel/ai) from 3.0.20 to 3.0.25. <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
058414fae5
|
Upgrade Ink to v6 and pause TUI on idle/error (#18705)
## Summary
- Upgrade `ink` from 5.1.1 to 6.8.0 in twenty-sdk (React 19 required, no
API breaking changes)
- Upgrade `react`/`react-dom` from 18 to 19 and
`@types/react`/`@types/react-dom` to 19 in twenty-sdk
- Enable `incrementalRendering` — only redraws changed lines instead of
full output, reducing flickering
- Pause the animation timer when the pipeline is not actively building
or syncing, so Ink stops re-rendering and the terminal becomes
scrollable (fixes inability to scroll up to read errors)
- Remove `AnimationProvider` context — derive animation frames from
`Date.now()` directly in `useStatusIcon`
- Export `NavigationMenuItemType` from `twenty-sdk` (re-exported from
`twenty-shared/types`)
- Add dedicated NavigationMenuItem integration tests to postcard-app
(unique positions, unique identifiers, valid object references)
## Test plan
- [ ] Run `twenty dev` and verify the TUI renders normally during
build/sync
- [ ] Trigger an error and verify the terminal output freezes and
becomes scrollable
- [ ] Verify that after fixing the error, the TUI resumes animating on
next build cycle
- [ ] Verify `import { NavigationMenuItemType } from "twenty-sdk"` works
- [ ] Run postcard-app integration tests and verify new
NavigationMenuItem tests pass
|
||
|
|
6e36ad9fa2
|
fix: mailparser vulnerable to cross-site scripting (#18664)
Resolves [Dependabot Alert 595](https://github.com/twentyhq/twenty/security/dependabot/595) and [Dependabot Alert 596](https://github.com/twentyhq/twenty/security/dependabot/596). |
||
|
|
2c2f66b584
|
fix: DOMPurify contains a cross-site scripting vulnerability (#18665)
Resolves [Dependabot Alert 597](https://github.com/twentyhq/twenty/security/dependabot/597), [Dependabot Alert 598](https://github.com/twentyhq/twenty/security/dependabot/598), [Dependabot Alert 599](https://github.com/twentyhq/twenty/security/dependabot/599) and [Dependabot Alert 600](https://github.com/twentyhq/twenty/security/dependabot/600). |
||
|
|
87c519b72f
|
fix: multer vulnerable to denial of service via uncontrolled recursion (#18659)
Resolves [Dependabot Alert 608](https://github.com/twentyhq/twenty/security/dependabot/608). |
||
|
|
1b20bdaf6d
|
fix: @isaacs/brace-expansion has uncontrolled resource consumption (#18660)
Resolves [Dependabot Alert 414](https://github.com/twentyhq/twenty/security/dependabot/414). |
||
|
|
67866ff59c
|
fix: expr-eval related dependabot alerts (#18661)
Resolves [Dependabot Alert 593](https://github.com/twentyhq/twenty/security/dependabot/593) and [Dependabot Alert 594](https://github.com/twentyhq/twenty/security/dependabot/594). expr-eval was last published six years ago and had changes five years ago. NPM contains a fork that published the changes from five years ago under the same name with `-fork` suffix. This PR uses that fork as suggested by Dependabot. |
||
|
|
e6f1bdd1c8
|
fix: yauzl contains an off-by-one error (#18662)
Resolves [Dependabot Alert 633](https://github.com/twentyhq/twenty/security/dependabot/633). |
||
|
|
b470cb21a1
|
Upgrade Apollo Client to v4 and refactor error handling (#18584)
## Summary This PR upgrades Apollo Client from v3.10.0 to v4 and refactors error handling patterns across the codebase to use a new centralized `useSnackBarOnQueryError` hook. ## Key Changes - **Dependency Update**: Upgraded `@apollo/client` from `^3.10.0` to `^3.11.0` in root package.json - **New Hook**: Added `useSnackBarOnQueryError` hook for centralized Apollo query error handling with snack bar notifications - **Error Handling Refactor**: Updated 100+ files to use the new error handling pattern: - Removed direct `ApolloError` imports where no longer needed - Replaced manual error handling logic with `useSnackBarOnQueryError` hook - Simplified error handling in hooks and components across multiple modules - **GraphQL Codegen**: Updated codegen configuration files to work with Apollo Client v3.11.0 - **Type Definitions**: Added TypeScript declaration file for `apollo-upload-client` module - **Test Updates**: Updated test files to reflect new error handling patterns ## Notable Implementation Details - The new `useSnackBarOnQueryError` hook provides a consistent way to handle Apollo query errors with automatic snack bar notifications - Changes span across multiple feature areas: auth, object records, settings, workflows, billing, and more - All changes maintain backward compatibility while improving code maintainability and reducing duplication - Jest configuration updated to work with the new Apollo Client version https://claude.ai/code/session_019WGZ6Rd7sEHuBg9sTrXRqJ --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
741e9a8f81
|
Update yarn lock (#18589)
https://github.com/twentyhq/twenty/pull/18075 |
||
|
|
c9deab4373
|
[COMMAND MENU ITEMS] Remove standard front components (#18581)
All standard command menu items will link to an engine component instead of standard front components. |
||
|
|
b21fb4aa6f
|
Fix PDF Upload edge case (#18533)
we were using an older version of `file-type` which has limited support for PDF as it's a complex spec Updated to latest version which includes support for plugins and added `@file-type/pdf` which has extensive spec compliant detection approach fixes TWENTY-SERVER-FAN |
||
|
|
15d0970f72
|
Bump @swc/core from 1.15.11 to 1.15.18 (#18570)
Bumps [@swc/core](https://github.com/swc-project/swc/tree/HEAD/packages/core) from 1.15.11 to 1.15.18. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/swc-project/swc/blob/main/CHANGELOG.md"><code>@swc/core</code>'s changelog</a>.</em></p> <blockquote> <h2>[1.15.18] - 2026-03-01</h2> <h3>Bug Fixes</h3> <ul> <li><strong>(html/wasm)</strong> Publish <code>@swc/html-wasm</code> for nodejs (<a href="https://redirect.github.com/swc-project/swc/issues/11601">#11601</a>) (<a href=" |