Conversation
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 <noreply@anthropic.com>
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 <noreply@anthropic.com>
… table name Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes twentyhq#17411 --------- Co-authored-by: neo773 <neo773@protonmail.com> Co-authored-by: neo773 <62795688+neo773@users.noreply.github.com> Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Created by Github action --------- Co-authored-by: github-actions <github-actions@twenty.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Created by Github action Co-authored-by: github-actions <github-actions@twenty.com>
- 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
Fixes twentyhq#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>
…Identifiers to update and restore (twentyhq#18015) closes twentyhq/private-issues#419
## 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"
/>
as title
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
## 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" />
Created by Github action --------- Co-authored-by: github-actions <github-actions@twenty.com>
Same as here twentyhq#18016
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.
Fixes: twentyhq/core-team-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 <arunkumar@Aruns-MacBook-Air.local> Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
…ls (twentyhq#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 twentyhq#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 <cursoragent@cursor.com>
…wentyhq#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 <cursoragent@cursor.com>
- 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
… operand filters (twentyhq#17564) migration command in response to the fix : twentyhq#17529 for the issue twentyhq/core-team-issues#2027 --------- Co-authored-by: Arun kumar <arunkumar@Aruns-MacBook-Air.local> Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n in application (twentyhq#18037) - add a new optional key `postInstallLogicFunctionUniversalIdentifier` in applicationConfig - seed postInstall function in create-twenty-app - update execute:function options - update doc
… secret Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…m conflicts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The wyw plugin has an explicit file allowlist — AudioLink was missing, causing styled.div to be undefined at runtime on staging. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts: # packages/twenty-front/src/locales/generated/af-ZA.ts # packages/twenty-front/src/locales/generated/ar-SA.ts # packages/twenty-front/src/locales/generated/ca-ES.ts # packages/twenty-front/src/locales/generated/cs-CZ.ts # packages/twenty-front/src/locales/generated/da-DK.ts # packages/twenty-front/src/locales/generated/de-DE.ts # packages/twenty-front/src/locales/generated/el-GR.ts # packages/twenty-front/src/locales/generated/en.ts # packages/twenty-front/src/locales/generated/es-ES.ts # packages/twenty-front/src/locales/generated/fi-FI.ts # packages/twenty-front/src/locales/generated/fr-FR.ts # packages/twenty-front/src/locales/generated/he-IL.ts # packages/twenty-front/src/locales/generated/hu-HU.ts # packages/twenty-front/src/locales/generated/it-IT.ts # packages/twenty-front/src/locales/generated/ja-JP.ts # packages/twenty-front/src/locales/generated/ko-KR.ts # packages/twenty-front/src/locales/generated/nl-NL.ts # packages/twenty-front/src/locales/generated/no-NO.ts # packages/twenty-front/src/locales/generated/pl-PL.ts # packages/twenty-front/src/locales/generated/pseudo-en.ts # packages/twenty-front/src/locales/generated/pt-BR.ts # packages/twenty-front/src/locales/generated/pt-PT.ts # packages/twenty-front/src/locales/generated/ro-RO.ts # packages/twenty-front/src/locales/generated/ru-RU.ts # packages/twenty-front/src/locales/generated/sr-Cyrl.ts # packages/twenty-front/src/locales/generated/sv-SE.ts # packages/twenty-front/src/locales/generated/tr-TR.ts # packages/twenty-front/src/locales/generated/uk-UA.ts # packages/twenty-front/src/locales/generated/vi-VN.ts # packages/twenty-front/src/locales/generated/zh-CN.ts # packages/twenty-front/src/locales/generated/zh-TW.ts # packages/twenty-front/src/locales/ru-RU.po
Stamps the CarrierProduct commission value onto each Policy as a frozen LTV snapshot at creation time. Existing policies keep their original LTV when commission rates change — only future policies get the new value. - Migration adds ltvAmountMicros/ltvCurrencyCode columns and CURRENCY field metadata - Pipeline field mappings added for both HealthSherpa and Old CRM pipelines - Both preprocessors look up CarrierProduct commission and inject _ltv* fields - Pre-query hooks auto-fill LTV on manual/UI policy creation - Date-aware backfill script for existing policies (scripts/backfill-policy-ltv.ts) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…arrier-product Add LTV field to Policy from CarrierProduct commission
All staging pods were stuck Pending because the staging node has an
{environment: staging} taint but no pods tolerated it. Adds global
tolerations support to all 4 deployment templates and configures
the staging values with the required toleration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…arrier-product Fix staging deploy: add tolerations for node taint
- Add policy.updateOne and policy.updateMany pre-query hooks that auto-derive LTV from CarrierProduct commission when carrier or product changes on a policy - Fix RecordInlineCell: replace unused useRecoilCallback import with useStore from jotai (was causing ReferenceError on every inline cell) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the partially-reverted Jotai migration artifacts with the known-good versions from main. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ustomizations Uses the clean Jotai-migrated versions from upstream (useStore from jotai, useRecoilComponentFamilyValueV2, isSelectedItemIdComponentFamilyState) with our additions (FieldDependencyContext cascade clear, ONE_TO_MANY sub-menu filter check). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ing record When the UI sends only carrierId or only productId in an updateOne payload, the hook now fetches the existing policy record (bypassing permission checks) to get the other ID before looking up the CarrierProduct commission. This ensures LTV is stamped even when fields are set one at a time or hidden from agents. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tate selectedItemIdComponentState was migrated to createComponentStateV2 but this file still used useRecoilComponentValue (Recoil). Switch to useRecoilComponentValueV2 to match. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tate selectedItemIdComponentState was migrated to createComponentStateV2 but this file used useRecoilComponentValue. Added useRecoilComponentValueV2 for the V2 state while keeping useRecoilComponentValue for the old-style selectors still in use. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…in workspace context The workspace ORM returns CURRENCY fields as nested objects (e.g. commission.amountMicros) not flat columns (commissionAmountMicros). Also wraps all policy pre-query hook ORM calls in executeInWorkspaceContext. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-query hooks modify the user's mutation payload, which fails when the user's role doesn't have permission to the LTV field. Post-query hooks run after the mutation succeeds and do a separate bypassed-permissions update to stamp LTV, so it works regardless of role field settings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The workspace repository.update() goes through formatData which expects composite CURRENCY fields as nested objects (ltv.amountMicros), not flat column names (ltvAmountMicros). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ezone
- Post-query hooks now derive policy name as "{Carrier} - {Product}"
using the same pattern as ingestion, with bypassed permissions
- Restore submittedDate auto-set on policy creation (accidentally dropped
during LTV migration) using the workspace member's configured timezone
- Falls back to America/New_York when timezone is 'system' or unset
- Rename stamp-policy-ltv to enrich-policy-after-save (handles both
name and LTV in a single update)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Name was previously derived in post-query hooks, causing stale values in the UI (one step behind). Moving to pre-query hooks ensures the name is set before the mutation, so the GraphQL response includes it. - Add name derivation to create-one and create-many pre-query hooks - Create update-one pre-query hook (fetches existing record for missing field) - Create update-many pre-query hook - Extract buildPolicyDisplayName into shared utility - Simplify enrich-policy-after-save to LTV-only Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-query hooks were adding submittedDate and agentId to the mutation payload, which fails field-level permission checks when the member role doesn't have write access to those fields. Moved submittedDate and agentId auto-setting to post-query hooks where they use bypassed permissions (same pattern as LTV). Pre-query hooks now only handle name derivation from carrier + product. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The ErrorBoundary in WidgetRenderer was silently catching errors and showing "Invalid Configuration" without any telemetry. This adds an onError callback that logs to console and sends to Sentry with widget context (type, id, configuration) to help debug member role issues. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ilComponentValue Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The DATE_OVERRIDES key was 'united health fellowship' but the actual carrier name is 'Universal Health Fellowship'. Also broadened the product pattern from /health sharing/i to /./i since UHF products are named Thrive/Standard/STx, not "health sharing". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Match auto insurance by carrier name (geico, the general) in addition to product name, since Geico products are named Standard/Preferred/ Non-Standard without the word "auto". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Production uses nameSingular 'agentProfile' but the refactored service only looked for 'agent', causing silent failure of agent auto-assignment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
agentProfilemetadata lookup that was removed during refactornameSingular: 'agentProfile'but the service only looked for'agent', causing silent failure of agent auto-assignment on new policiesagentProfilefirst, falls back toagentTest plan
🤖 Generated with Claude Code