Commit Graph
11475 Commits
Author SHA1 Message Date
Paul RastoinandGitHub ce2723d6cf Move view field label identifier deletion validation into the cross entity validation (#19642)
## Introduction
In the same validate build and run we should be able to delete a view
field targetting a label identifier and at the same create one that
repoints to it again without failing any validation

Leading for this valdiation rule to be moved in the cross entity
validation steps
2026-04-13 14:38:27 +00:00
Thomas des FrancsandGitHub 12233e6c47 few fixes (#19648)
## Summary
- refresh the partner hero visual and testimonial presentation,
including the partner-specific carousel and illustration assets
- switch the testimonials top notch to the masked rendering approach
used elsewhere for more precise shape control
- extend halftone studio/export support and related geometry/state
handling used by the updated partner visuals
- include supporting website UI adjustments across navigation, pricing,
plans, and Salesforce-related sections

## Testing
- Not run (not requested)
2026-04-13 14:36:03 +00:00
Abdullah.andGitHub 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".
2026-04-13 14:02:21 +00:00
neo773andGitHub 88c0b24d9e Add per-workspace error handling to CronTriggerCronJob (#19640)
fix sonarly 19618
2026-04-13 13:59:54 +00:00
Thomas des FrancsandGitHub 87bb2f94bb Fixes on website (#19625)
## Summary
- fix the halftone studio image-switch behavior so image mode uses a
sane default preview distance instead of rendering nearly off-screen
- add shared preview-distance handling for shape and image modes, and
tune the default 3D idle auto-rotate speed
- update halftone controls/export plumbing to support the latest studio
settings changes
- refresh website UI/content in pricing, Salesforce, menu, and
billing-related sections

## Testing
- Ran targeted Jest tests for halftone state and footprint logic
- Ran TypeScript check for `packages/twenty-website-new`
- Broader app-level/manual testing not run
2026-04-13 13:55:38 +00:00
c67602f2e8 i18n - translations (#19647)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-13 16:00:27 +02:00
e34ca3817c i18n - translations (#19646)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-13 15:53:02 +02:00
martmullandGitHub 227d24512e Fix permission flag deletion validator (#19636)
As title
2026-04-13 13:41:28 +00:00
Raphaël BosiandGitHub 1382790c80 Fix side panel close button title (#19638)
## Before
<img width="830" height="1486" alt="CleanShot 2026-04-13 at 15 07 19@2x"
src="https://github.com/user-attachments/assets/757a52bb-f06e-4f04-950a-087cbdec0653"
/>


## After
<img width="838" height="1478" alt="CleanShot 2026-04-13 at 15 06 56@2x"
src="https://github.com/user-attachments/assets/ed9d99ab-fbda-4548-b09a-e7825d86b5dd"
/>
2026-04-13 13:39:51 +00:00
Paul RastoinandGitHub 5e7e5dd466 Colliding subject field fix on messageThread command (#19637) 2026-04-13 13:33:46 +00:00
martmullandGitHub 6182918a66 Document isAuthRequired: true instead of false (#19641) 2026-04-13 13:32:23 +00:00
Baptiste DevessierandGitHub 6829fc315a Implement full tab widget frontend (#19568)
https://github.com/user-attachments/assets/488e0145-ff49-4205-8fd3-0eb4f614c054
2026-04-13 13:24:20 +00:00
8425afd930 i18n - translations (#19645)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-13 15:37:00 +02:00
64e031b9dd i18n - translations (#19643)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-13 15:30:32 +02:00
martmullandGitHub cd10f3cbd9 Disable permission tab when empty (#19630)
as title

fixes
https://discord.com/channels/1130383047699738754/1488475331072491590
2026-04-13 13:18:49 +00:00
martmullandGitHub bf5cc68f25 Rename standard and custom apps (#19631)
as title
no migration for existing apps, changes only apply on new workspaces
2026-04-13 13:13:59 +00:00
martmullandGitHub 8bf9b12ace Fix installed app setting tab (#19629)
## Before

<img width="773" height="523" alt="image"
src="https://github.com/user-attachments/assets/e62d39b6-a82a-4b87-a983-70d63842c739"
/>


## After

<img width="780" height="519" alt="image"
src="https://github.com/user-attachments/assets/cec80e28-1298-443f-8e12-5f3b4dd8bf06"
/>
2026-04-13 13:13:53 +00:00
martmullandGitHub 2ac93bd803 Fix design (#19628)
## Before
<img width="614" height="348" alt="image"
src="https://github.com/user-attachments/assets/0a87b8cb-efe0-42ab-ad50-98a3635796f6"
/>

## After

<img width="622" height="411" alt="image"
src="https://github.com/user-attachments/assets/4f3ab135-dbe9-4384-97c2-4d20a13b3d9c"
/>
2026-04-13 13:13:45 +00:00
Charles BochetandGitHub 884b06936e Switch app test infra to globalSetup with appDevOnce (#19623)
## Summary

- Replace per-file `setupFiles` + manual
`appBuild`/`appDeploy`/`appInstall` with vitest `globalSetup` that runs
`appDevOnce` once for the entire suite and `appUninstall` in teardown
- Add `fileParallelism: false` to prevent shared-state collisions
between test files
- Replace `app-install.integration-test.ts` with
`schema.integration-test.ts` that verifies app installation, custom
object schema (fields/relations), and CRUD
- Add reusable test helpers (`client.ts`, `metadata.ts`, `mutations.ts`)
- Applied to both `create-twenty-app` template and `postcard` example
2026-04-13 13:03:52 +00:00
Baptiste DevessierandGitHub 63666547fb Fix e2e (#19639) 2026-04-13 15:13:11 +02:00
Paul RastoinandGitHub 21142d98fe Implement cross version upgrade (#19559)
# Introduction
Refactoring the upgrade engine to handle cross version upgrade,
completely getting rid of the semver `version` at db and runtime level
It remains a visual a listing indicator for or CD process but also
during devenv in order to prepare next release
Will write a release process runbook documentation on how to handle
upgrade step patch, command insertion etc as it needs to be cascaded
across all the involved supported version

**The upgrade sequence model:**

The sequence is a flat, ordered array of upgrade steps
(`UpgradeStep[]`), built from the registry by chaining all versions in
order, each version contributing its fast-instance → slow-instance →
workspace commands sorted by timestamp. Version is metadata for logging,
not used in the algorithm.

**Segments:**

The sequence naturally splits into alternating segments of contiguous
instance steps and contiguous workspace steps. The runner processes
segments in order:

- **Instance segment:** Run sequentially from the instance cursor. Each
step runs once globally.
- **Workspace segment:** Each workspace independently walks from its own
cursor through the end of the segment. Workspaces are independent within
a segment — they can be at different positions.
- **Synchronization (workspace → instance):** The runner blocks before
entering an instance segment. All active/suspended workspaces must have
completed the last workspace step of the preceding workspace segment. If
any workspace failed, abort. This is the only explicit synchronization
point.
- Instance → workspace ordering is implicit — the runner processes
segments sequentially, so the instance segment naturally completes
before the workspace segment begins.


full docs
https://gist.github.com/prastoin/e62106d455fd72d6b6ebada8351e5492

## Version constants & type-level deprecation

Version management is split into three atomic constants:
`TWENTY_PREVIOUS_VERSIONS`, `TWENTY_CURRENT_VERSION`, and
`TWENTY_NEXT_VERSIONS`. Two derived constants compose them:
`CROSS_UPGRADE_SUPPORTED_VERSIONS` (previous + current — what the engine
runs) and `ALL_TWENTY_VERSIONS` (the full ordered tuple including next).
The registry service validates at module init that no version is
duplicated across constants and that at least one previous version
exists.

A `DeprecatedSinceVersion<RemoveAtVersion, T>` type utility resolves to
`T` while `TWENTY_CURRENT_VERSION` is below `RemoveAtVersion`, and to
`never` once it reaches it — turning deprecation into a compile-time
guarantee via `IndexOf` and `IsGreaterOrEqual` generics in
`twenty-shared`.

### `workspace.version` column deprecation

The column is replaced by cursor-based state inference from
`UpgradeMigration` records, but cannot be dropped in 1.22: workspaces
activated during 1.21 predate the cursor system and need their initial
cursor backfilled first (`backfillWorkspaceCreatedIn1_21_0Cursors`).
This backfill itself depends on a new `isInitial` column on
`UpgradeMigration`, bootstrapped via a targeted TypeORM migration before
the upgrade sequence runs.

Both functions and the entity field are typed with
`DeprecatedSinceVersion<'1.23.0', ...>`. When `TWENTY_CURRENT_VERSION`
reaches `1.23.0`, compile errors force their removal — and the
pre-declared `DropWorkspaceVersionColumnFastInstanceCommand` takes over
to drop the column.

## What's next
- ci cross version upgrade ( wip )
- banner asking to contact twenty administrator if workspace is outdated
- upgrade healthcheck cli 

## New unit/integ test pattern
Create a dedicated `createNestApp` that consumes a real database in
order not to have to mack any database interaction to the
`upgradeMigrations` allowing full coverage of the whole
`upgradeRunnerService.run` core logic
2026-04-13 11:42:27 +02:00
Paul RastoinandGitHub 7091561489 Fix command FixMessageThreadViewAndLabelIdentifierCommand (#19622)
## Introduction
View standard backfill seed has been introduced during a partial patch,
a window exists where some workspaces got created without the view and
wasn't included in the upgrade process

The fix isn't covering all the view that has been missed during that
time, only the one required for the command to pass
2026-04-13 11:19:57 +02:00
de401d96fe i18n - translations (#19621)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-13 09:54:25 +02:00
09806d7d8c Add admin panel workspace detail page with chat viewer (#19579)
## Overview
Adds comprehensive admin panel functionality for viewing workspace
details and AI chat threads.

## Changes

### Frontend
- **New Routes**: Added `AdminPanelWorkspaceDetail` and
`AdminPanelWorkspaceChatThread` pages with lazy loading
- **New Queries**: 
  - `getAdminWorkspaceChatThreads` - fetch chat threads for a workspace
  - `getAdminChatThreadMessages` - fetch messages for a specific thread
  - `workspaceLookupAdminPanel` - lookup workspace info and users
- **New Components**:
- `SettingsAdminWorkspaceDetail` - displays workspace info and chat
sessions tabs
- `SettingsAdminWorkspaceChatThread` - renders chat conversation with
message bubbles
- **Navigation**: Updated AI admin panel to link to workspace detail
pages
- **Settings Paths**: Added `AdminPanelWorkspaceDetail` and
`AdminPanelWorkspaceChatThread` paths

### Backend
- **New DTOs**:
  - `AdminWorkspaceChatThreadDTO` - workspace chat thread data
  - `AdminChatThreadMessagesDTO` - thread with messages
  - `AdminChatMessageDTO` - individual message with parts
- **New Resolvers**: Added three queries to `AdminPanelResolver`
- **New Service Methods**:
  - `workspaceLookup()` - fetch workspace info
  - `getWorkspaceChatThreads()` - list chat threads
  - `getChatThreadMessages()` - fetch thread messages with validation
- **Module Updates**: Added entity imports for workspace, user, AI chat,
and feature flag data

### Security
- Added `allowImpersonation` check before accessing chat data
- Validates workspace ownership and access permissions

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 09:47:34 +02:00
150c326369 fix: prevent image upload panel from being clipped in side panel (#19613)
fixes: #19571

## What's happening
BlockNote's `.bn-panel` (the Upload/Embed popup for images, videos,
audio) has a hardcoded `width: 500px` in the upstream
`blocknoteStyles.css`. When you open it inside the side panel (~350px
wide), it overflows past the container's `overflow: hidden` and gets
clipped.
## Why percentage-based fixes don't work here
I initially tried `max-width: 100%` on `.bn-panel` but it doesn't work
the panel sits inside a Floating UI popover that's absolutely positioned
with no explicit width. Its width comes from its content (the 500px
panel), so `max-width: 100%` just resolves to that same 500px. It's a
circular reference.
## The fix
```css
& .bn-mantine {
  container-type: inline-size;
}
& .bn-mantine .bn-panel {
  width: min(500px, 100cqi);
  box-sizing: border-box;
}
```
container-type: inline-size on .bn-mantine lets us reference the
editor's actual width using cqi units. min(500px, 100cqi) keeps the
panel at 500px in wide containers (main note view) and shrinks it to fit
in narrow ones (side panel).

I scoped container-type to .bn-mantine (BlockNote's own root wrapper)
rather than the outer StyledEditor div, so the containment context stays
within BlockNote's own tree.

#Before
<img width="373" height="530" alt="image"
src="https://github.com/user-attachments/assets/63fb407c-79d1-4faa-afb4-15a98fe4ba22"
/>

#After
<img width="332" height="597" alt="image"
src="https://github.com/user-attachments/assets/f7e91c28-ad35-44a5-9450-0b6d52714977"
/>
<img width="599" height="579" alt="image"
src="https://github.com/user-attachments/assets/20fd457b-2d06-4799-9164-f993ef37d833"
/>


Tested
Side panel: panel fits correctly, matches "Add image" button width 
Full-width editor: panel stays at 500px 
Slash menu, formatting toolbar, drag handles: all unaffected

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-04-13 09:08:28 +02:00
BugIsGodandGitHub c73cdd0844 fix: prevent image upload panel from being clipped in side panel (#19572)
fixes:   #19571 
## Summary:
- BlockNote's file upload/embed panel (.bn-panel) has a hardcoded width:
500px that overflows the side panel's overflow: hidden containers,
causing the Upload/Embed UI to be cut off
<img width="636" height="364" alt="image"
src="https://github.com/user-attachments/assets/4ec501c6-409c-4a86-a5b3-2c5f104c94f1"
/>

## Before
<img width="464" height="660" alt="image"
src="https://github.com/user-attachments/assets/3364e20e-6194-4c5d-b16f-9541cc11bfd7"
/>

## After
**Same width with "Add Image" button** ( same in the video,audio upload
<img width="444" height="665" alt="image"
src="https://github.com/user-attachments/assets/369a6974-a986-44ab-a38a-a717a8f978c0"
/>
2026-04-13 09:01:07 +02:00
4e46aa32bb i18n - translations (#19612)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-12 20:33:07 +02:00
WeikoandGitHub 9e385e44f9 Fields widget draft view (#19562)
- Defer backend view creation for FIELDS widgets to prevent orphan views
when users cancel or leave before saving. Views are now created
optimistically in Jotai state (client-side UUID) and only persisted to
the database when the page layout is saved.
- Align the frontend's default field groups fallback with the backend
logic: split into General/Other groups, hide relation fields by default,
and filter invisible fields consistently across all code paths.
2026-04-12 20:26:47 +02:00
Charles BochetandGitHub 63806b24fe Export field settings types from SDK public API (#19611)
## Summary

- Follows up on #19610 which exported view/page-layout types but missed
field settings types
- Adds re-exports for `DateDisplayFormat`, `NumberDataType`, and
`FieldMetadataSettingsOnClickAction` from the SDK public API
- These enums are referenced in the return type of `defineObject` (via
field settings types like `FieldMetadataSettingsDate`,
`FieldMetadataSettingsNumber`, `FieldMetadataSettingsMultiItem`) but
were not publicly exported
- This causes TS4082 ("private name") errors for SDK consumers that have
`declaration: true` in their tsconfig, specifically when using
`defineObject` with fields that have settings (e.g. SELECT, DATE, NUMBER
fields)
2026-04-12 19:35:37 +02:00
Charles BochetandGitHub 7540bb064f Re-export missing types from SDK public API (#19610)
## Summary

- Fixes TS4082 errors for SDK consumers with `declaration: true` in
their tsconfig
- The `define*` functions (e.g. `defineView`, `definePageLayout`,
`defineLogicFunction`) return `ValidationResult<T>` where `T` references
types from `twenty-shared` that were not re-exported from the SDK's
public barrel
- TypeScript cannot generate `.d.ts` files when the return type
references "private names" — types that exist in the package but aren't
publicly exported

### Added re-exports

**Enums** (used in `ViewManifest`, `HttpRouteTriggerSettings`):
- `ViewType`, `ViewFilterOperand`, `ViewFilterGroupLogicalOperator`,
`ViewOpenRecordIn`, `ViewVisibility`
- `HTTPMethod`

**Types** (used in `PageLayoutWidgetManifest`, `LogicFunctionConfig`):
- `GridPosition`, `PageLayoutWidgetConditionalDisplay`
- `InputJsonSchema`
2026-04-12 18:33:14 +02:00
Charles BochetandGitHub ad1a4ecca0 Add isUnique support for application-defined fields (#19609)
## Summary

- Adds `isUnique?: boolean` to `RegularFieldManifest` in
`twenty-shared`, allowing SDK applications to declare unique constraints
on fields
- Updates the manifest-to-flat-field converter to read `isUnique` from
the manifest instead of hardcoding `false`
- Generates corresponding unique index metadata in
`computeApplicationManifestAllUniversalFlatEntityMaps` when a field has
`isUnique: true`, matching the behavior of the `CreateFieldInput` path
- Adds SDK-side validation rejecting `isUnique` on RELATION,
MORPH_RELATION, and FILES field types
- Adds integration test verifying manifest sync creates a unique index
for `isUnique` fields
- Adds SDK unit tests for `isUnique` validation on unsupported field
types

## Test plan

- [x] SDK unit tests: `defineField` accepts `isUnique: true` on TEXT,
rejects on RELATION and FILES
- [ ] Integration test: manifest sync with `isUnique: true` creates the
unique index in DB
- [ ] Verify `isUnique` defaults to `false` when not specified (backward
compatible)
- [ ] Verify standalone manifest fields (not nested in objects) also
generate unique indexes correctly
2026-04-12 17:03:09 +02:00
Thomas des FrancsandGitHub d9d3648baa Halftone studio v3 (glass effect) (#19598)
## Summary
- refine `/halftone` controls for material selection and slower 3D
rotation tuning
- switch the default halftone material to solid for new sessions
- include related halftone rendering, export, and glass material updates
across the website app

## Testing
- `yarn nx run twenty-website-new:typecheck`
- `yarn prettier
packages/twenty-website-new/src/app/halftone/_components/controls/AnimationsTab.tsx
--check`
- `yarn prettier
packages/twenty-website-new/src/app/halftone/_components/controls/controls-ui.tsx
packages/twenty-website-new/src/app/halftone/_components/controls/DesignTab.tsx
--check`
- `yarn prettier
packages/twenty-website-new/src/app/halftone/_lib/state.ts --check`
2026-04-12 14:40:52 +00:00
Thomas des FrancsandGitHub fda5aba9ec small fixes on pricing (#19603)
## Summary
- update pricing card styling to use a 4px border radius
- make pricing card CTAs fill the available card width
- reduce spacing below the pricing cards section
- fix pricing copy casing and punctuation, including the tailor-made
plan banner
- make engagement band headings support a configurable size and default
them to the smaller variant

## Testing
- Not run (not requested)
2026-04-12 14:39:34 +00:00
Charles BochetandGitHub 4264741281 Clear stale SDK config on uninstall and invalid client (#19608)
## Summary
- After a successful `uninstall`, clear all app registration config
(`appRegistrationId`, `appRegistrationClientId`, `appAccessToken`,
`appRefreshToken`) so the next `dev` run doesn't hit "app not found"
errors from leftover credentials
- On app re-registration (`ensureAppRegistration`), clear stale
`appAccessToken`/`appRefreshToken` that belonged to the previous
registration
- On OAuth token refresh failure, only clear config when the server
returns `invalid_client` (registration was deleted), not on transient
failures like network issues
- Extract a shared `parse-server-error` utility for consistently parsing
both GraphQL error codes (`extensions.code`/`subCode`) and OAuth error
responses (`error`/`error_description`)
2026-04-12 16:29:29 +02:00
Charles BochetandGitHub 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)
2026-04-12 15:45:31 +02:00
Charles BochetandGitHub 3ae63f0574 Fix syncApplication failing when navigation menu item child is listed before folder in manifest (#19599)
## Summary

- Fix `syncApplication` crashing with `ENTITY_NOT_FOUND` when a
navigation menu item child (with `folderUniversalIdentifier`) appears
before its folder in the manifest's `navigationMenuItems` array
- Add a generic topological sort in
`WorkspaceEntityMigrationBuilderService.validateAndBuild()` that detects
self-referential FKs from `ALL_MANY_TO_ONE_METADATA_RELATIONS` and
ensures parents are created before children
- This also covers other self-referential entities:
`viewFilterGroup.parentViewFilterGroup`,
`fieldMetadata.relationTargetFieldMetadata`, and
`rowLevelPermissionPredicateGroup.parentRowLevelPermissionPredicateGroup`

## Root cause

The builder iterated `createdFlatEntityMaps.byUniversalIdentifier` in
insertion order (from the manifest). Validation passed because it
checked both optimistic maps and remaining-to-create maps. But the
runner processed create actions sequentially, so
`resolveUniversalRelationIdentifiersToIds` threw when the folder hadn't
been created yet.
2026-04-12 12:35:38 +02:00
Charles BochetandGitHub c8f5ecb2b6 Add APPLICATION_LOG_DRIVER=CONSOLE to twenty-app-dev container (#19600)
## Summary
- Enable application log console output in the `twenty-app-dev` Docker
image by adding `APPLICATION_LOG_DRIVER=CONSOLE` to the Dockerfile ENV
block
- Rename `APPLICATION_LOG_DRIVER_TYPE` to `APPLICATION_LOG_DRIVER` and
`ApplicationLogDriverType` to `ApplicationLogDriver` for consistency
with all other driver config variables (`EMAIL_DRIVER`, `LOGGER_DRIVER`,
`CAPTCHA_DRIVER`, etc.)
- Add `APPLICATION_LOG_DRIVER` to `.env.example`
2026-04-12 11:55:38 +02:00
55b1624210 Convert AI chat state atoms to component family states (#19585)
## Summary
Refactored AI chat state management to use component family states
instead of global atoms. This change enables proper state isolation per
chat thread, preventing state leakage between different chat instances.

## Key Changes

- **Converted global atoms to component family states:**
  - `agentChatErrorState` → `agentChatErrorComponentFamilyState`
- `agentChatIsStreamingState` →
`agentChatIsStreamingComponentFamilyState`
- `agentChatFirstLiveSeqState` →
`agentChatFirstLiveSeqComponentFamilyState`
- `agentChatHandleEventCallbackState` →
`agentChatHandleEventCallbackComponentFamilyState`
  - `agentChatUsageState` → `agentChatUsageComponentFamilyState`
- `currentAIChatThreadTitleState` →
`currentAIChatThreadTitleComponentFamilyState`

- **Updated state access patterns:**
- Introduced `useAtomComponentFamilyStateCallbackState` hook to get
family state callbacks
- Changed from direct atom access to family key-based access using `{
threadId }` as the family key
- Updated all components and hooks to use the new family state patterns

- **Removed instance ID dependency:**
  - Eliminated `AGENT_CHAT_INSTANCE_ID` constant usage
- Simplified state access by using thread ID directly as the family key

- **Updated affected components and hooks:**
- `useAgentChatSubscription`: Now creates family state atoms per thread
- `AgentChatMessagesFetchEffect`: Uses family state callbacks for event
handling
- `AgentChatThreadInitializationEffect`: Sets family state values per
thread
  - `useAIChatThreadClick`: Updates family states when switching threads
- `AIChatErrorUnderMessageList`, `AIChatLastMessageWithStreamingState`,
`AIChatEmptyState`, `AIChatStandaloneError`, `SendMessageButton`,
`AIChatContextUsageButton`, `SidePanelAskAIInfo`: Updated to use family
state values with thread ID

## Implementation Details

- All new component family states use
`AgentChatComponentInstanceContext` for proper component-level isolation
- Family key structure: `{ threadId: string | null }`
- Removed `disposed` flag logic as it's no longer needed with proper
state isolation
- Updated dependency arrays in hooks to include family callback
functions

https://claude.ai/code/session_01D8syiJtCXu5bEHSr5KYkCt

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-12 07:39:12 +02:00
c268a50e4e i18n - translations (#19591)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-11 22:12:58 +02:00
4c57352450 Improve sensitive config variable masking and editing UX (#19578)
## Summary
This PR enhances the handling of sensitive configuration variables by
improving masking logic and user experience when editing them. It adds
metadata-aware masking for dynamically marked sensitive variables and
clears sensitive values when entering edit mode.

## Key Changes

- **Backend masking improvements**: Updated `maskSensitiveValue()` to
accept metadata parameter, enabling masking of variables marked as
sensitive via metadata (not just predefined masking config). Sensitive
non-string values are masked as `********`.

- **Edit mode UX**: When editing a sensitive variable, the value field
is now cleared on entering edit mode to prevent exposing masked values
and ensure users intentionally provide new secret values.

- **Form state tracking**: Enhanced `useConfigVariableForm()` hook to
accept an `isEditing` parameter and properly track value changes for
sensitive variables during edit operations.

- **Input placeholder**: Updated placeholder text for sensitive variable
inputs to show `Enter a new secret value` instead of the generic
database storage message, providing clearer intent to users.

## Implementation Details

- The `maskSensitiveValue()` method now checks both predefined masking
configurations and runtime metadata to determine if a value should be
masked
- Sensitive string values use LAST_N_CHARS strategy (4 characters),
while non-string values are masked uniformly
- The form's `hasValueChanged` flag is set to true when editing
sensitive variables to ensure proper validation and submission handling

https://claude.ai/code/session_01JiTckmuVJMQWpJ7TUGwsqb

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-11 22:07:05 +02:00
Charles BochetandGitHub b37ef3e7da Add app-path input to deploy and install composite actions (#19589)
Supports monorepo layouts where the app isn't at the repo root. Defaults
to '.' for backward compatibility.

Made-with: Cursor
2026-04-11 17:45:42 +02:00
Charles BochetandGitHub 4d877d072d Bump twenty-sdk, twenty-client-sdk, create-twenty-app to 1.22.0-canary.3 (#19587)
## Summary
- Bump `twenty-sdk`, `twenty-client-sdk`, and `create-twenty-app` from
`1.22.0-canary.2` to `1.22.0-canary.3` for publishing.

## Test plan
- Version-only change, no code modifications.

Made with [Cursor](https://cursor.com)
2026-04-11 16:04:46 +02:00
Charles BochetandGitHub baf2fc4cc9 Fix sdk-e2e-test: ensure DB is ready before server starts (#19583)
## Summary

- The `sdk-e2e-test` CI job has been failing since at least April 9th
because the nx dependency graph runs `database:reset` and
`start:ci-if-needed` in **parallel** — neither depends on the other. The
server starts before the DB tables are created, crashes with `relation
"core.keyValuePair" does not exist`, and `wait-on` times out after 10
minutes.
- Replace the `nx-affected` orchestration for e2e with explicit
**sequential** CI steps: build → create DB → reset DB → start server →
wait for health → run tests.
- Add server log dump on failure for easier future debugging.

## Root cause

In `packages/twenty-sdk/project.json`, the `test:e2e` target has:

```json
"dependsOn": [
  "build",
  { "target": "database:reset", "projects": "twenty-server" },
  { "target": "start:ci-if-needed", "projects": "twenty-server" }
]
```

Since `database:reset` and `start:ci-if-needed` don't depend on each
other, nx can (and does) run them concurrently. `start:ci-if-needed`
fires `nohup nest start &` and immediately completes. The server process
tries to query `core.keyValuePair` before `database:reset` creates it →
crash → wait-on timeout → job failure.
2026-04-11 16:02:12 +02:00
3b55026452 Improve NullCheckEnum filter descriptions with usage examples (#19581)
## Summary
Enhanced the documentation and user guidance for null/empty value
filters across all field types by updating the `NullCheckEnum`
descriptions in the field filter Zod schemas. The descriptions now
provide clear, actionable guidance on how to use the "NULL" and
"NOT_NULL" filter options.

## Changes
- Updated 20+ field type filter descriptions to replace generic "Is null
or not null" text with more descriptive guidance
- New descriptions follow the pattern: "Check for missing or empty
[field type]. Use "NULL" to find records with no [value], "NOT_NULL" for
records with a [value]"
- Applied consistent messaging across all field types including:
  - Basic types: UUID, text, number, boolean, date
  - Complex types: select, multi-select, rating
- Composite types: amount, currency, first name, last name, street,
city, country, email, phone, link URL
  - Relationship and JSON fields
- Specialized descriptions for composite fields (e.g., "Check for
missing or empty amount" for currency amount field)

## Benefits
- Improved API documentation clarity for developers using field filters
- Reduced ambiguity about NULL vs NOT_NULL filter behavior
- Better discoverability of filtering capabilities through schema
descriptions
- Consistent messaging across all field types for improved user
experience

https://claude.ai/code/session_0139Nb5bZykacNE69GQsFSrr

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-11 14:50:27 +02:00
Charles BochetandGitHub 53065f241f Exchange clientSecret for tokens after app registration + bump canary (#19582)
## Summary

- **Fix `createApplicationRegistration` flow**: The server's
`createApplicationRegistration` mutation returns a `clientSecret`, not
`accessToken`/`refreshToken` directly. The SDK now correctly requests
`clientSecret` and immediately performs an OAuth `client_credentials`
exchange to obtain `appAccessToken` and `appRefreshToken`, then stores
them in config.
- **New `exchangeCredentialsForTokens` helper**: Shared by both `dev`
and `dev --once` flows. Takes `clientId` + `clientSecret`, calls
`/oauth/token` with `client_credentials` grant, and persists the
resulting tokens.
- **Bump `twenty-sdk`, `twenty-client-sdk`, `create-twenty-app` to
`1.22.0-canary.2`**

## Context

The `1.22.0-canary.1` SDK release expected
`createApplicationRegistration` to return `accessToken`/`refreshToken`
directly, but the `v1.22.0` server returns `clientSecret`. This caused
`yarn twenty dev` and `yarn twenty dev --once` to fail with "No
registration found" errors.
2026-04-11 12:26:18 +02:00
Thomas des FrancsandGitHub 300be990b0 halftone v2 (#19573)
## Summary
- Add Playwright inspection scripts for problem canvas export, chain
logging, and metrics capture
- Save updated markdown snapshots and screenshot artifacts for homepage
and problem section debugging
- Include generated browser profile data used during the investigation

## Testing
- Not run (not requested)
2026-04-11 10:00:24 +00:00
Charles BochetandGitHub 0a76db94bc Bump twenty-sdk, twenty-client-sdk, create-twenty-app to 1.22.0-canary.1 (#19580)
## Summary
- Bumps `twenty-sdk`, `twenty-client-sdk`, and `create-twenty-app`
package versions from `0.9.0` to `1.22.0-canary.1` for the 1.22 canary
release.

## Test plan
- [ ] Verify packages build successfully (`npx nx build twenty-sdk`,
`npx nx build twenty-client-sdk`, `npx nx build create-twenty-app`)
- [ ] Verify `create-twenty-app` scaffolds new apps with the correct SDK
version


Made with [Cursor](https://cursor.com)
2026-04-11 11:34:55 +02:00
Charles BochetandGitHub c26c0b9d71 Use app's own OAuth credentials for CoreApiClient generation (#19563)
## Summary

- **SDK (`dev` & `dev --once`)**: After app registration, the CLI now
obtains an `APPLICATION_ACCESS` token via `client_credentials` grant
using the app's own `clientId`/`clientSecret`, and uses that token for
CoreApiClient schema introspection — instead of the user's
`config.accessToken` which returns the full unscoped schema.
- **Config**: `oauthClientSecret` is now persisted alongside
`oauthClientId` in `~/.twenty/config.json` when creating a new app
registration, so subsequent `dev`/`dev --once` runs can obtain fresh app
tokens without re-registration.
- **CI action**: `spawn-twenty-app-dev-test` now outputs a proper
`API_KEY` JWT (signed with the seeded dev workspace secret) instead of
the previous hardcoded `ACCESS` token — giving consumers a real API key
rather than a user session token.

## Motivation

When developing Twenty apps, `yarn twenty dev` was using the CLI user's
OAuth token for GraphQL schema introspection during CoreApiClient
generation. This token (type `ACCESS`) has no `applicationId` claim, so
the server returns the **full workspace schema** — including all objects
— rather than the scoped schema the app should see at runtime (filtered
by `applicationId`).

This caused a discrepancy: the generated CoreApiClient contained fields
the app couldn't actually query at runtime with its `APPLICATION_ACCESS`
token.

By switching to `client_credentials` grant, the SDK now introspects with
the same token type the app will use in production, ensuring the
generated client accurately reflects the app's runtime capabilities.
2026-04-11 11:24:28 +02:00
f52d66b960 i18n - translations (#19570)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-10 19:19:17 +02:00
65b2baca7a Remove IS_USAGE_ANALYTICS_ENABLED feature flag (#19566)
## Summary
This PR removes the `IS_USAGE_ANALYTICS_ENABLED` feature flag and makes
usage analytics features universally available. The feature flag guard
has been removed from the usage analytics resolver and all conditional
rendering based on this flag has been eliminated.

## Key Changes
- **Removed feature flag dependency**: Deleted
`IS_USAGE_ANALYTICS_ENABLED` from the `FeatureFlagKey` enum in
`twenty-shared`
- **Updated AI Usage tab**: Simplified `SettingsAIUsageTab` to remove
enterprise access checks and feature flag conditionals, now only checks
if ClickHouse is configured
- **Updated Usage Analytics section**: Removed feature flag guard from
`SettingsUsageAnalyticsSection` and added loading/empty state handling
- **Updated AI settings navigation**: Made the Usage tab always visible
in the AI settings tabs, removing conditional rendering based on feature
flag
- **Updated Billing Credits section**: Removed feature flag check before
showing the "View usage" button
- **Updated Settings routes**: Removed `SettingsProtectedRouteWrapper`
with feature flag requirement from usage routes
- **Updated GraphQL resolver**: Removed `@RequireFeatureFlag` decorator
and `FeatureFlagGuard` from the `getUsageAnalytics` query
- **Updated dev seeder**: Removed the feature flag seed entry for
`IS_USAGE_ANALYTICS_ENABLED`

## Implementation Details
- Usage analytics now gracefully handles loading states with
`UsageSectionSkeleton`
- Empty state messaging is shown when no usage data is available yet
- ClickHouse configuration remains the only requirement for usage
analytics functionality
- All enterprise-specific gating for AI usage analytics has been removed
in favor of ClickHouse availability checks

https://claude.ai/code/session_01MRFVXtquL3wS7qmQkDU3AT

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-10 19:12:33 +02:00