Skip to content

Commit 233af4e

Browse files
walmatclaudeBOHEUSneo773greptile-apps[bot]
authored
Merge staging to main: February release
* Add configurable ingestion pipeline system for no-code data import Introduces a generalized pipeline system that replaces hardcoded webhook workers with a configurable approach. Supports push (webhook) and pull (scheduled fetch) modes with field mapping, transforms, relation resolution, and dedup/upsert. Backend: NestJS module with entities, GraphQL resolvers, BullMQ jobs, per-pipeline rate limiting (100 req/min via ThrottlerService), and 100 tests across 12 suites. Frontend: Settings UI for pipeline CRUD, field mapping editor, dry-run testing, and run history. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Add configurable ingestion pipeline system for no-code data import Introduces a generalized pipeline system that replaces hardcoded webhook workers with a configurable approach. Supports push (webhook) and pull (scheduled fetch) modes with field mapping, transforms, relation resolution, and dedup/upsert. Backend: NestJS module with entities, GraphQL resolvers, BullMQ jobs, per-pipeline rate limiting (100 req/min via ThrottlerService), and 100 tests across 12 suites. Frontend: Settings UI for pipeline CRUD, field mapping editor, dry-run testing, and run history. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Fix DB replication: disable triggers during restore, fix refreshToken table name Co-Authored-By: Claude Opus 4.6 <[email protected]> * Fix DB replication: enable pgcrypto extension for gen_random_bytes Co-Authored-By: Claude Opus 4.6 <[email protected]> * Fix connected account permissions (#17598) Fixes #17411 --------- Co-authored-by: neo773 <[email protected]> Co-authored-by: neo773 <[email protected]> Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * i18n - docs translations (#18017) Created by Github action --------- Co-authored-by: github-actions <[email protected]> * Add Google OAuth callback URLs for staging domain Co-Authored-By: Claude Opus 4.6 <[email protected]> * Fix staging OAuth: rewrite prod domain in DB config during replication Twenty's config system gives DB values priority over env vars, so we need to rewrite crm.omniaagent.com -> staging-crm.omniaagent.com in the configVariable table after replicating prod data. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Fix config URL rewrite: use correct keyValuePair table with jsonb cast Co-Authored-By: Claude Opus 4.6 <[email protected]> * i18n - docs translations (#18020) Created by Github action Co-authored-by: github-actions <[email protected]> * Files command - fixes (#18016) - Fixed "property entity not found" error when updating/creating a new field and querying the same object repository just after - Downgraded log type for unnecessary migration * Date & DateTime validation fixes / improvements (#18009) Fixes https://github.com/twentyhq/twenty/issues/17138 - Backend should have strict date/dateTime format validation - FE in import csv is more permissive --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * fixes: loosen up front validation, add resolveEntityRelationUniversalIdentifiers to update and restore (#18015) closes https://github.com/twentyhq/private-issues/issues/419 * New field creates fields widget field (#18022) ## Context Introducing "NewFieldDefaultConfiguration" to FIELDS widget configurations ```typescript { isVisible: boolean; viewFieldGroupId: string | null; } ``` This configuration will define where a new field should be added (which section) and its default visibility inside FIELDS widget views. The new field position should always be at the end (meaning the last position for the view fields OR the last position of a viewFieldGroup) See "New fields" on this screenshot <img width="401" height="724" alt="Layout V1" src="https://github.com/user-attachments/assets/4969bcaa-f244-4504-8947-778a02c24c47" /> * App feedbacks (#18028) as title * Add SSE for metadata and plug front components (#17998) Create the necessary tooling to listen to metadata events and plug it to the front components. Now we have a hot reload like experience when we edit a component in an app. ## Backend - Split `EventWithQueryIds` into `ObjectRecordEventWithQueryIds` and `MetadataEventWithQueryIds` - Publish metadata event batches to active SSE streams in `MetadataEventsToDbListener` ## Frontend - Create a metadata event dispatching pipeline: SSE metadata events are grouped by metadata name, transformed into `MetadataOperationBrowserEventDetail` objects, and dispatched as browser `CustomEvents` - Add `useListenToMetadataOperationBrowserEvent` hook for consuming metadata operation events filtered by metadata name and operation type - Rename `useListenToObjectRecordEventsForQuery` to `useListenToEventsForQuery`, now accepting both `RecordGqlOperationSignature` and `MetadataGqlOperationSignature` - Implement `useOnFrontComponentUpdated` which subscribes to front component metadata events and updates the Apollo cache when the component is modified - Add `builtComponentChecksum` to the front component query and appends it to the component URL for browser cache invalidation * Improve API Client usage and add Typescript check (#18023) ## Summary https://github.com/user-attachments/assets/1e75cc9d-d9d2-4ef2-99f9-34450f5d8de7 Add background incremental type checking (`tsc --watch`) to the SDK dev mode, so type regressions are caught when the generated API client changes — without requiring a full rebuild of source files. Previously, removing a field from the data model would regenerate the API client, but existing front components/logic functions referencing the removed field wouldn't surface type errors (since their source didn't change, esbuild wouldn't rebuild them). ## What changed - **Background `tsc --watch`**: a long-lived TypeScript watcher runs alongside esbuild watchers, incrementally re-checking all files when the generated client changes. Only logs on state transitions (errors appear / errors clear) to stay quiet. - **Atomic client generation**: API client is now generated into a temp directory and swapped in atomically, avoiding a race condition where `tsc --watch` could see an empty `generated/` directory mid-regeneration. - **Step decoupling**: orchestrator steps no longer receive `uploadFilesStep` directly. Instead, they use callbacks (`onFileBuilt`, `onApiClientGenerated`), and each step manages its own `builtFileInfos` state. - **`apiClientChecksum` omitted from `ApplicationConfig`**: it's a build-time computed value, same as `packageJsonChecksum`. <img width="327" height="177" alt="image" src="https://github.com/user-attachments/assets/02bd25bb-fa41-42b0-8d96-01c51bd4580c" /> <img width="529" height="452" alt="image" src="https://github.com/user-attachments/assets/61f6e968-365b-4a5b-8f2b-a8419d6b1bd3" /> * i18n - translations (#18029) Created by Github action --------- Co-authored-by: github-actions <[email protected]> * v1.18 - Fix command (#18032) Same as here https://github.com/twentyhq/twenty/pull/18016 * Fix Gmail thread awareness for custom labels (#18031) This fixes two edge cases for Gmail - When policy was set to `SELECTED_FOLDERS` excluding root INBOX, it missed label changes, so messages with newly applied labels weren't imported until a full resync. - Gmail thread replies by default by default do no inherit parent message's label properties so thread context was also lost because only individually labeled messages were returned, dropping earlier parts of the conversation. Fixed by subscribing to `labelAdded`/`labelRemoved` history events and fetching full thread context when at least one message in a thread carries a synced label. `ALL_FOLDERS` path is untouched. * Allow DATE_TIME IS operand to filter on a whole day (#17529) Fixes: https://github.com/twentyhq/core-team-issues/issues/2027 We've replaced the DATE_TIME picker with DATE picker, and changed the logic to filter for complete day period. https://github.com/user-attachments/assets/ba7e1078-bab3-4c62-a803-d6a851f14b7d --------- Co-authored-by: Arun kumar <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * Replace generic "Unknown error" messages with descriptive error details (#18019) ## Summary - Replace all generic `"Unknown error"` fallback messages across the server codebase with messages that include the actual error details - The most impactful change is in `guard-redirect.service.ts`, which handles OAuth redirect errors — non-`AuthException` errors (e.g., passport state verification failures) now show `"Authentication error: <actual message>"` instead of the opaque `"Unknown error"` - Gmail/Google error handler services now include the error message in the thrown exception instead of discarding it - Other catch blocks (workflow delay resume, migration runner rollback, code interpreter, marketplace) now use `String(error)` for non-Error objects instead of a static fallback Fixes the class of issues reported in https://github.com/twentyhq/twenty/issues/17812, where a user saw "Unknown error" during Google OAuth and had no way to diagnose the root cause (which turned out to be a session cookie / SSL configuration issue). ## Test plan - [ ] Verify OAuth error flows (e.g., Google Auth with misconfigured callback URL) now display the actual error message on the `/verify` page instead of "Unknown error" - [ ] Verify Gmail sync error handling still correctly classifies and re-throws errors with descriptive messages - [ ] Verify workflow delay resume failures include the error details in the workflow run status Made with [Cursor](https://cursor.com) Co-authored-by: Cursor <[email protected]> * Use proper PostgreSQL identifier/literal escaping in workspace DDL (#18024) ## Summary - Replace the character-stripping approach (`removeSqlDDLInjection`) with standard PostgreSQL `escapeIdentifier` and `escapeLiteral` functions across all workspace schema manager services - Add missing identifier escaping to `createForeignKey` (was the only method in the FK manager without it) - Add allowlist validation for index WHERE clauses and FK action types - Harden tsvector expression builder with proper identifier quoting ## Context The workspace schema managers build DDL dynamically from metadata (table names, column names, enum values, etc.). The previous approach stripped all non-alphanumeric characters — safe but lossy (silently corrupts values with legitimate special characters). The new approach uses PostgreSQL's standard escaping: - **Identifiers**: double internal `"` and wrap → `"my""table"` (same algorithm as `pg` driver's `escapeIdentifier`) - **Literals**: double internal `'` and wrap → `'it''s a value'` (same algorithm as `pg` driver's `escapeLiteral`) `removeSqlDDLInjection` is kept only for name generation (e.g., `computePostgresEnumName`) where stripping to `[a-zA-Z0-9_]` is the correct behavior. ## Files changed | File | What | |------|------| | `remove-sql-injection.util.ts` | Added `escapeIdentifier` + `escapeLiteral` | | `validate-index-where-clause.util.ts` | New — allowlist for partial index WHERE clauses | | 5 schema manager services | Replaced strip+manual-quote with `escapeIdentifier`/`escapeLiteral` | | `build-sql-column-definition.util.ts` | `escapeIdentifier` for column names, validated `generatedType` | | `sanitize-default-value.util.ts` | `escapeLiteral` instead of stripping | | `serialize-default-value.util.ts` | `escapeLiteral` for values, `escapeIdentifier` for enum casts | | `get-ts-vector-column-expression.util.ts` | `escapeIdentifier` for field names in expressions | | `sanitize-default-value.util.spec.ts` | Updated tests for escape behavior | ## Test plan - [x] All 64 existing tests pass across 6 test suites - [x] `lint:diff-with-main` passes - [x] TypeScript typecheck — no new errors - [ ] Verify workspace sync-metadata still works end-to-end - [ ] Verify custom object/field creation works - [ ] Verify enum field option changes work Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <[email protected]> * Fixes - Workspace logo migration (#18035) - Update migration command to handle case where workspace logo is originated from workspace email and point to twenty-icons.com - Update same logic for new workspaces - Add feature-flag for all newly created workspaces * [Chore] : Generate migration for DATE_TIME to DATE for DATE_TIME + IS operand filters (#17564) migration command in response to the fix : https://github.com/twentyhq/twenty/pull/17529 for the issue https://github.com/twentyhq/core-team-issues/issues/2027 --------- Co-authored-by: Arun kumar <[email protected]> Co-authored-by: Lucas Bordeau <[email protected]> * Share APP_SECRET from prod to staging for encrypted config decryption Co-Authored-By: Claude Opus 4.6 <[email protected]> * 2094 extensibility define postinstall orand preinstall function to run in application (#18037) - add a new optional key `postInstallLogicFunctionUniversalIdentifier` in applicationConfig - seed postInstall function in create-twenty-app - update execute:function options - update doc * Fix tokens secret copy: use replace --force to overwrite Helm-managed secret Co-Authored-By: Claude Opus 4.6 <[email protected]> * Nav Menu Item Migration command fix (#18041) * Fix tokens secret sync: delete+create instead of replace to avoid Helm conflicts Co-Authored-By: Claude Opus 4.6 <[email protected]> * Increase Helm timeout to 15m, remove cleanup-on-fail for staging Co-Authored-By: Claude Opus 4.6 <[email protected]> * i18n - docs translations (#18040) Created by Github action Co-authored-by: github-actions <[email protected]> * Sync page Layout (#18034) ## Sync page layouts, tabs, and widgets Adds the ability for SDK applications to synchronize `pageLayout`, `pageLayoutTab`, and `pageLayoutWidget` entities, following the same pattern established in #18003 for views and navigation menu items. ### Changes **`twenty-shared`** - New `PageLayoutManifest`, `PageLayoutTabManifest`, and `PageLayoutWidgetManifest` types with a hierarchical structure (page layout → tabs → widgets) - Added `pageLayouts: PageLayoutManifest[]` to the `Manifest` type **`twenty-sdk`** - New `definePageLayout()` SDK function with validation for universalIdentifier, name, and nested tabs/widgets - Wired into the manifest extraction and build pipeline (`DefinePageLayout` target function, `PageLayouts` entity key) - Exported from the SDK entry point **`twenty-server`** - Added `pageLayout`, `pageLayoutTab`, `pageLayoutWidget` to `APPLICATION_MANIFEST_METADATA_NAMES` - New conversion utilities: manifest → universal flat entity for all three entity types - Updated `computeApplicationManifestAllUniversalFlatEntity * Fix tokens secret sync: patch existing secret instead of delete+recreate Co-Authored-By: Claude Opus 4.6 <[email protected]> * Fix tokens secret: patch existing or create new, keep Helm create as fallback Co-Authored-By: Claude Opus 4.6 <[email protected]> * Fix ingestion pipeline UI: compile Lingui i18n catalogs and stop scrambling emails on staging Lingui message extraction and compilation was never run for the ingestion pipeline files, causing all UI labels to show garbled hash IDs. Also removes email scrambling from the DB replication script since staging is a private environment used by the same team - scrambling caused userId mismatches that blocked Google OAuth login. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Add example in create-twenty-app (#18043) - add interactive mode to create-twenty-app - by default create an example for each entities <img width="1181" height="168" alt="image" src="https://github.com/user-attachments/assets/a2490d8f-66a1-4cd5-bf41-57166cc20a1e" /> * i18n - docs translations (#18048) Created by Github action Co-authored-by: github-actions <[email protected]> * Add missing objects to rich app integration tests (#18039) Updating rich app so it also create: - a many to many relation - views - navigation items The app was built successfully. Will still be missing front component examples <img width="1498" height="660" alt="Capture d’écran 2026-02-18 à 17 47 25" src="https://github.com/user-attachments/assets/acd5193f-3a36-4eb7-8276-3154e4e60f5e" /> * Refactor page layout types (#18042) ## Refactor page layout widget types into shared package and expose from SDK ### Why Widget configuration types were defined only on the server, forcing SDK consumer apps to import from deep internal `twenty-shared/dist` paths — fragile and breaks on structural changes. Server DTOs also had no compile-time guarantee they matched the canonical types. ### What changed - **`twenty-shared`**: Migrated `ChartFilter`, `GridPosition`, `RatioAggregateConfig` and all 20 widget configuration variants into `twenty-shared/types`. `PageLayoutWidgetConfiguration` (base, with `SerializedRelation`) and `PageLayoutWidgetUniversalConfiguration` (derived via `FormatRecordSerializedRelationProperties`) are now the single source of truth. - **`twenty-sdk`**: Re-exported `AggregateOperations`, `ObjectRecordGroupByDateGranularity`, `PageLayoutTabLayoutMode`, and `PageLayoutWidgetUniversalConfiguration` so consumer apps import from `twenty-sdk` directly. - **`twenty-server`**: All widget DTOs now `implements` their shared type for compile-time enforcement. Added helpers to convert nested `fieldMetadataId` ↔ `fieldMetadataUniversalIdentifier` inside chart filters. Removed redundant local type re-exports. * refactor workflow action messaging with callout (#18038) ## Summary - remove the dedicated `WorkflowMessage` component and story - update workflow action editor components to use the shared callout patterns - adjust `Callout` and its stories to support the new usage in workflow actions ## Before/After <img width="525" height="548" alt="image" src="https://github.com/user-attachments/assets/ce57a84f-f070-4149-85ef-a4d162b2d878" /> <img width="518" height="593" alt="image" src="https://github.com/user-attachments/assets/f7249cd0-221f-496d-9deb-d9966ee43382" /> * Add currency hover tooltip in CurrencyDisplay (#18045) https://github.com/user-attachments/assets/af768ecb-b5e9-4e8d-a9f9-fee1a08ea9a0 Fixes https://github.com/twentyhq/twenty/issues/17756 * Increase staging worker memory limit to 1024Mi to fix OOM crash Worker was in CrashLoopBackOff with "JavaScript heap out of memory" error at 512Mi. Matches production worker memory limit. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Increase staging worker memory limit to 1024Mi to fix OOM crash Worker was in CrashLoopBackOff with "JavaScript heap out of memory" error at 512Mi. Matches production worker memory limit. Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: show "Not shared" for junction relation fields when target or intermediate object is not readable (#18025) When a user's role lacks read permission on the target object (e.g., Company) or the intermediate junction object (e.g., EmploymentHistory), junction relation fields like "Previous Companies" displayed as blank instead of showing "Not shared." - In RecordFieldList, junction fields now check the junction object's read permission and set isForbidden on the field context so FieldDisplay renders "Not shared" instead of an empty field. - In RelationFromManyFieldDisplay, if junction records exist but all nested target records are null (permission-denied by the API), the component renders "Not shared" instead of an empty list. --------- Co-authored-by: Félix Malfait <[email protected]> * Fix ingestion worker: wrap record processing in workspace context The worker needs a workspace context (via AsyncLocalStorage) to use GlobalWorkspaceOrmManager. Uses buildSystemAuthContext() like other job processors in the codebase. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Fix ingestion worker: wrap record processing in workspace context The worker needs a workspace context (via AsyncLocalStorage) to use GlobalWorkspaceOrmManager. Uses buildSystemAuthContext() like other job processors in the codebase. Co-Authored-By: Claude Opus 4.6 <[email protected]> * i18n - docs translations (#18050) Created by Github action Co-authored-by: github-actions <[email protected]> * Restore old favorite design (#18049) Issue : With IS_NAVIGATION_MENU_ITEM_ENABLED:true + IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED:false, nav menu design is changed after 1.18.0 release : views expansion removed, system object displayed, position re-ordered We prefer keeping the same "old" favorite behaviour and design state - After 1.18.0 all workspaces have up-to-date navigation menu items (migrated) - IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED becomes the FF for nav menu new design --------- Co-authored-by: Charles Bochet <[email protected]> * Fix impossible scroll in sdk app:dev (#18051) Issue is that we are refreshing the terminal because of icons animations * Harden server-side input validation and auth defaults (#18018) ## Summary - **File storage (LocalDriver):** Add realpath resolution and symlink rejection to `writeFile`, `downloadFile`, and `downloadFolder` — brings them in line with the existing `readFile` protections. Includes unit tests. - **JWT:** Pin signing/verification to HS256 explicitly. - **Auth:** Revoke active refresh tokens when a user changes their password. - **Logic functions:** Validate `handlerName` as a safe JS identifier at both DTO and runtime level, preventing injection into the generated runner script. - **User entity:** Remove `passwordHash` from the GraphQL schema (`@Field` decorator removed, column stays). - **Query params:** Use `crypto.randomBytes` instead of `Math.random` for SQL parameter name generation. - **Exception filter:** Mirror the request `Origin` header instead of sending `Access-Control-Allow-Origin: *`. ## Test plan - [x] `local.driver.spec.ts` — writeFile rejects symlinks, downloadFile rejects paths outside storage - [ ] Verify JWT auth flow still works (login, token refresh) - [ ] Verify password change invalidates existing sessions - [ ] Verify logic function creation with valid/invalid handler names - [ ] Verify file upload/download in dev environment Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <[email protected]> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> * Add static transform type for constant field values in ingestion pipeline Allows setting a fixed value regardless of source data, useful for fields like leadStatus that need a default (e.g. "ASSIGNED"). Co-Authored-By: Claude Opus 4.6 <[email protected]> * Add static transform type for constant field values in ingestion pipeline Allows setting a fixed value regardless of source data, useful for fields like leadStatus that need a default (e.g. "ASSIGNED"). Co-Authored-By: Claude Opus 4.6 <[email protected]> * Skip empty string source values in ingestion field mapping Convoso sends empty strings for unpopulated fields. These should be treated as absent rather than mapped to target fields where they'd cause enum validation errors. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Skip empty string source values in ingestion field mapping Convoso sends empty strings for unpopulated fields. These should be treated as absent rather than mapped to target fields where they'd cause enum validation errors. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Prevent SSRF via IMAP/SMTP/CalDAV (#17973) Prevents leaking of internal services by filtering out private IPs, same way we do for webhooks * Fix website build (#18052) * i18n - translations (#18053) Created by Github action --------- Co-authored-by: github-actions <[email protected]> * Improve security settings card grouping and description overflow (#17928) # After - Added a separtor between the two audit logs cards - Rename the audit log card to avoid repetition - Grouped "Invite by link" and "2 factor auth" in one group - Changed the card component description to always be one line max with truncation & tooltips <img width="777" height="1278" alt="CleanShot 2026-02-13 at 17 02 36" src="https://github.com/user-attachments/assets/685c792a-c85b-4521-8c1b-bd9adedc75d9" /> <img width="976" height="690" alt="b49f2eb043b6712d013618bb0a4ef7f011cf2316e1163fbdee4c293bed036ac9" src="https://github.com/user-attachments/assets/6e17aa11-ecdb-4f98-ba50-5cd9b9c5def6" /> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Charles Bochet <[email protected]> Co-authored-by: Charles Bochet <[email protected]> * Fix empty string values bypassing enum validation in ingestion pipeline The post-transform check only tested isDefined, so empty strings from map transforms passed through and caused PostgreSQL enum errors (e.g. gender: ""). Co-Authored-By: Claude Opus 4.6 <[email protected]> * Fix empty string values bypassing enum validation in ingestion pipeline The post-transform check only tested isDefined, so empty strings from map transforms passed through and caused PostgreSQL enum errors (e.g. gender: ""). Co-Authored-By: Claude Opus 4.6 <[email protected]> * i18n - translations (#18056) Created by Github action --------- Co-authored-by: github-actions <[email protected]> * Fix website build (#18057) * Add Health Sherpa policy ingestion with smart person matching Implements automated policy data ingestion from Health Sherpa webhooks using the existing ingestion pipeline infrastructure. Features: - Generic policy fields (carrier-agnostic): applicationId, externalSource, etc. - Smart person matching with 4-strategy fallback system: 1. Match by phone (normalized) 2. Match by agent NPN + member name 3. Match by email (skip junk emails) 4. Auto-create person if no match - Deduplication by applicationId (update vs create) - Phone normalization: "(555) 123-4567" → "5551234567" - Auto-assign to agent by NPN - Duplicate email handling (retry without email) - 17 field mappings (webhook → CRM) - Full unit test coverage New files: - Migration: add-external-policy-fields (9 new columns + indexes) - Seed: seed-healthsherpa-pipeline.command.ts - Preprocessor: healthsherpa-policy.preprocessor.ts (smart matching) - Registry: ingestion-preprocessor.registry.ts - Tests: healthsherpa-policy.preprocessor.spec.ts (12 tests) Modified files: - ingestion-push-process.job.ts (call preprocessor) - ingestion-pipeline.module.ts (register providers) - ingestion-job.module.ts (register providers) Co-Authored-By: Claude Opus 4.6 <[email protected]> * Messages Message Folder Association (#17398) This PR adds Message folder association for message channel messages, Currently under testing phase, not ready yet. --------- Co-authored-by: Claude Opus 4.6 <[email protected]> * Fix website build (#18061) As per title * i18n - docs translations (#18062) Created by Github action Co-authored-by: github-actions <[email protected]> * Add Convoso call ingestion preprocessor for ingestion pipeline Introduces ConvosoCallPreprocessor that enriches call payloads with computed fields (direction, name, person/lead source resolution, billing) and filters incomplete/system payloads. Updates the preprocessor registry to support null returns for record skipping. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Wrap preprocessor in workspace context for DB access The preprocessor runs before processRecords which has its own workspace context. Preprocessors that access the database (like ConvosoCall and HealthSherpa) need workspace context to resolve repositories. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Migrate dropdown to jotai (#18063) Here we go again * Add incoming payload viewer to ingestion pipeline run history Stores the raw incoming webhook payload on each ingestion log entry and displays it in an expandable row in the Run History table. Clicking a row reveals the JSON payload and any errors. Co-Authored-By: Claude Opus 4.6 <[email protected]> * i18n - docs translations (#18067) Created by Github action Co-authored-by: github-actions <[email protected]> * Bump @xyflow/react from 12.4.2 to 12.10.0 (#18070) Bumps [@xyflow/react](https://github.com/xyflow/xyflow/tree/HEAD/packages/react) from 12.4.2 to 12.10.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/xyflow/xyflow/releases"><code>@​xyflow/react</code>'s releases</a>.</em></p> <blockquote> <h2><code>@​xyflow/react</code><a href="https://github.com/12"><code>@​12</code></a>.10.0</h2> <h3>Minor Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5637">#5637</a> <a href="https://github.com/xyflow/xyflow/commit/0c7261a6dc94f1aa58333a6aebcaca8ced9b5ad2"><code>0c7261a6d</code></a> Thanks <a href="https://github.com/moklick"><code>@​moklick</code></a>! - Add <code>zIndexMode</code> to control how z-index is calculated for nodes and edges</p> </li> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5484">#5484</a> <a href="https://github.com/xyflow/xyflow/commit/a523919d6789995e9d0f3dd29b0b47fc3b8d8439"><code>a523919d6</code></a> Thanks <a href="https://github.com/peterkogo"><code>@​peterkogo</code></a>! - Add <code>experimental_useOnNodesChangeMiddleware</code> hook</p> </li> </ul> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5629">#5629</a> <a href="https://github.com/xyflow/xyflow/commit/9030fab2df8285fdfb649bda6e1e885dfd228d45"><code>9030fab2d</code></a> Thanks <a href="https://github.com/AlaricBaraou"><code>@​AlaricBaraou</code></a>! - Prevent unnecessary re-render in <code>FlowRenderer</code></p> </li> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5592">#5592</a> <a href="https://github.com/xyflow/xyflow/commit/38dbf41c464550cc803b946a4ad1f46982385a03"><code>38dbf41c4</code></a> Thanks <a href="https://github.com/svilen-ivanov-kubit"><code>@​svilen-ivanov-kubit</code></a>! - Always create a new measured object in apply changes.</p> </li> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5635">#5635</a> <a href="https://github.com/xyflow/xyflow/commit/2d7fa40e2684a0fcdd4eca7800ccf2c34338e549"><code>2d7fa40e2</code></a> Thanks <a href="https://github.com/tornado-softwares"><code>@​tornado-softwares</code></a>! - Update an ongoing connection when user moves node with keyboard.</p> </li> <li> <p>Updated dependencies [<a href="https://github.com/xyflow/xyflow/commit/0c7261a6dc94f1aa58333a6aebcaca8ced9b5ad2"><code>0c7261a6d</code></a>, <a href="https://github.com/xyflow/xyflow/commit/8598b6bc2a9d052b12d5215706382da0aa84827b"><code>8598b6bc2</code></a>, <a href="https://github.com/xyflow/xyflow/commit/2d7fa40e2684a0fcdd4eca7800ccf2c34338e549"><code>2d7fa40e2</code></a>]:</p> <ul> <li><code>@​xyflow/system</code><a href="https://github.com/0"><code>@​0</code></a>.0.74</li> </ul> </li> </ul> <h2><code>@​xyflow/react</code><a href="https://github.com/12"><code>@​12</code></a>.9.3</h2> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5621">#5621</a> <a href="https://github.com/xyflow/xyflow/commit/c1304dba7a20bb8d74c7aceb23cd80b56e4c0482"><code>c1304dba7</code></a> Thanks <a href="https://github.com/moklick"><code>@​moklick</code></a>! - Set <code>paneClickDistance</code> default value to <code>1</code>.</p> </li> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5578">#5578</a> <a href="https://github.com/xyflow/xyflow/commit/00bcb9f5f45f49814b9ac19b3f55cfe069ee3773"><code>00bcb9f5f</code></a> Thanks <a href="https://github.com/peterkogo"><code>@​peterkogo</code></a>! - Pass current pointer position to connection</p> </li> <li> <p>Updated dependencies [<a href="https://github.com/xyflow/xyflow/commit/00bcb9f5f45f49814b9ac19b3f55cfe069ee3773"><code>00bcb9f5f</code></a>]:</p> <ul> <li><code>@​xyflow/system</code><a href="https://github.com/0"><code>@​0</code></a>.0.73</li> </ul> </li> </ul> <h2><code>@​xyflow/react</code><a href="https://github.com/12"><code>@​12</code></a>.9.2</h2> <h3>Patch Changes</h3> <ul> <li><a href="https://redirect.github.com/xyflow/xyflow/pull/5593">#5593</a> <a href="https://github.com/xyflow/xyflow/commit/a8ee089d7689d9a58113690c8e90e1c1e109602a"><code>a8ee089d7</code></a> Thanks <a href="https://github.com/moklick"><code>@​moklick</code></a>! - Reset selection box when user selects a node</li> </ul> <h2><code>@​xyflow/react</code><a href="https://github.com/12"><code>@​12</code></a>.9.1</h2> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5572">#5572</a> <a href="https://github.com/xyflow/xyflow/commit/5ec0cac7fad21109b74839969c0818f88ddc87d9"><code>5ec0cac7f</code></a> Thanks <a href="https://github.com/peterkogo"><code>@​peterkogo</code></a>! - Fix onPaneClick events being suppressed when selectionOnDrag=true</p> </li> <li> <p>Updated dependencies [<a href="https://github.com/xyflow/xyflow/commit/5ec0cac7fad21109b74839969c0818f88ddc87d9"><code>5ec0cac7f</code></a>]:</p> <ul> <li><code>@​xyflow/system</code><a href="https://github.com/0"><code>@​0</code></a>.0.72</li> </ul> </li> </ul> <h2><code>@​xyflow/react</code><a href="https://github.com/12"><code>@​12</code></a>.9.0</h2> <h3>Minor Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5544">#5544</a> <a href="https://github.com/xyflow/xyflow/commit/c17b49f4c16167da3f791430163edd592159d27d"><code>c17b49f4c</code></a> Thanks <a href="https://github.com/0x0f0f0f"><code>@​0x0f0f0f</code></a>! - Add <code>EdgeToolbar</code> component</p> </li> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5550">#5550</a> <a href="https://github.com/xyflow/xyflow/commit/6ffb9f7901c32f5b335aee2517f41bf87f274f32"><code>6ffb9f790</code></a> Thanks <a href="https://github.com/peterkogo"><code>@​peterkogo</code></a>! - Prevent child nodes of different parents from overlapping</p> </li> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5551">#5551</a> <a href="https://github.com/xyflow/xyflow/commit/6bb64b3ed60f26c9ea8bc01c8d62fb9bf74cd634"><code>6bb64b3ed</code></a> Thanks <a href="https://github.com/moklick"><code>@​moklick</code></a>! - Allow to start a selection above a node</p> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/xyflow/xyflow/blob/main/packages/react/CHANGELOG.md"><code>@​xyflow/react</code>'s changelog</a>.</em></p> <blockquote> <h2>12.10.0</h2> <h3>Minor Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5637">#5637</a> <a href="https://github.com/xyflow/xyflow/commit/0c7261a6dc94f1aa58333a6aebcaca8ced9b5ad2"><code>0c7261a6d</code></a> Thanks <a href="https://github.com/moklick"><code>@​moklick</code></a>! - Add <code>zIndexMode</code> to control how z-index is calculated for nodes and edges</p> </li> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5484">#5484</a> <a href="https://github.com/xyflow/xyflow/commit/a523919d6789995e9d0f3dd29b0b47fc3b8d8439"><code>a523919d6</code></a> Thanks <a href="https://github.com/peterkogo"><code>@​peterkogo</code></a>! - Add <code>experimental_useOnNodesChangeMiddleware</code> hook</p> </li> </ul> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5629">#5629</a> <a href="https://github.com/xyflow/xyflow/commit/9030fab2df8285fdfb649bda6e1e885dfd228d45"><code>9030fab2d</code></a> Thanks <a href="https://github.com/AlaricBaraou"><code>@​AlaricBaraou</code></a>! - Prevent unnecessary re-render in <code>FlowRenderer</code></p> </li> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5592">#5592</a> <a href="https://github.com/xyflow/xyflow/commit/38dbf41c464550cc803b946a4ad1f46982385a03"><code>38dbf41c4</code></a> Thanks <a href="https://github.com/svilen-ivanov-kubit"><code>@​svilen-ivanov-kubit</code></a>! - Always create a new measured object in apply changes.</p> </li> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5635">#5635</a> <a href="https://github.com/xyflow/xyflow/commit/2d7fa40e2684a0fcdd4eca7800ccf2c34338e549"><code>2d7fa40e2</code></a> Thanks <a href="https://github.com/tornado-softwares"><code>@​tornado-softwares</code></a>! - Update an ongoing connection when user moves node with keyboard.</p> </li> <li> <p>Updated dependencies [<a href="https://github.com/xyflow/xyflow/commit/0c7261a6dc94f1aa58333a6aebcaca8ced9b5ad2"><code>0c7261a6d</code></a>, <a href="https://github.com/xyflow/xyflow/commit/8598b6bc2a9d052b12d5215706382da0aa84827b"><code>8598b6bc2</code></a>, <a href="https://github.com/xyflow/xyflow/commit/2d7fa40e2684a0fcdd4eca7800ccf2c34338e549"><code>2d7fa40e2</code></a>]:</p> <ul> <li><code>@​xyflow/system</code><a href="https://github.com/0"><code>@​0</code></a>.0.74</li> </ul> </li> </ul> <h2>12.9.3</h2> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5621">#5621</a> <a href="https://github.com/xyflow/xyflow/commit/c1304dba7a20bb8d74c7aceb23cd80b56e4c0482"><code>c1304dba7</code></a> Thanks <a href="https://github.com/moklick"><code>@​moklick</code></a>! - Set <code>paneClickDistance</code> default value to <code>1</code>.</p> </li> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5578">#5578</a> <a href="https://github.com/xyflow/xyflow/commit/00bcb9f5f45f49814b9ac19b3f55cfe069ee3773"><code>00bcb9f5f</code></a> Thanks <a href="https://github.com/peterkogo"><code>@​peterkogo</code></a>! - Pass current pointer position to connection</p> </li> <li> <p>Updated dependencies [<a href="https://github.com/xyflow/xyflow/commit/00bcb9f5f45f49814b9ac19b3f55cfe069ee3773"><code>00bcb9f5f</code></a>]:</p> <ul> <li><code>@​xyflow/system</code><a href="https://github.com/0"><code>@​0</code></a>.0.73</li> </ul> </li> </ul> <h2>12.9.2</h2> <h3>Patch Changes</h3> <ul> <li><a href="https://redirect.github.com/xyflow/xyflow/pull/5593">#5593</a> <a href="https://github.com/xyflow/xyflow/commit/a8ee089d7689d9a58113690c8e90e1c1e109602a"><code>a8ee089d7</code></a> Thanks <a href="https://github.com/moklick"><code>@​moklick</code></a>! - Reset selection box when user selects a node</li> </ul> <h2>12.9.1</h2> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/xyflow/xyflow/pull/5572">#5572</a> <a href="https://github.com/xyflow/xyflow/commit/5ec0cac7fad21109b74839969c0818f88ddc87d9"><code>5ec0cac7f</code></a> Thanks <a href="https://github.com/peterkogo"><code>@​peterkogo</code></a>! - Fix onPaneClick events being suppressed when selectionOnDrag=true</p> </li> <li> <p>Updated dependencies [<a href="https://github.com/xyflow/xyflow/commit/5ec0cac7fad21109b74839969c0818f88ddc87d9"><code>5ec0cac7f</code></a>]:</p> <ul> <li><code>@​xyflow/system</code><a href="https://github.com/0"><code>@​0</code></a>.0.72</li> </ul> </li> </ul> <h2>12.9.0</h2> <h3>Minor Changes</h3> <ul> <li><a href="https://redirect.github.com/xyflow/xyflow/pull/5544">#5544</a> <a href="https://github.com/xyflow/xyflow/commit/c17b49f4c16167da3f791430163edd592159d27d"><code>c17b49f4c</code></a> Thanks <a href="https://github.com/0x0f0f0f"><code>@​0x0f0f0f</code></a>! - Add <code>EdgeToolbar</code> component</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/xyflow/xyflow/commit/c0ed3c33a3498877ab2a5755299ff84ee659782e"><code>c0ed3c3</code></a> chore(packages): bump</li> <li><a href="https://github.com/xyflow/xyflow/commit/83a312b2e1691a44223536653689f8f99f0d5b24"><code>83a312b</code></a> chore(zIndexMode): use basic as default</li> <li><a href="https://github.com/xyflow/xyflow/commit/14fd41b1f153406f1a21a61bf98ea07ad8275ec6"><code>14fd41b</code></a> change default back to elevateEdgesOnSelect=false and zIndexMode=basic</li> <li><a href="https://github.com/xyflow/xyflow/commit/3680a6a0e623e19d1f983515273f11bdd355ec86"><code>3680a6a</code></a> Merge branch 'main' into feat/zindexmode</li> <li><a href="https://github.com/xyflow/xyflow/commit/a523919d6789995e9d0f3dd29b0b47fc3b8d8439"><code>a523919</code></a> chore(middleware): cleanup</li> <li><a href="https://github.com/xyflow/xyflow/commit/e4e3605d62c8c710fe7ddb2ec3929af0a7962a6b"><code>e4e3605</code></a> Merge branch 'main' into middlewares</li> <li><a href="https://github.com/xyflow/xyflow/commit/2c05b3224a13e896dfb9a0c93f3af7bb592afc45"><code>2c05b32</code></a> Merge branch 'feat/zindexmode' of github.com:xyflow/xyflow into feat/zindexmode</li> <li><a href="https://github.com/xyflow/xyflow/commit/ddbb9280f6242794187205a207e993e2c721c244"><code>ddbb928</code></a> chore(examples): add zindexmode</li> <li><a href="https://github.com/xyflow/xyflow/commit/9faca3357d5db68fdad6c96de06fd66dd1d0ba64"><code>9faca33</code></a> Merge branch 'main' into feat/zindexmode</li> <li><a href="https://github.com/xyflow/xyflow/commit/4eb42952f01b947c9d36c25e6b30b7bd98224632"><code>4eb4295</code></a> feat(svelte): add zIndexMode</li> <li>Additional commits viewable in <a href="https://github.com/xyflow/xyflow/commits/@xyflow/[email protected]/packages/react">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@xyflow/react&package-manager=npm_and_yarn&previous-version=12.4.2&new-version=12.10.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump eslint-config-next from 14.2.33 to 14.2.35 (#18069) Bumps [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) from 14.2.33 to 14.2.35. <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vercel/next.js/commit/7b940d9ce96faddb9f92ff40f5e35c34ace04eb2"><code>7b940d9</code></a> v14.2.35</li> <li><a href="https://github.com/vercel/next.js/commit/f3073688ce18878a674fdb9954da68e9d626a930"><code>f307368</code></a> v14.2.34</li> <li>See full diff in <a href="https://github.com/vercel/next.js/commits/v14.2.35/packages/eslint-config-next">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=eslint-config-next&package-manager=npm_and_yarn&previous-version=14.2.33&new-version=14.2.35)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump @emotion/is-prop-valid from 1.3.0 to 1.4.0 (#18068) Bumps [@emotion/is-prop-valid](https://github.com/emotion-js/emotion) from 1.3.0 to 1.4.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/emotion-js/emotion/releases"><code>@​emotion/is-prop-valid</code>'s releases</a>.</em></p> <blockquote> <h2><code>@​emotion/is-prop-valid</code><a href="https://github.com/1"><code>@​1</code></a>.4.0</h2> <h3>Minor Changes</h3> <ul> <li><a href="https://redirect.github.com/emotion-js/emotion/pull/3306">#3306</a> <a href="https://github.com/emotion-js/emotion/commit/dfae1cbd98d3ebe449ce322b38cbf4a7fbfbfe96"><code>dfae1cb</code></a> Thanks <a href="https://github.com/EnzoAlbornoz"><code>@​EnzoAlbornoz</code></a>! - Adds <code>popover</code>, <code>popoverTarget</code> and <code>popoverTargetAction</code> to the list of allowed props.</li> </ul> <h2><code>@​emotion/is-prop-valid</code><a href="https://github.com/1"><code>@​1</code></a>.3.1</h2> <h3>Patch Changes</h3> <ul> <li><a href="https://redirect.github.com/emotion-js/emotion/pull/3093">#3093</a> <a href="https://github.com/emotion-js/emotion/commit/532ff57cafd8ba04f3b624074556ea47ec76fc9a"><code>532ff57</code></a> Thanks <a href="https://github.com/codejet"><code>@​codejet</code></a>, <a href="https://github.com/DustinBrett"><code>@​DustinBrett</code></a>! - Adds <code>fetchpriority</code> and <code>fetchPriority</code> to the list of allowed props.</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/emotion-js/emotion/commit/38db311adf024fe8a24b57c687824c47abbd0957"><code>38db311</code></a> Version Packages (<a href="https://redirect.github.com/emotion-js/emotion/issues/3347">#3347</a>)</li> <li><a href="https://github.com/emotion-js/emotion/commit/dfae1cbd98d3ebe449ce322b38cbf4a7fbfbfe96"><code>dfae1cb</code></a> Adds <code>popover</code>, <code>popoverTarget</code> and <code>popoverTargetAction</code> to the list of allo...</li> <li><a href="https://github.com/emotion-js/emotion/commit/49229553967b6050c92d9602eb577bdc48167e91"><code>4922955</code></a> Version Packages (<a href="https://redirect.github.com/emotion-js/emotion/issues/3335">#3335</a>)</li> <li><a href="https://github.com/emotion-js/emotion/commit/0facbe47bd9099ae4ed22dc201822d910ac3dec5"><code>0facbe4</code></a> Renamed default-exported variable in <code>@emotion/styled</code> to aid inferred import...</li> <li><a href="https://github.com/emotion-js/emotion/commit/cce67ec6b2fc94261028b4f4778aae8c3d6c5fd6"><code>cce67ec</code></a> Bump parcel (<a href="https://redirect.github.com/emotion-js/emotion/issues/3258">#3258</a>)</li> <li><a href="https://github.com/emotion-js/emotion/commit/3c19ce5997f73960679e546af47801205631dfde"><code>3c19ce5</code></a> Version Packages (<a href="https://redirect.github.com/emotion-js/emotion/issues/3280">#3280</a>)</li> <li><a href="https://github.com/emotion-js/emotion/commit/a19d019bd418ebc3b9cba0e58f58b36ac2862a42"><code>a19d019</code></a> Convert <code>@emotion/styled</code>'s source code to TypeScript (<a href="https://redirect.github.com/emotion-js/emotion/issues/3284">#3284</a>)</li> <li><a href="https://github.com/emotion-js/emotion/commit/5974e33fcb5e7aee177408684ac6fe8b38b3e353"><code>5974e33</code></a> Fix JSX namespace <a href="https://github.com/ts-ignores"><code>@​ts-ignores</code></a> (<a href="https://redirect.github.com/emotion-js/emotion/issues/3282">#3282</a>)</li> <li><a href="https://github.com/emotion-js/emotion/commit/fc4d7bd744c205f55513dcd4e4e5134198c219de"><code>fc4d7bd</code></a> Convert <code>@emotion/react</code>'s source code to TypeScript (<a href="https://redirect.github.com/emotion-js/emotion/issues/3281">#3281</a>)</li> <li><a href="https://github.com/emotion-js/emotion/commit/8dc1a6dd19d2dc9ce435ef0aff85ccf5647f5d2e"><code>8dc1a6d</code></a> Convert <code>@emotion/cache</code>'s source code to TypeScript (<a href="https://redirect.github.com/emotion-js/emotion/issues/3277">#3277</a>)</li> <li>Additional commits viewable in <a href="https://github.com/emotion-js/emotion/compare/@emotion/[email protected]...@emotion/[email protected]">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@emotion/is-prop-valid&package-manager=npm_and_yarn&previous-version=1.3.0&new-version=1.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * FILES field - Attachment name display fix (#18073) with new 'file' FILES field on attachment, UI should display attachment name from file field value. Issue with API users updating only 'file' FILES field (and not name field anymore) * Add objectRecordCounts query to /metadata endpoint (#18054) ## Summary - Adds an `objectRecordCounts` query on the `/metadata` GraphQL endpoint that returns approximate record counts for all objects in the workspace - Uses PostgreSQL's `pg_class.reltuples` catalog stats — a single instant query instead of N `COUNT(*)` table scans - Replaces the previous `CombinedFindManyRecords` approach which hit the server's 20 root resolver limit and silently showed 0 for all counts on the settings Data Model page ### Server - `ObjectRecordCountDTO` — GraphQL type with `objectNamePlural` and `totalCount` - `ObjectRecordCountService` — reads `pg_class` catalog for the workspace schema - Query added to `ObjectMetadataResolver` with `@MetadataResolver()` + `NoPermissionGuard` ### Frontend - `OBJECT_RECORD_COUNTS` query added to `object-metadata/graphql/queries.ts` - `useCombinedGetTotalCount` simplified to a zero-argument hook using the new query - `SettingsObjectTable` simplified to a single hook call --------- Co-authored-by: Cursor <[email protected]> * Refactor and standardize `isSystem` field and object (#17992) # Introduction ## Centralize system field definitions - Extract a single `PARTIAL_SYSTEM_FLAT_FIELD_METADATAS` constant as the source of truth for all 8 system fields (`id`, `createdAt`, `updatedAt`, `deletedAt`, `createdBy`, `updatedBy`, `position`, `searchVector`), eliminating duplication across custom object and standard app field builders - Refactor `buildDefaultFlatFieldMetadatasForCustomObject` to use the shared constant via a new `buildObjectSystemFlatFieldMetadatas` helper ## Mark system fields as `isSystem: true` - Fields `id`, `createdAt`, `updatedAt`, `deletedAt`, `createdBy`, `updatedBy`, `position`, `searchVector` are now properly flagged as system fields across all standard objects and custom object creation - Standard app field builders for all ~30 standard objects updated to set `isSystem: true` on `createdAt`, `updatedAt`, `deletedAt`, `createdBy`, `updatedBy` - System-only standard objects (blocklist, calendar channels, message threads, etc.) now also include `createdBy`, `updatedBy`, `position`, `searchVector` field definitions that were previously missing ## Validate system fields on object creation - New transversal validation (`crossEntityTransversalValidation`) runs after all atomic entity validations in the build orchestrator, ensuring all 8 system fields are present with correct `type` and `isSystem: true` when an object is created - New `buildUniversalFlatObjectFieldByNameAndJoinColumnMaps` utility to resolve field names to universal identifiers for a given object - New exception codes: `MISSING_SYSTEM_FIELD` and `INVALID_SYSTEM_FIELD` on `ObjectMetadataExceptionCode` ## Protect system fields and objects from mutation - Field validators now block update/delete of `isSystem` fields by non-system callers (`FIELD_MUTATION_NOT_ALLOWED`) - Object validators now block update/delete of `isSystem` objects by non-system callers - `POSITION` and `TS_VECTOR` field type validators replaced: instead of rejecting creation outright, they now validate that the field is named correctly (`position` / `searchVector`) and has `isSystem: true` ## Distinguish `isSystemBuild` from `isCallerTwentyStandardApp` - New `isCallerTwentyStandardApp` utility checks whether the caller's `applicationUniversalIdentifier` matches the twenty standard app - Name-sync logic (`isFlatFieldMetadataNameSyncedWithLabel`, `areFlatObjectMetadataNamesSyncedWithLabels`) refactored to use `isCallerTwentyStandardApp` for custom suffix decisions, keeping `isSystemBuild` for mutation permission checks - `WorkspaceMigrationBuilderOptions` type updated to include `applicationUniversalIdentifier` ## Adapt frontend filtering - New `HIDDEN_SYSTEM_FIELD_NAMES` constant (`id`, `position`, `searchVector`) and `isHiddenSystemField` utility to only hide truly internal fields while keeping user-facing system fields (`createdAt`, `updatedAt`, `deletedAt`, `createdBy`, `updatedBy`) visible in the UI - ~20 frontend files updated to replace `!field.isSystem` checks with `!isHiddenSystemField(field)` across record index, settings, data model, charts, workflows, spreadsheet import, aggregations, and role permissions ## Add 1.19 upgrade commands - **`backfill-system-fields-is-system`**: Raw SQL command to set `isSystem = true` on existing workspace fields matching system field names, and fix `position` field type from `NUMBER` to `POSITION` for `favorite`/`favoriteFolder` objects. Includes proper cache invalidation. - **`add-missing-system-fields-to-standard-objects`**: Codegen'd workspace migration to create missing `position`, `searchVector`, `createdBy`, `updatedBy` fields on standard objects that didn't previously have them. Runs via `WorkspaceMigrationRunnerService` in a single transaction with idempotency check. **Known limitation**: assumes all standard objects exist and are valid in the target workspace. ## Add `universalIdentifier` for system fields in standard object constants - `standard-object.constant.ts` updated to include `universalIdentifier` for `createdBy`, `updatedBy`, `position`, and `searchVector` across all standard objects - `fieldManifestType.ts` updated to support the new field manifest shape ## System relation Completely removed and backfilled all `isSystem` relation to be false false As we won't require an object to have any relation system fields ## Add integration tests - New test suite `failing-sync-application-object-system-fields` covering: missing system fields, wrong field types (`id` as TEXT, `createdAt` as TEXT, `position` as TEXT), system field deletion attempts, and system field update attempts - New test utilities: `buildDefaultObjectManifest` (builds an object manifest with all 8 system fields) and `setupApplicationForSync` (centralizes application setup) - Existing successful sync test updated to verify system fields are created with correct properties ## Next step Make the builder scope the compared entity to be the currently built app + nor twenty standard app * i18n - translations (#18079) Created by Github action --------- Co-authored-by: github-actions <[email protected]> * fix: remove the error message for test failure in ci-front (#18076) Introduced an error message on twenty-front CI earlier to try and inform the user that test failure could be a coverage issue if no individual test was failing. However, it led to the assumption that it must be coverage failure in all cases even when it was test failure leading to the CI being red. This PR reverts the change. * Keep migrating to jotai (#18064) And we continue! * Remove non positive integer constraint on Nav Menu Item (#18081) To fit with position typed field logic + Ease favorite to nav menu item migration (which have negative and float position) * i18n - translations (#18086) Created by Github action --------- Co-authored-by: github-actions <[email protected]> * Refactor message backfill command (#18078) # Introduction Atomically create the field and object to be created And avoid synchronizing unrelated non up to date object and fields Followup https://github.com/twentyhq/twenty/pull/17398 * Migrate more to Jotai (#18087) Continue jotai migration * Factorize and add public-assets/*path endpoint (#18080) as title * Twenty standard app static options id (#18089) # Introduction While preparing the twenty-standard as code migration to twenty-app through sdk I've faced permanent field enum update as the id was generated dynamically at each twenty standard app construction Making them deterministic in order to avoid having this noise Won't backfill this on existing workspace as it's not critical and that we will rework the options in the future * Create LLMS.md on create-twenty-app (#18091) Managed to create a many to many app with minimal instructions. File will need to be enriched with more pitfalls. --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Fix google compose scope not gated by feature flag (#18093) ## Context New google api scope has been introduced in https://github.com/twentyhq/twenty/pull/17793 without being gated behind a feature flag Microsoft is using pre-existing Mail.ReadWrite scope there is nothing to gate ## Before <img width="553" height="445" alt="Screenshot 2026-02-19 at 14 57 58" src="https://github.com/user-attachments/assets/59a4f76b-d38d-492f-b013-b6cad4091a7f" /> ## After <img width="535" height="392" alt="Screenshot 2026-02-19 at 14 58 44" src="https://github.com/user-attachments/assets/0337bf15-ec30-4549-bb9d-571a982dffd8" /> * Remove non positive integer constraint on Nav Menu Item 2/2 (#18090) Follow up https://github.com/twentyhq/twenty/pull/18081 * Resolve lead source from list_id via Convoso Lists API When source_name is missing from the call payload (common with Convoso Call Log API data), fall back to resolving the list_id to a list name via the Convoso Lists API. The list map is cached in-memory for 10 minutes. The resolved name is used for lead source creation, call name computation, and billing matching. Co-Authored-By: Claude Opus 4.6 <[email protected]> * [FRONT COMPONENTS] Declare command menu items in front components (#18047) ## Description - Adds support for declaring command menu items directly within `defineFrontComponent` via an optional command config property - Introduces a new `CommandMenuItemManifest` type in twenty-shared and wires it through the manifest build pipeline ## Example Of usage ```tsx import { defineFrontComponent } from "twenty-sdk"; const TestAction = () => { return <div>Test Action</div>; }; export default defineFrontComponent({ universalIdentifier: "6c289461-0007-4a62-a99f-69e5c11a4ce7", name: "test-action", description: "Test Action", component: TestAction, command: { universalIdentifier: "c07df864-495f-46f3-9f5b-9d3ce2589e9b", label: "Run My Action", icon: "IconBolt", isPinned: false, }, }); ``` ## Video QA https://github.com/user-attachments/assets/f910fc6a-44a9-45d1-87c5-f0ce64bb3878 * Fix: add a new style to the target text box (#18065) ### Approach I add some new rules for the style of the target text box. (Fix: #13229 ) <img width="842" height="545" alt="target class" src="https://github.com/user-attachments/assets/7cd0a615-392a-493b-831f-77ddb93de5fc" /> **This is what it looks like now.** <img width="320" height="224" alt="image" src="https://github.com/user-attachments/assets/26514102-e684-49ce-915d-43e5677520a5" /> * Add CONVOSO_API_TOKEN to Helm staging values and worker extraEnv support Adds extraEnv iteration to the worker deployment template (matching the existing server template pattern) and configures CONVOSO_API_TOKEN on both server and worker for the staging environment. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Use K8s secret for CONVOSO_API_TOKEN instead of hardcoded value Adds extraEnvSecrets support to both server and worker Helm templates, allowing env vars to be sourced from Kubernetes secrets via secretKeyRef. The Convoso API token is now stored in a convoso-credentials secret rather than being hardcoded in the values file. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Add showInSidebar per-role permission to replace hardcoded sidebar filter Adds a new `showInSidebar` boolean on ObjectPermission and a global `showAllObjectsInSidebar` toggle on Role, following the same pattern as canReadObjectRecords/canUpdateObjectRecords. The sidebar now filters items based on this permission instead of the hardcoded MEMBER_VISIBLE_OBJECTS set. Co-Authored-By: Claude Opus 4.6 <[email protected]> * Switch Convoso call pipeline to pull mode with date range params and preprocessor Convoso Connect webhooks send lead data regardless of event type, so the push pipeline doesn't receive call records. This switches to polling the Convoso Call Log API (/v1/log/retrieve) on a cron schedule, matching the old Cloudflare Worker approach. - Add dateRangeParams to SourceRequestConfig for dynamic time-window queries - Add envVar support to QueryParamAuthConfig for runtime env-based auth tokens - Wire preprocessor + workspace context into IngestionPullJob (same as push job) - Include SQL script to update pipeline config in staging DB Co-Authored-By: Claude Opus 4.6 <[email protected]> * chore: upgrade @swc/core to 1.15.11 and align SWC ecosystem (#18088) ## Summary - Upgrades `@swc/core` from 1.13.3 to **1.15.11** (swc_core v56), which introduces CBOR-based plugin serialization replacing rkyv, eliminating strict version-matching between SWC core and Wasm plugins - Upgrades `@lingui/swc-plugin` from ^5.6.0 to **^5.11.0** (swc_core 50.2.3, built with `--cfg=swc_ast_unknown` for cross-version compatibility) - Upgrades `@swc/plugin-emotion` from 10.0.4 to **14.6.0** (swc_core 53, also with backward-compat feature) - Upgrades companion packages: `@swc-node/register` 1.8.0 → 1.11.1, `@swc/helpers` ~0.5.2 → ~0.5.18, `@vitejs/plugin-react-swc` 3.11.0 → 4.2.3 ### Why this is safe now Starting from `@swc/core v1.15.0`, SWC replaced the rkyv serialization scheme with CBOR (a self-describing format) and added `Unknown` AST enum variants. Plugins built with `swc_core >= 47` and `--cfg=swc_ast_unkn…
1 parent 87ff1d3 commit 233af4e

File tree

205 files changed

+24382
-116
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

205 files changed

+24382
-116
lines changed

.github/workflows/deploy-staging.yaml

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,46 @@ jobs:
4747
- name: Checkout code
4848
uses: actions/checkout@v4
4949

50+
- name: Setup Node.js
51+
uses: actions/setup-node@v4
52+
with:
53+
node-version: '24'
54+
55+
- name: Cache dependencies and Nx build cache
56+
uses: actions/cache@v4
57+
with:
58+
path: |
59+
node_modules
60+
packages/*/node_modules
61+
.yarn/cache
62+
.nx/cache
63+
key: build-${{ hashFiles('yarn.lock') }}-${{ github.sha }}
64+
restore-keys: |
65+
build-${{ hashFiles('yarn.lock') }}-
66+
build-
67+
68+
- name: Install dependencies
69+
run: yarn install --immutable
70+
71+
- name: Build all packages
72+
run: npx nx run-many --target=build --projects=twenty-server,twenty-front --parallel=2
73+
env:
74+
VITE_BUILD_SOURCEMAP: 'true'
75+
VITE_DISABLE_TYPESCRIPT_CHECKER: 'true'
76+
77+
- name: Upload Sentry sourcemaps (server)
78+
if: ${{ env.SENTRY_AUTH_TOKEN != '' }}
79+
run: |
80+
npx sentry-cli sourcemaps upload \
81+
--auth-token "$SENTRY_AUTH_TOKEN" \
82+
--org omnia-insurance \
83+
--project crm-server \
84+
--release "${{ github.sha }}" \
85+
./packages/twenty-server/dist
86+
find ./packages/twenty-server/dist -name '*.js.map' -delete
87+
env:
88+
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
89+
5090
- name: Configure AWS credentials
5191
uses: aws-actions/configure-aws-credentials@v4
5292
with:
@@ -74,16 +114,14 @@ jobs:
74114
uses: docker/build-push-action@v6
75115
with:
76116
context: .
77-
file: packages/twenty-docker/twenty/Dockerfile
117+
file: packages/twenty-docker/twenty/Dockerfile.ci
78118
push: true
79119
tags: ${{ steps.meta.outputs.tags }}
80120
labels: ${{ steps.meta.outputs.labels }}
81121
cache-from: type=gha
82122
cache-to: type=gha,mode=max
83123
build-args: |
84124
REACT_APP_SERVER_BASE_URL=/api
85-
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
86-
SENTRY_RELEASE=${{ github.sha }}
87125
88126
replicate-db:
89127
name: Replicate Production DB to Staging
@@ -142,12 +180,17 @@ jobs:
142180
- name: Ensure staging namespace exists
143181
run: kubectl create namespace ${{ env.NAMESPACE }} --dry-run=client -o yaml | kubectl apply -f -
144182

145-
- name: Copy S3 secret from prod namespace
183+
- name: Copy secrets from prod namespace
146184
run: |
185+
# S3 credentials - only copy if missing
147186
kubectl get secret twenty-s3-credentials -n ${{ env.NAMESPACE }} 2>/dev/null || \
148187
kubectl get secret twenty-s3-credentials -n ${{ env.PROD_NAMESPACE }} -o yaml | \
149188
sed 's/namespace: ${{ env.PROD_NAMESPACE }}$/namespace: ${{ env.NAMESPACE }}/' | \
150189
kubectl apply -f -
190+
# Tokens (APP_SECRET) - sync from prod so encrypted DB config can be decrypted
191+
PROD_TOKEN=$(kubectl get secret tokens -n ${{ env.PROD_NAMESPACE }} -o jsonpath='{.data.accessToken}')
192+
kubectl patch secret tokens -n ${{ env.NAMESPACE }} -p "{\"data\":{\"accessToken\":\"$PROD_TOKEN\"}}" 2>/dev/null || \
193+
kubectl create secret generic tokens -n ${{ env.NAMESPACE }} --from-literal=accessToken="$(echo $PROD_TOKEN | base64 -d)"
151194
152195
- name: Determine image tag
153196
id: image-tag
@@ -177,8 +220,7 @@ jobs:
177220
--set worker.image.repository=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }} \
178221
--set worker.image.tag=${{ steps.image-tag.outputs.tag }} \
179222
--wait \
180-
--cleanup-on-fail \
181-
--timeout 10m
223+
--timeout 15m
182224
183225
- name: Verify deployment
184226
run: |

.github/workflows/scripts/replicate-db-to-staging.sh

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,27 +49,36 @@ kubectl exec -n "$STAGING_NS" "$STAGING_POD" -- \
4949
kubectl exec -n "$STAGING_NS" "$STAGING_POD" -- \
5050
psql -U postgres -c "CREATE DATABASE $DB_NAME;"
5151

52-
echo "==> Restoring dump into staging..."
53-
kubectl exec -i -n "$STAGING_NS" "$STAGING_POD" -- \
54-
psql -U postgres -d "$DB_NAME" < "$DUMP_FILE"
52+
echo "==> Restoring dump into staging (triggers disabled to avoid FK ordering issues)..."
53+
{ echo "SET session_replication_role = 'replica';"; cat "$DUMP_FILE"; echo "SET session_replication_role = 'origin';"; } | \
54+
kubectl exec -i -n "$STAGING_NS" "$STAGING_POD" -- \
55+
psql -U postgres -d "$DB_NAME"
5556

5657
echo "==> Anonymizing staging data..."
5758
kubectl exec -n "$STAGING_NS" "$STAGING_POD" -- \
5859
psql -U postgres -d "$DB_NAME" -c "
59-
-- Null out password hashes
60+
CREATE EXTENSION IF NOT EXISTS pgcrypto;
61+
62+
-- Null out password hashes (force Google SSO on staging)
6063
UPDATE core.\"user\" SET \"passwordHash\" = NULL;
6164
62-
-- Scramble email addresses
63-
UPDATE core.\"user\"
64-
SET email = 'staging-user-' || id || '@example.com';
65+
-- Keep real emails so Google OAuth works on staging
66+
-- (same team, private environment)
6567
66-
-- Delete refresh tokens
67-
DELETE FROM core.\"refreshToken\";
68+
-- Delete refresh tokens (stored in appToken table with type)
69+
DELETE FROM core.\"appToken\" WHERE type = 'REFRESH_TOKEN';
6870
69-
-- Regenerate app tokens
71+
-- Regenerate remaining app tokens
7072
UPDATE core.\"appToken\"
7173
SET value = encode(gen_random_bytes(32), 'hex'),
7274
\"expiresAt\" = NOW() + INTERVAL '30 days';
75+
76+
-- Rewrite config URLs from prod domain to staging domain
77+
-- Config is stored in keyValuePair table as jsonb
78+
UPDATE core.\"keyValuePair\"
79+
SET value = REPLACE(value::text, 'crm.omniaagent.com', 'staging-crm.omniaagent.com')::jsonb
80+
WHERE type = 'CONFIG_VARIABLE'
81+
AND value::text LIKE '%crm.omniaagent.com%';
7382
"
7483

7584
echo "==> Granting permissions to twenty_app_user..."

packages/twenty-docker/helm/twenty/omnia-staging-values.yaml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ server:
1414
SENTRY_FRONT_DSN: https://660cb58838f1dbf2ee91c1290136056e@o4510840638930944.ingest.us.sentry.io/4510840650989568
1515
NODE_OPTIONS: "--max-old-space-size=1536"
1616
SIGN_IN_PREFILLED: "true"
17+
extraEnvSecrets:
18+
CONVOSO_API_TOKEN:
19+
secretName: convoso-credentials
20+
key: apiToken
1721
resources:
1822
requests:
1923
cpu: 100m
@@ -43,13 +47,17 @@ worker:
4347
image:
4448
repository: 189365142140.dkr.ecr.us-east-1.amazonaws.com/twenty-crm
4549
tag: staging-latest
50+
extraEnvSecrets:
51+
CONVOSO_API_TOKEN:
52+
secretName: convoso-credentials
53+
key: apiToken
4654
resources:
4755
requests:
4856
cpu: 100m
4957
memory: 256Mi
5058
limits:
5159
cpu: 500m
52-
memory: 512Mi
60+
memory: 1024Mi
5361

5462
db:
5563
internal:
@@ -78,6 +86,11 @@ storage:
7886
accessKeyIdKey: accessKeyId
7987
secretAccessKeyKey: secretAccessKey
8088

89+
secrets:
90+
tokens:
91+
create: true
92+
name: tokens
93+
8194
redisInternal:
8295
resources:
8396
requests:

packages/twenty-docker/helm/twenty/templates/deployment-server.yaml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ spec:
100100
psql -h ${DB_HOST} -p 5432 -U postgres -d ${DBNAME} -c "ALTER DEFAULT PRIVILEGES IN SCHEMA core GRANT ALL ON SEQUENCES TO ${APP_USER};"
101101
psql -h ${DB_HOST} -p 5432 -U postgres -d ${DBNAME} -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO ${APP_USER};"
102102
psql -h ${DB_HOST} -p 5432 -U postgres -d ${DBNAME} -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO ${APP_USER};"
103+
echo "Granting permissions on workspace schemas..."
104+
psql -h ${DB_HOST} -p 5432 -U postgres -d ${DBNAME} -c "DO \$\$ DECLARE ws RECORD; BEGIN FOR ws IN SELECT nspname FROM pg_namespace WHERE nspname LIKE 'workspace_%' LOOP EXECUTE format('GRANT ALL PRIVILEGES ON SCHEMA %I TO ${APP_USER}', ws.nspname); EXECUTE format('GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA %I TO ${APP_USER}', ws.nspname); EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON TABLES TO ${APP_USER}', ws.nspname); EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON SEQUENCES TO ${APP_USER}', ws.nspname); END LOOP; END \$\$;"
105+
echo "Transferring workspace table ownership to ${APP_USER}..."
106+
psql -h ${DB_HOST} -p 5432 -U postgres -d ${DBNAME} -c "DO \$\$ DECLARE r RECORD; BEGIN FOR r IN SELECT schemaname, tablename FROM pg_tables WHERE schemaname LIKE 'workspace_%' AND tableowner != '${APP_USER}' LOOP EXECUTE format('ALTER TABLE %I.%I OWNER TO ${APP_USER}', r.schemaname, r.tablename); END LOOP; END \$\$;"
103107
echo "Database ${DBNAME} is ready."
104108
{{- end }}
105109
- name: run-migrations
@@ -112,7 +116,15 @@ spec:
112116
- >-
113117
npx -y typeorm migration:run -d dist/database/typeorm/core/core.datasource
114118
env:
115-
{{- if eq (include "twenty.db.useExternalSecret" .) "true" }}
119+
{{- if .Values.db.enabled }}
120+
- name: PGPASSWORD
121+
valueFrom:
122+
secretKeyRef:
123+
name: {{ include "twenty.fullname" . }}-db-superuser
124+
key: password
125+
- name: PG_DATABASE_URL
126+
value: "postgres://postgres:$(PGPASSWORD)@{{ include "twenty.fullname" . }}-db.{{ include "twenty.namespace" . }}.svc.cluster.local/{{ .Values.db.internal.database | default "twenty" }}"
127+
{{- else if eq (include "twenty.db.useExternalSecret" .) "true" }}
116128
- name: DB_PASSWORD
117129
valueFrom:
118130
secretKeyRef:
@@ -173,6 +185,13 @@ spec:
173185
- name: {{ $key }}
174186
value: {{ $value | quote }}
175187
{{- end }}
188+
{{- range $key, $ref := .Values.server.extraEnvSecrets }}
189+
- name: {{ $key }}
190+
valueFrom:
191+
secretKeyRef:
192+
name: {{ $ref.secretName }}
193+
key: {{ $ref.key }}
194+
{{- end }}
176195
lifecycle:
177196
preStop:
178197
exec:

packages/twenty-docker/helm/twenty/templates/deployment-worker.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ spec:
7777
{{- if $storageEnv }}
7878
{{ $storageEnv | nindent 12 }}
7979
{{- end }}
80+
{{- range $key, $value := .Values.worker.extraEnv }}
81+
- name: {{ $key }}
82+
value: {{ $value | quote }}
83+
{{- end }}
84+
{{- range $key, $ref := .Values.worker.extraEnvSecrets }}
85+
- name: {{ $key }}
86+
valueFrom:
87+
secretKeyRef:
88+
name: {{ $ref.secretName }}
89+
key: {{ $ref.key }}
90+
{{- end }}
8091
resources:
8192
{{- toYaml .Values.worker.resources | nindent 12 }}
8293
stdin: {{ default true .Values.worker.stdin }}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Slim CI Dockerfile — no compilation, only packaging.
2+
# Builds happen on the GHA host where Nx cache persists across runs.
3+
4+
# Stage 1: Production dependencies (cached when yarn.lock unchanged)
5+
FROM node:24-alpine AS deps
6+
7+
WORKDIR /app
8+
9+
COPY ./package.json ./yarn.lock ./.yarnrc.yml ./tsconfig.base.json ./nx.json /app/
10+
COPY ./.yarn/releases /app/.yarn/releases
11+
COPY ./.yarn/patches /app/.yarn/patches
12+
13+
COPY ./packages/twenty-emails/package.json /app/packages/twenty-emails/
14+
COPY ./packages/twenty-server/package.json /app/packages/twenty-server/
15+
COPY ./packages/twenty-server/patches /app/packages/twenty-server/patches
16+
COPY ./packages/twenty-ui/package.json /app/packages/twenty-ui/
17+
COPY ./packages/twenty-shared/package.json /app/packages/twenty-shared/
18+
COPY ./packages/twenty-front/package.json /app/packages/twenty-front/
19+
COPY ./packages/twenty-sdk/package.json /app/packages/twenty-sdk/
20+
21+
RUN yarn workspaces focus --production twenty-emails twenty-shared twenty-server && yarn cache clean
22+
23+
# Stage 2: Final image
24+
FROM node:24-alpine
25+
26+
RUN apk add --no-cache curl jq postgresql-client
27+
RUN npm install -g tsx
28+
29+
COPY ./packages/twenty-docker/twenty/entrypoint.sh /app/entrypoint.sh
30+
RUN chmod +x /app/entrypoint.sh
31+
32+
WORKDIR /app/packages/twenty-server
33+
34+
ARG REACT_APP_SERVER_BASE_URL
35+
ENV REACT_APP_SERVER_BASE_URL=$REACT_APP_SERVER_BASE_URL
36+
37+
ARG APP_VERSION
38+
ENV APP_VERSION=$APP_VERSION
39+
40+
# Copy production node_modules from deps stage
41+
COPY --chown=1000 --from=deps /app /app
42+
43+
# Copy pre-built artifacts from host (via build context)
44+
COPY --chown=1000 ./packages/twenty-server/dist /app/packages/twenty-server/dist
45+
COPY --chown=1000 ./packages/twenty-shared/dist /app/packages/twenty-shared/dist
46+
COPY --chown=1000 ./packages/twenty-emails/dist /app/packages/twenty-emails/dist
47+
COPY --chown=1000 ./packages/twenty-front/build /app/packages/twenty-server/dist/front
48+
49+
LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty
50+
51+
RUN mkdir -p /app/.local-storage /app/packages/twenty-server/.local-storage && \
52+
chown -R 1000:1000 /app
53+
54+
USER 1000
55+
56+
CMD ["node", "dist/main"]
57+
ENTRYPOINT ["/app/entrypoint.sh"]

0 commit comments

Comments
 (0)