Commit Graph
10601 Commits
Author SHA1 Message Date
Félix Malfait aced6349dc Merge remote-tracking branch 'origin/main' into feat/app-distribution-npm-tarball
Made-with: Cursor

# Conflicts:
#	packages/twenty-apps/hello-world/package.json
#	packages/twenty-apps/hello-world/yarn.lock
2026-03-04 15:34:05 +01:00
Félix Malfait 34b83daeb7 Fix 2026-03-04 15:26:38 +01:00
Paul RastoinGitHubThomas TrompettebosiraphaelWeikogithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>github-actionsCharles Bochet
845a1934d3 Tt call recording app (#18281)
Co-authored-by: Thomas Trompette <thomas.trompette@sfr.fr>
Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
Co-authored-by: Weiko <corentin@twenty.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2026-03-04 14:11:57 +00:00
Félix Malfait be7bc82a2e Refacto 2026-03-04 14:43:24 +01:00
c97d872b9f [BREAKING_CHANGE_VIEW_SORT] Refactor view sort to v2 (#17609)
Fixes https://github.com/twentyhq/core-team-issues/issues/2187

---------

Co-authored-by: prastoin <paul@twenty.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
2026-03-04 12:48:58 +00:00
Félix Malfait 9e34c42dc2 fix: stop hardcoding sourceType to LOCAL in application create
application.service.create() was overriding sourceType to LOCAL
regardless of what the caller passed. For npm/tarball installs, the
correct sourceType was set via updateApplicationSourceType, but it
ran BEFORE synchronizeFromManifest (which creates the Application
record), so the update hit zero rows on first install.

Fix: remove the hardcoded override (column default handles the
fallback) and move updateApplicationSourceType after the sync so it
correctly updates the newly-created record.

Made-with: Cursor
2026-03-04 13:48:44 +01:00
Félix Malfait 97f3bc3da5 fix: update integration tests and exception filter for refactored types
- Update app-distribution tests: 'none' sourceType → 'local'
- Handle ApplicationRegistrationException in REST API exception filter
  so tarball upload errors return proper HTTP status codes
- Catch manifest.json read failure in tarball upload and throw
  INVALID_INPUT (400) instead of PACKAGE_RESOLUTION_FAILED (500)
- Update marketplace-catalog-sync test to include marketplaceDisplayData
  in raw SQL inserts (matching what the real sync cron produces)

Made-with: Cursor
2026-03-04 13:29:28 +01:00
EtienneandGitHub 906a0aed38 Common API - Filter validation layer (#18187)
Closes https://github.com/twentyhq/core-team-issues/issues/1627

**FilterArgProcessor consolidation:**
Refactored to both validate AND transform filter values in a single pass
Coerced string inputs to native types (e.g., "1" → 1, "true" → true -
useful for Rest input)
Returns transformed filter instead of just validating
Removed overrideFilterByFieldMetadata calls from all computeArgs methods
**QueryRunnerArgsFactory cleanup**
**Testing:**
Add unit testing
uncomment integration tests
2026-03-04 12:10:44 +00:00
Félix Malfait 682bcd0186 fix: extract AppRegistrationSourceType to its own file
Break circular import chain: application-registration.entity →
user.entity → app-token.entity → workspace.entity →
application.entity → (back to) application-registration.entity.

The enum is now in its own file with no entity imports, so both entity
files can reference it without triggering a circular dependency at
module load time.

Made-with: Cursor
2026-03-04 13:05:33 +01:00
nitinandGitHub 80d054563e followup: centralize widget common properties and add widget bulk update integration tests (#18225)
followup
https://github.com/twentyhq/twenty/pull/18015#pullrequestreview-3818929035
2026-03-04 11:47:56 +00:00
Baptiste DevessierandGitHub 5b544809f7 Support ungrouped fields + improve edition UX (#18224)
## Demo


https://github.com/user-attachments/assets/59e530ea-1c5b-44be-a012-42551e68221c

## Demo – creating a new group


https://github.com/user-attachments/assets/e8511bc3-d586-422c-aca8-b02794a0c84f

## Demo – ungrouped fields


https://github.com/user-attachments/assets/6ded4a90-fb08-485e-ad08-086f3a970752

Closes https://github.com/twentyhq/core-team-issues/issues/2232
Closes https://github.com/twentyhq/core-team-issues/issues/2237
Closes https://github.com/twentyhq/core-team-issues/issues/2238
2026-03-04 11:45:14 +00:00
Charles BochetandGitHub 3b2bf39565 Refactor modal (#18377)
## Summary

- Move Modal UI components (`Modal`, `ModalContent`, `ModalHeader`,
`ModalFooter`, `ModalBackdrop`) from `twenty-front` to `twenty-ui` as
stateless, reusable components
- Create `ModalStatefulWrapper` in `twenty-front` that connects Jotai
state (`isModalOpenedComponentState`) to the stateless `Modal` via an
`isOpen` prop
- Rename `modalVariant` prop to `overlay` with clearer values: `'dark'`
(default), `'light'` (in-container), `'transparent'` (invisible panel).
Remove unused `'medium'` overlay
- Rename `modalId` to `modalInstanceId` across the entire modal zone
(~30 consumer files)
- Extract `ModalProps` to its own file in
`twenty-ui/types/ModalProps.ts`; extract `ModalStatefulWrapperProps` to
its own file using `Pick<ModalProps, ...>` for shared props
- Extract `ModalBackdrop` to its own file and export from `twenty-ui`;
use it in `UserOrMetadataLoader` instead of a local styled component
- Use `ModalFooter` in `StepNavigationButton` and `ModalHeader` in
`SpreadsheetImportStepperContainer` instead of duplicated `styled.div`
definitions
- Remove unused `onClose` prop from stateless `Modal`; fix `typeof
document` guard in `ModalStatefulWrapper`
- Split shared types into individual files: `ModalSize.ts`,
`ModalPadding.ts`, `ModalOverlay.ts`
- Extract wyw profiling instrumentation from `vite.config.ts` into
reusable `createWywProfilingPlugin` with parametrized threshold and
improved logging
- Delete old `Modal.tsx`, `Modal.styles.ts`, `ModalContent.tsx`,
`ModalHeader.tsx`, `ModalFooter.tsx` from `twenty-front`
- Add comprehensive Storybook stories in `twenty-ui` covering Default,
Confirmation, Small, ExtraLarge, Closed, and Interactive variants
2026-03-04 13:22:31 +01:00
Paul RastoinandGitHub 995793c0ac [CREATE_APP] Integration testing scaffold (#18345)
# Introduction
Adding integration test scaffold to the create twenty app and an example
to the hello world app
This PR also fixes all the sdk e2e tests in local

## `HELLO_WORLD`
Removed the legacy implem in the `twenty-apps` folder, replacing it by
an exhaustive app generation

## Next step
Will in another PR add workflows for CI testing

## Open question
- Should we still add vitest config and dep even if the user did not ask
for the integration test example ? -> currently we don't
- That's the perfect timing to identify if we're ok to handle seed
workspace authentication with the known api key
2026-03-04 13:12:13 +01:00
Félix Malfait f5243000e0 chore: regenerate GraphQL types after marketplace module extraction
Run graphql:generate and graphql:generate --configuration=metadata to
pick up the new installNpmApp mutation and updated schema.

Made-with: Cursor
2026-03-04 12:39:59 +01:00
Félix Malfait cd80fbf29d fix: register MarketplaceModule in CoreEngineModule
MarketplaceModule was only imported in DatabaseCommandModule (CLI) but
not in the main app module tree, so the resolver and cron were not
loaded at runtime.

Made-with: Cursor
2026-03-04 12:30:02 +01:00
Félix Malfait 2cc1e6243f fix: add PermissionsModule to MarketplaceModule, fix prettier
- MarketplaceResolver uses SettingsPermissionGuard which injects
  PermissionsService — need PermissionsModule in imports
- Fix prettier formatting in uploadAppTarball GraphQL mutation

Made-with: Cursor
2026-03-04 12:17:24 +01:00
Félix Malfait fba4fc789b refactor: extract marketplace module, fix types, clean up architecture
- Extract marketplace into dedicated NestJS module (marketplace/) from
  the overloaded application/ module (services, resolver, DTOs, crons,
  constants, types, utils)
- Fix MarketplaceDisplayData type mismatches with DTO (field types,
  required arrays, optional permission booleans)
- Fix cross-module exception: app-tarball-upload now throws
  ApplicationRegistrationException instead of ApplicationException
- Move MarketplaceResolver from ApplicationSyncModule to MarketplaceModule
- Remove redundant useApolloClient from useUploadAppTarball
- Move frontend marketplace hooks/mutations to modules/marketplace/
- Unify version comparison to use isNewerSemver consistently
- Validate npm registry response shape instead of unsafe cast
- Clarify workspaceId ownership semantics on ApplicationRegistration

Made-with: Cursor
2026-03-04 12:07:59 +01:00
Félix Malfait cb6d04862c Improve 2026-03-04 10:52:09 +01:00
Abdullah.andGitHub 225f185278 fix: fast-xml-parser has stack overflow in XMLBuilder with preserve order (#18375)
Resolves [Dependabot Alert
551](https://github.com/twentyhq/twenty/security/dependabot/551).
2026-03-04 10:36:58 +01:00
Abdullah.andGitHub ca1d49c6cd fix: rollup 4 has arbitrary file write via path traversal (#18373)
Resolves [Dependabot Alert
508](https://github.com/twentyhq/twenty/security/dependabot/508).
2026-03-04 10:35:10 +01:00
Abdullah.andGitHub 2f9c94d9a0 fix: upgrade nestjs dependencies to upgrade multer transitive import (#18374)
Resolves [Dependabot Alert
549](https://github.com/twentyhq/twenty/security/dependabot/549) and
[Dependabot Alert
550](https://github.com/twentyhq/twenty/security/dependabot/550).
2026-03-04 10:34:44 +01:00
Félix Malfait ea4e50679a refactor: remove premature registryUrl from ApplicationRegistration entity
The per-registration registry URL override was never set by any code
path — all npm operations already fall back to the server-level
APP_REGISTRY_URL config. Remove the column, entity field, and migration
to avoid unnecessary schema complexity. Can be re-added later if
per-app private registries become a real use case.

Made-with: Cursor
2026-03-04 09:44:42 +01:00
Félix Malfait 83e1efc496 fix: typecheck and prettier errors in upload controller and upgrade service
Made-with: Cursor
2026-03-04 09:38:15 +01:00
Félix Malfait a1c246eb92 fix: address follow-up review items
1. Advisory lock: use pg_advisory_xact_lock(key1, key2) with two
   separate INT4 hashes for 64-bit key space instead of single 32-bit
2. Update badge: use proper semver comparison (isNewerSemver) instead
   of simple inequality check, preventing false positives on downgrades
3. Catalog sync: replace boolean hasSyncedOnce with timestamp-based
   cooldown (5min), enabling retries after transient failures
4. Yarn engine: dynamically resolve yarn path from .yarnrc.yml instead
   of hardcoding the version in the filename
5. Temp directory: clean up APP_RESOLVER_TMPDIR on module init to
   remove stale files from previous server runs

Made-with: Cursor
2026-03-04 09:36:40 +01:00
Félix Malfait 86d98a5830 fix: address PR review comments (security, correctness, UX)
1. SDK push: fix endpoint URL (/api/app-registrations/) and send
   base64 JSON body instead of multipart/form-data
2. Security: skip symlinks in collectFiles to prevent path traversal
3. Security: use resolve()+startsWith() instead of includes('..')
   for tarball path traversal protection
4. Multi-tenant: scope upsertRegistration by workspaceId
5. Data consistency: set sourceType=TARBALL on creation instead of
   saving as NONE then updating
6. Correctness: move hasSyncedOnce after successful sync
7. Correctness: URL-encode scoped npm package names in registry URLs
8. Error handling: wrap JSON.parse in try-catch for manifest parsing
9. Security: remove filesystem paths from error messages
10. Robustness: add default branch to REST exception filter
11. UX: gate modal close on install success
12. Robustness: add default case to mapSourceType
13. UX: improve userFriendlyMessage for package resolution failure

Made-with: Cursor
2026-03-04 09:21:54 +01:00
a9c4920fcc i18n - docs translations (#18370)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-03-04 09:16:33 +01:00
07dd27f6c4 i18n - translations (#18368)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-03-04 01:29:35 +01:00
Charles BochetandGitHub 7a2e397ad1 Complete linaria migration (#18361)
## Summary

Completes the migration of the frontend styling system from **Emotion**
(`@emotion/styled`, `@emotion/react`) to **Linaria** (`@linaria/react`,
`@linaria/core`), a zero-runtime CSS-in-JS library where styles are
extracted at build time.

This is the final step of the migration — all ~494 files across
`twenty-front`, `twenty-ui`, `twenty-website`, and `twenty-sdk` are now
fully converted.

## Changes

### Styling Migration (across ~480 component files)
- Replaced all `@emotion/styled` imports with `@linaria/react`
- Converted runtime theme access patterns (`({ theme }) => theme.x.y`)
to build-time `themeCssVariables` CSS custom properties
- Replaced `useTheme()` hook (from Emotion) with
`useContext(ThemeContext)` where runtime theme values are still needed
(e.g., passing colors to non-CSS props like icon components)
- Removed `@emotion/react` `css` helper usages in favor of Linaria
template literals

### Dependency & Configuration Changes
- **Removed**: `@emotion/react`, `@emotion/styled` from root
`package.json`
- **Added**: `@wyw-in-js/babel-preset`, `next-with-linaria` (for
twenty-website SSR support)
- Updated Nx generator defaults from `@emotion/styled` to
`@linaria/react` in `nx.json`
- Simplified `vite.config.ts` (removed Emotion-specific configuration)
- Updated `twenty-website/next.config.js` to use `next-with-linaria` for
SSR Linaria support

### Storybook & Testing
- Removed `ThemeProvider` from Emotion in Storybook previews
(`twenty-front`, `twenty-sdk`)
- Now relies solely on `ThemeContextProvider` for theme injection

### Documentation
- Removed the temporary `docs/emotion-to-linaria-migration-plan.md`
(migration complete)
- Updated `CLAUDE.md` and `README.md` to reflect Linaria as the styling
stack
- Updated frontend style guide docs across all locales

## How it works

Linaria extracts styles at build time via the `@wyw-in-js/vite` plugin.
All expressions in `styled` template literals must be **statically
evaluable** — no runtime theme objects or closures over component state.

- **Static styles** use `themeCssVariables` which map to CSS custom
properties (`var(--theme-color-x)`)
- **Runtime theme access** (for non-CSS use cases like icon `color`
props) uses `useContext(ThemeContext)` instead of Emotion's `useTheme()`
2026-03-04 00:50:06 +01:00
Félix Malfait af9e551c74 fix: update snapshot for feature-flag-disabled test
Error code changed from BAD_USER_INPUT to FORBIDDEN.

Made-with: Cursor
2026-03-03 22:45:10 +01:00
Félix Malfait 0e3c1a3ce0 fix: throw error when UUID-based registration not found in installMarketplaceApp
When universalIdentifier is a UUID and no matching registration exists,
throw instead of falling through to create a new npm registration.

Made-with: Cursor
2026-03-03 21:36:26 +01:00
Félix Malfait 8981534805 fix: handle nullable description in application table and detail tab
Made-with: Cursor
2026-03-03 21:16:03 +01:00
Félix MalfaitandGitHub df0700bd9d Merge branch 'main' into feat/app-distribution-npm-tarball 2026-03-03 21:05:21 +01:00
Félix Malfait 07bec1310b graphql gen 2026-03-03 21:04:48 +01:00
Paul RastoinandGitHub 8a3b96d911 Remove files (#18360) 2026-03-03 19:01:27 +01:00
Félix Malfait 61d98598d7 fix: use REL_ prefix for OneToOne unique constraint name
Made-with: Cursor
2026-03-03 18:36:07 +01:00
Félix Malfait 34ae2bc41e Fix 2026-03-03 18:03:08 +01:00
Paul RastoinandGitHub 132a19f688 [SDK] Execute logic function e2e test (#18351)
# Introduction
Creating an e2e test covering the execute logic function public
operation
2026-03-03 17:44:19 +01:00
Félix Malfait e584a2d593 fix: extract response.status to variable for lingui i18n rule
Made-with: Cursor
2026-03-03 17:37:02 +01:00
Félix Malfait 800cfe409f fix: wrap upload error string with i18n t`` macro
Made-with: Cursor
2026-03-03 17:25:21 +01:00
Félix Malfait ff6d0c13d0 fix: add missing SDK command files and fix prettier formatting
- Create app-pack.ts and app-push.ts CLI commands (lost during merge)
- Remove duplicate app:build command registration in app-command.ts
- Fix Prettier formatting in server integration test files
- Fix Prettier formatting in app-registration-upload controller

Made-with: Cursor
2026-03-03 17:11:53 +01:00
Félix MalfaitandGitHub 97e45d0aed Merge branch 'main' into feat/app-distribution-npm-tarball 2026-03-03 16:52:49 +01:00
Félix Malfait d2ebe3edb2 feat: add npm and tarball app distribution with upgrade mechanism
Implement a comprehensive app distribution system supporting both public
(npm registry) and private (tarball upload) installation channels.

Backend:
- Add AppRegistrationSourceType enum (npm, tarball, none) to track app origin
- Add AppPackageResolverService for resolving packages from npm or tarball sources
- Add ApplicationInstallService with PostgreSQL advisory locks for safe installs
- Add AppUpgradeService with version checking and rollback support
- Add tarball upload REST endpoint with secure extraction (path traversal protection)
- Add marketplace catalog sync cron job (hourly) from hardcoded catalog index
- Add app version check cron job (every 6 hours) to detect available updates
- Disable yarn lifecycle scripts (enableScripts: false) to prevent RCE via postinstall
- Add database migration for sourceType, sourcePackage, latestAvailableVersion fields

Frontend:
- Add "Install from npm" modal for manual package installation
- Add "Upload tarball" modal for direct .tar.gz uploads
- Add upgrade mutation and version container with upgrade button
- Add blue "Update" badge on installed apps table when newer version available
- Fetch application registrations to compare installed vs latest versions
- Migrate styled components from Emotion to Linaria (matching main migration)
- Remove redundant sourcePackage mutation argument (derived from universalIdentifier)

Testing:
- Add integration tests for app distribution (install, upgrade, tarball upload)
- Add integration tests for marketplace catalog sync

Made-with: Cursor
2026-03-03 16:45:29 +01:00
Charles BochetandGitHub 3bfdc2c83f chore(twenty-front): migrate command-menu, workflow, page-layout and UI modules from Emotion to Linaria (PR 4-6/10) (#18342)
## Summary

Continues the Emotion → Linaria migration (PR 4-6 from the [migration
plan](docs/emotion-to-linaria-migration-plan.md)). Migrates **311
files** across four module groups:

| Module | Files |
|---|---|
| command-menu | 53 |
| workflow | 84 |
| page-layout | 84 |
| UI (partial - first ~80 files) | ~80 |
| twenty-ui (TEXT_INPUT_STYLE) | 1 |
| misc (hooks, keyboard-shortcut-menu, file-upload) | ~9 |

### Migration patterns applied

- `import styled from '@emotion/styled'` → `import { styled } from
'@linaria/react'`
- `import { useTheme } from '@emotion/react'` → `import { useContext }
from 'react'` + `import { ThemeContext } from 'twenty-ui/theme'`
- `${({ theme }) => theme.X.Y.Z}` → `${themeCssVariables.X.Y.Z}` (static
CSS variables)
- `theme.spacing(N)` → `themeCssVariables.spacing[N]`
- `styled(motion.div)` → `motion.create(StyledBase)` (11 components)
- `styled(Component)<TypeParams>` → wrapper div approach for non-HTML
elements
- Multi-declaration interpolations split into one CSS property per
interpolation
- Interpolation return types fixed (`&&` → ternary `? : ''`)
- `TEXT_INPUT_STYLE` converted from function to static string constant
(backward compatible)
- Emotion `<Global>` replaced with `useEffect` style injection
- Complex runtime-dependent styles use CSS custom properties via
`style={}` prop

### After this PR

- **Remaining files**: ~400 (object-record: ~160, settings: ~200, UI:
~44)
- **No breaking changes**: CSS variables resolve identically to the
previous Emotion theme values
2026-03-03 16:42:03 +01:00
martmullandGitHub 8b26020a0b Fix missing omit in application config (#18354)
as title
2026-03-03 16:33:49 +01:00
b1107c823a Apollo enrich (#18277)
- apollo enrich application (via OAuth 2)
- add applicationId to var env in logic function executor
- update `getDefaultUrl` logic

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-03-03 14:43:10 +01:00
martmullandGitHub 5c4a1f931a Fix trigger missing (#18348)
## After

<img width="1170" height="448" alt="image"
src="https://github.com/user-attachments/assets/3a8dd77c-06d2-438e-b2d3-07d272c08588"
/>

<img width="977" height="441" alt="image"
src="https://github.com/user-attachments/assets/3e16ec94-63ce-4d09-af54-38f330bfa0c9"
/>

<img width="802" height="333" alt="image"
src="https://github.com/user-attachments/assets/0975f199-b89a-4a05-a8e4-2101f5556445"
/>
2026-03-03 14:37:17 +01:00
4266f4022a i18n - translations (#18349)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-03-03 14:24:43 +01:00
Thomas TrompetteandGitHub b2b3a3f860 Workflow iterator continues on faillure (#18325)
<img width="450" height="212" alt="Capture d’écran 2026-03-03 à 11 41
54"
src="https://github.com/user-attachments/assets/b2c29a48-7dc0-4b16-a085-8f305d21f7ca"
/>

New status `FAIL_SAFE` added. This status propagates to the following
nodes until reaching the iterator, that will start the new iteration.

The difference with `SKIP` is that, when the parent nodes have at least
one `FAIL_SAFE`, it becomes `FAIL_SAFE` too. While a parent 1 `SKIP` +
parent 2 `SUCCESS` => to be executed.

I also thought about just going back to the iterator as a break would,
but since we have branches, it may lead to inconsistent statuses with
parallel updates.
2026-03-03 14:18:57 +01:00
Charles BochetandGitHub d48c58640c Migrate CI runners from Depot back to GitHub-hosted runners (#18347)
## Summary
- Replaces all `depot-ubuntu-24.04` runners with `ubuntu-latest`
- Replaces all `depot-ubuntu-24.04-8` runners with
`ubuntu-latest-8-cores`
- Updates storybook build cache keys in ci-front.yaml to reflect the
runner name change

Reverts the temporary Depot migration introduced in #18163 / #18179
across all 23 workflow files.
2026-03-03 14:14:27 +01:00
Paul RastoinandGitHub 005223de8c [SDK] Make public-operations non throw (#18343)
Followup https://github.com/twentyhq/twenty/pull/18320
2026-03-03 14:04:13 +01:00