d75685b8dca4ab2db2ecf74c8cb6dab6e1ade185
12648 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d75685b8dc |
fix(metadata): nestjs-query batched relation queries truncate results across parents (#21455)
## TL;DR
The metadata API silently drops relation rows whenever a batched
relation query exceeds the requested page size. A dev-seeded workspace
already has **558 fieldMetadata rows across 31 objects**, so
`objects(paging:{first:50}) { fields(paging:{first:500}) }` executes:
```sql
SELECT DISTINCT ... FROM core."fieldMetadata" fields
WHERE workspaceId = $1 AND objectMetadataId IN (...31 ids...)
LIMIT 501 OFFSET 0 -- no ORDER BY
```
…and returns exactly **501 of 558** fields — ~57 rows dropped, and
*which object loses which field is scan-order-dependent*. This is what
made `example-app-postcard` CI flap with "PostCard object missing field
X" (different X per run).
## Root cause
`@ptc-org/nestjs-query-typeorm`'s `batchQueryRelations` (the DataLoader
batch path behind every `@CursorConnection`) applies the **per-parent**
page size as a **single global LIMIT** on the batched query, then groups
rows per parent in memory. Any batch whose combined relation rows exceed
`first + 1` truncates arbitrary parents. This affects production
metadata reads, not just CI — any workspace with enough fields/objects
loses rows in `objects.fields`-style connections.
## Fix
Yarn patch on `@ptc-org/nestjs-query-typeorm@9.4.0` (same vehicle as the
existing `nestjs-query-graphql` patch):
- `RelationQueryBuilder.batchSelect`: only apply LIMIT/OFFSET when the
batch has a **single parent**; multi-parent batches stay **bounded**
with `parents × (offset + limit)` — the upper bound a correct per-parent
pager can ever need, so it cannot wrongly truncate while still guarding
against unbounded fetches on high-cardinality relations;
- `batchQueryRelations`: enforce paging **per parent** by slicing after
`mapRelations` (preserves the `first + 1` hasNextPage probe semantics).
## Verification
- On a frozen repro DB (postcard installed, 558 fields): unpatched
returns 501 fields with `postCard` missing `deliveredAt`; patched
returns **558/558** with the full `postCard` field set. Reproduced
identically on typeorm 0.3.20 and 0.3.26 — pre-existing bug, **not** a
typeorm regression (this unblocks the typeorm upgrade that was reverted
from #21448).
- Postcard install/uninstall stress loop: unpatched fails within 1–2
iterations; patched **12/12 green**.
- `npx nx typecheck twenty-server` clean, full `twenty-server` unit
suite green (5651 passed).
## Related
#21435 chases the **same CI symptom** (postcard randomly missing a
freshly synced field) at a different layer — a workspace-cache write
racing invalidation. The two are complementary: the repro behind this PR
survives a **cold server restart + `redis-cli FLUSHALL`** with all rows
intact in Postgres, which no cache race can explain — the truncation
happens on the DB read itself (`LIMIT 501` over 558 matching rows,
captured via `log_statement=all`). Both fixes are likely needed for the
postcard job to be fully reliable.
## Notes
Worth upstreaming to `@ptc-org/nestjs-query` eventually; the proper
upstream fix is per-parent windowed pagination (`ROW_NUMBER() OVER
(PARTITION BY parentId)`), but the in-memory per-parent slice is correct
and proportionate at metadata-API scale.
|
||
|
|
d0884bd708 |
Fix missing datetime filter type (#21451)
Currently datetime fields are only typed to be filtered by string Add a proper typing to match gql filters ## Before <img width="750" height="492" alt="image" src="https://github.com/user-attachments/assets/ff3a5423-3bb0-4295-84c9-e404489354f6" /> ## After <img width="537" height="511" alt="image" src="https://github.com/user-attachments/assets/d8c8219f-b7de-41b0-96cb-5adbfda7a91d" /> |
||
|
|
0ac4f237c0 |
fix(server): stop redundant lambda rebuilds causing build-lock acquisition failures (#21442)
## Context `Lambda invocation failed for function '<id>' during build: Failed to acquire lock for key: lambda-build:<id>` fires ~1000 times/day in production. ## Root cause `LambdaExecutorManagerService.buildExecutor` re-checks `canSkip` inside the `lambda-build:<functionId>` lock, but the re-check reuses the `flatApplication` snapshot captured when the request started. `canSkip` depends on `!flatApplication.isSdkLayerStale`, so: 1. An app sync/install regenerates the SDK client and sets `isSdkLayerStale = true` 2. All in-flight executions of the function fail `canSkip` and queue on the lock 3. The first holder rebuilds and `markSdkLayerFresh` clears the flag in DB + workspace cache 4. Queued waiters can't see that fix — their in-memory snapshot still says stale — so **each waiter redoes the full rebuild serially** (download SDK archive, delete + republish layer, update function config, wait for update) 5. The lock is held back-to-back for minutes; everyone deeper in the queue exhausts the 120s retry budget and throws The local driver already handles this correctly (`LocalLayerManagerService` refreshes the flat application from the workspace cache inside its lock); the lambda driver missed it. ## Fix - Refresh `flatApplication` from the workspace cache inside the lock before re-checking `canSkip`, so waiters skip in ~100ms once the first holder finishes - Degrade gracefully on lock-acquisition timeout: re-check build status with fresh data and proceed with the invocation if the executor is already usable, instead of failing the run (introduces a typed `CacheLockAcquisitionError` so only that case is caught) ## Test plan - [x] `cache-lock.service.spec.ts` passes - [x] `lint:diff-with-main` + typecheck pass - [ ] Monitor `Failed to acquire lock for key: lambda-build:*` error rate in production after deploy |
||
|
|
796f763bb7 |
i18n - website translations (#21453)
Created by Github action --------- Co-authored-by: github-actions <github-actions@twenty.com> |
||
|
|
184c4948d6 |
security: strip Node dev headers from images + lingui 5.9.5 (drops vulnerable esbuild) (#21448)
## Context
AWS Inspector flags the `prod-twenty` image (built from current main)
with 16 findings, and Dependabot alert 174 flags esbuild. This PR fixes
the OpenSSL scanner findings and the esbuild CVE. The typeorm bump
(CVE-2025-60542) was **pulled out of this PR** — see "typeorm status"
below.
## Changes
### Strip `/usr/local/include/node` from runtime stages
(`twenty-server`, `twenty-app-dev`)
15 OpenSSL CVEs (June 9 advisory, incl. CRITICAL CVE-2026-34182) are all
detected via **Node's bundled OpenSSL dev headers**: 3 GENERIC
`openssl/openssl` 3.5.6 detections per CVE at
`/usr/local/include/node/openssl/archs/linux-x86_64/{asm,asm_avx2,no-asm}/include/openssl/opensslv.h`.
The headers are only needed by node-gyp and native addons are compiled
in the build stages — nothing compiles at runtime. Dropping them clears
all 45 detection instances and permanently ends this class of finding
(third occurrence: 3.5.5 → 3.5.6 → 3.5.7). None of these CVEs are
reachable through Node (no CMS/PKCS#7 API, `pfx` is operator-supplied,
Node's QUIC uses ngtcp2, ASN.1 issues need ~2GB inputs).
**Follow-up (~June 17, 2026):** the `node` binary itself still
statically links OpenSSL 3.5.6 — invisible to the scanner after this PR
and unreachable in practice, but the real fix is bumping the pinned
`node:24-alpine` digest once the [announced June 17 Node.js security
releases](https://nodejs.org/en/blog/vulnerability/june-2026-security-releases)
ship a 24.x linking OpenSSL ≥ 3.5.7 (verify via
`deps/openssl/openssl/VERSION.dat` on the release tag — 24.16.0 is still
on 3.5.6). A dated TODO sits next to the cleanup in the Dockerfile.
### esbuild dev-server CORS CVE (Dependabot alert 174,
GHSA-67mh-4wv8-2f99)
`@lingui/cli@5.1.2` (pins `esbuild ^0.21.5`) was the last parent
resolving a vulnerable esbuild (≤ 0.24.2 lets any website send requests
to the dev server and read responses). Instead of a resolution override,
this bumps the lockstepped **lingui suite 5.1.2 → 5.9.5** (within-major;
lingui adopted `esbuild ^0.25.1` in 5.4.1), which:
- removes `esbuild@0.21.5` and all its platform packages from the
lockfile with no forced ranges;
- drops the `@lingui/core` lockstep resolution (its comment marked it
droppable on the next coordinated lingui bump — the tree now resolves a
single `@lingui/core@5.9.5`);
- `@lingui/swc-plugin` stays at `^5.11.0` (peers on `@lingui/core: 5`;
its 6.x line targets lingui 6).
**lingui 5.9.5 behavioral fallout handled here:**
- Translation functions now **throw without an active locale** (5.1.2
fell back silently). The global `i18n` singleton that backs server-side
`` t`…` `` calls only had a messages compiler set, never an activated
locale → activate the source locale in `I18nService.loadTranslations()`,
mirrored in the server jest setup (unit tests bypass Nest bootstrap).
- `msg`/`t` placeholders are now strictly typed (reject
`null`/`undefined`/`unknown`) → one server call site and 16 twenty-front
files adapted with minimal nullish-coalescing fixes that preserve
rendering.
- `.po`/compiled-catalog churn from the new extractor/compiler
(reference reordering, sorted keys — verified content-identical on
unchanged `.po` inputs) is intentionally not committed: the scheduled
i18n workflows regenerate those.
## typeorm status (pulled out)
typeorm 0.3.20 → 0.3.26 was originally in this PR but **made workspace
metadata sync intermittently lossy**: `example-app-postcard` failed
twice with a *different* field missing from the synced PostCard object
each run, and one integration shard's `DataSeedWorkspaceCommand` died
with "Could not find flat entity with universal identifier …" — versus
zero such failures on recent main. Local runs (db reset + seed, group-by
integration suite 19/19) pass, so it is a nondeterministic
CI-load-sensitive regression that needs dedicated debugging (typeorm
changed LIMIT/OFFSET 0 semantics, lazy count for `getManyAndCount`,
upsert WHERE construction, and topological-sort internals in that
range). The resolutions comment documents this as the blocker;
CVE-2025-60542 is MySQL-driver-only (`sqlstring`), so Postgres-only
Twenty is not exposed in the meantime.
## Verification
- `npx nx typecheck twenty-server` / `twenty-front` — clean (no cache)
- `npx nx test twenty-server` — full suite green
- `lingui:extract` + `lingui:compile` — clean for twenty-server /
twenty-emails / twenty-front
- `oxfmt --check` — clean for both packages
- Lockfile diff: lingui 5.9.5 entries, `esbuild@0.21.5` +
`@esbuild/*@0.21.5` platform packages removed, no typeorm changes
|
||
|
|
303c415dd1 |
fix(ai) - add logs + remove dashboard building (#21440)
- add logs for thread finishing without agent message - add logs to monitor toolCall token usage - remove dashboard building via AI (before fixing it) - fix Anthropic compute |
||
|
|
a6fcbf58e4 |
fix(billing) - enable upgrade if invoice already paid (#21450)
Had an issue concerning a user with credits, then invoice automatically paid. Upgrade failed |
||
|
|
7da6f25aaf |
Replace random remote images in stories to stop flaky Argos diffs (#21447)
### Problem `TabButton` and `AvatarOrIcon` stories (in both `twenty-ui` and `twenty-ui-deprecated`) used random remote image URLs — `picsum.photos/192/192` and `i.pravatar.cc/300`. Each Argos run fetched a different image, producing false-positive pixel diffs. This is the image counterpart to #21412, which froze framer-motion animations for the same reason. ### Fix Replace all 6 random URLs with `AVATAR_URL_MOCK` — a fixed base64 data URI already used across avatar stories. It's deterministic and network-free, so screenshots are now stable across runs. - `twenty-ui` / `twenty-ui-deprecated` → `TabButton.stories.tsx` (×2 each) - `twenty-ui` / `twenty-ui-deprecated` → `AvatarOrIcon.stories.tsx` (×1 each) Note: this changes the rendered image content, so it adds new baselines (one-time Argos approval, not flakiness). |
||
|
|
f7463886a6 |
feat(partners): partner role row-level security (RLS) with scoped edits (#21386)
## Summary
Adds an external **Partner** self-service role that sees and edits only
its own
records via row-level security (RLS), so a validated partner can sign in
and manage
just the deals they're matched on.
## What's included
- **`partnerUser` relation** on Partner, Person, Company, Opportunity (+
inverse
relations on Workspace Member) — the login member a record belongs to.
- **RLS predicates** scoping each of those objects to "partnerUser IS
the current
workspace member", plus a self-scope on Workspace Member so member-typed
relations
resolve without exposing the internal team roster. Applied out-of-band
via
`yarn rls:configure` (the app manifest cannot ship RLS predicates).
- **Assign / unassign cascade** (`on-opportunity-partner-assigned` logic
function):
assigning a Partner to an Opportunity stamps `partnerUser` onto the
Opportunity +
its Company + People; removing the Partner clears it (and cascades to
the
Company/People when no other deal of that member still uses them).
- **Partner role permissions**
- Partner profile: full read/update.
- Opportunity: read all; **update `stage` and `amount` only** (every
other
user-facing field locked).
- Company / Person: read-only.
- Workspace Member: read-only, RLS-scoped to self.
- **`partnerUser` column** added to the Validated Partners view so the
login member
can be assigned inline.
## Install / upgrade note
After install or reinstall, run `yarn rls:configure` (`:prod` variant
for prod) to
(re)apply the RLS predicates and verify the field-permission locks.
Manifest sync
handles object/field permissions; predicates are applied by this script.
## Platform gaps found (for the eng team)
1. **Manifest sync doesn't invalidate the roles-permissions Redis
cache.** Permission
changes deployed via `yarn twenty dev --once` persist to the DB but
aren't reflected
in the cached snapshot used for enforcement until
`engine:workspace:metadata:permissions:roles-permissions:<workspaceId>:{data,hash}`
is flushed. Relevant on any real workspace when permissions change.
2. **Locking a server-injected field silently breaks all updates.** The
`*.updateOne`
pre-query hook writes `updatedBy` into every update, so
`canUpdateFieldValue:false`
on `updatedBy` makes the permission check reject *every* record update
with
`PERMISSION_DENIED`. Field-permission lock lists must exclude
server-managed/injected
fields (`updatedBy`; and `position`, co-written with `stage` on kanban
drag).
## Version
Minor bump → `0.5.0` (new role, new fields, new behaviour;
backwards-compatible).
## Testing
- Verified locally as a partner user: edits own profile; edits
Opportunity stage +
amount; Company/Person read-only; sees only matched deals; unassigning a
partner
removes the deal (and its company/people) from the partner's view.
- `yarn rls:configure` passes (5 predicates upserted; 24 Opportunity
fields locked,
stage + amount editable).
- Lint clean.
|
||
|
|
166f7ee0d2 |
chore(deps): prune yarn resolutions down to load-bearing entries (#21446)
## Context Audit of all 28 `resolutions` entries in the root package.json against yarn.lock dependency graphs and the npm registry, to remove every entry that is no longer forcing anything a normal resolution wouldn't do — resolutions are hard to maintain and silently freeze versions. Net result: **28 → 22 entries**, two small dependency bumps replace pins, and every remaining entry now has its blocker + removal condition documented in `//resolutions`. ## Removed — dead weight (re-resolution lands on the same safe versions) | Entry | Why it was dead | |---|---| | `type-fest: 4.10.1` | Stale 2024 dedup pin that semver-overrode ~16 of 19 declared ranges (forced `^0.13`/`^0.20`/`^0.21` consumers up four majors, `^5.x` consumers down one). Types-only; each parent now resolves its own compatible copy. | | `typescript: 5.9.3` | No-op: every range (`^5.9.3`, `5.9.3`, `~5.9.2`) resolves to 5.9.3 naturally. Only the electron-forge scaffolding template regains its own nested `~5.4.5` (never builds this repo). | | `node-gyp: ^12.4.0` | All requesters are Yarn-injected `node-gyp: latest` = 12.4.0 today. The tar-6-era node-gyp versions it evicted have no requesting parent left. | | `cacache: ^20.0.0` | All four parents (arborist, metavuln-calculator, make-fetch-happen 15, pacote 21) already declare `^20`. Guarded by the kept `make-fetch-happen: ^15` resolution. | | `pacote/tar: ^7.5.16` | The original target (pacote 11/15 via zapier) is gone; the only pacote left is 21.5.0 which declares `tar ^7.4.3` natively. | ## Removed — replaced by a parent upgrade - **`nodemailer: 8.0.10`** → `imapflow` 1.2.1 → **1.3.6** (ships patched nodemailer 8.0.10 exact; 1.4.0 is blocked by the 3-day npm age gate). twenty-server's own `^8.0.5` range was already safe. - **`node-ical/uuid: 11.1.1`** → `node-ical` ^0.20.1 → **^0.21.0**, which drops uuid (and axios) entirely. The uuid removal happened at 0.21.0 — not in the 0.26 rrule-temporal type overhaul that #21441 flagged as the blocker. ## Narrowed — `qs: 6.15.2` global → two scoped entries Only three lockfile entries actually request vulnerable qs ranges: `express@4.22.0` (pinned by `@mintlify/previewing`), `express@4.22.1` + `@cypress/request@3.0.10` (pinned by verdaccio 6.7.2, latest). Replaced the global pin with `express/qs` + `@cypress/request/qs`, so the 12+ healthy parents (express 4.22.2/5.x, body-parser, stripe, …) are no longer frozen and will pick up future qs releases naturally. ## Re-pinned — `graphql-redis-subscriptions/ioredis` Changed `^5.6.0` → exact `5.10.1` and documented why: this must equal the exact ioredis version pinned by twenty-server and bullmq. Without it, graphql-redis-subscriptions' `^5.3.2` resolves to a second ioredis copy and `RedisPubSub`'s publisher/subscriber types reject the server's client (caught by twenty-server typecheck during this work — bump it in lockstep with the ioredis pin). ## Kept (all load-bearing, now documented inline) graphql (singleton below msw's `^16.12.0`), @lingui/core (suite lockstep), @types/qs (6.9.17 typing-break holdback), @opentelemetry/api (NoopMeterProvider singleton, #20231), chokidar v3 (NestJS CLI fsevents, #20316), tmp (zapier-platform-cli pins 0.2.5), make-fetch-happen + the two @electron tar entries (blocked on electron-forge adopting @electron/rebuild 4), @angular-devkit/core (blocked on a fixed @nestjs/cli > 11.0.23), yeoman-environment, webpack-dev-server, next/postcss (fix only in next 16.3.0 canaries), the remaining uuid pins, and react-doc-viewer/ajv. ## Follow-ups (separate PRs) - `typeorm` 0.3.20 → 0.3.30: re-roll the 46-line patch; clears the `typeorm/uuid` resolution **and** the open high-severity GHSA-q2pj-6v73-8rgj (SQL injection in `repository.save/update`, fixed in 0.3.26). - googleapis 105 → ≥152 migration clears `googleapis-common/uuid`. ## Verification - `yarn install` clean; lockfile contains **no** vulnerable qs (≤6.15.1)/tar 6/uuid <11/nodemailer <8.0.4/postcss 8.4.31/tmp <0.2.6 entries - `npx nx typecheck twenty-server` ✓ and `npx nx typecheck twenty-front` ✓ - CalDAV + IMAP unit tests (node-ical/imapflow consumers): 9 suites, 121 tests ✓ - `yarn npm audit --all`: only pre-existing typeorm finding remains (see follow-up) |
||
|
|
1ccede2309 |
security: scoped ajv 8.20.0 resolution for react-doc-viewer (Dependabot alert 481) (#21445)
Closes the **final** open Dependabot alert — ajv [481](https://github.com/twentyhq/twenty/security/dependabot/481) — with a scoped resolution. ### Why a resolution (no parent path) `ajv >= 7.0.0 < 8.18.0` is pulled **only** by `@cyntler/react-doc-viewer`, which pins `ajv ^7.2.4`. Its **latest (1.17.1) still pins `^7`** — there is no react-doc-viewer version on ajv 8 (no 1.18/2.0) — so it can't be closed by upgrading the parent. ### Why it's completely safe `@cyntler/react-doc-viewer` **never imports ajv** — zero references in its dist; ajv is a declared-but-unused dependency. So forcing it to ajv 8 has **no functional impact**, and the ajv 7→8 breaking-change concern is moot. Scoped to `@cyntler/react-doc-viewer/ajv` so it touches nothing else. ### Verification - `yarn install --immutable` ✓; every ajv now resolves to **8.18.0 / 8.20.0** (safe) or `6.12.x` (outside the advisory range) — no vulnerable ajv remains. Documented in the top-level `//resolutions` note with a removal trigger. **This was the last open alert.** |
||
|
|
462dd3b0e9 |
security: uuid CVE — bump bullmq/msal/blocknote + scoped resolutions for the rest (Dependabot alert 1289) (#21441)
Closes the uuid Dependabot alert — [1289](https://github.com/twentyhq/twenty/security/dependabot/1289) — by **upgrading the parents that bump cleanly** and **scope-resolving only the ones that genuinely can't**. `uuid < 11.1.1` (buffer-bounds check in v3/v5/v6) is pulled by ~9 transitives. ### Bumped (parent upgrade — drops uuid<11, no behavior change; typecheck verified) - **bullmq** 5.40.0 → 5.78.0 — also aligned **ioredis** 5.6.0 → 5.10.1 (bullmq pins it) and fixed the renamed `Job.returnValue→returnvalue` / `stackTrace→stacktrace` (now `string[]|null`) in `admin-panel-queue.service.ts`. - **@azure/msal-node** ^3.8.4 → ^5.2.3 (5.2.4 was age-gate-quarantined). - **@blocknote/** ×5 ^0.47.3 → ^0.51.4. ### Scope-resolved to uuid 11.1.1 (no clean bump exists) - **sockjs** (latest; pinned by webpack-dev-server) and **@ptc-org/nestjs-query-typeorm** (9.4.0 *is* latest, pins `^10`) — no version drops uuid. - **typeorm** — a `patch:` dep / ORM core, too risky to bump. - **node-ical** 0.26 (type-model overhaul → caldav-parser rewrite) and **googleapis** 173 (Gmail/OAuth, 105→173) — large breaking migrations; **deferred to dedicated PRs**. - **@cypress/request** — transitive (cypress isn't a direct dep). Resolutions are **per-package** and preserve the intentional **uuid 13.x** (twenty-sdk / create-twenty-app). ### Verification - `twenty-server` typecheck ✓ (0 errors), `twenty-front` typecheck ✓ (0 errors). - `yarn install --immutable` ✓; every uuid resolves to **11.1.1** or **13.0.2**. - bullmq/msal/typeorm runtime exercised by the **server integration tests**; @blocknote by the **storybook tests** in CI. |
||
|
|
6af06c1062 |
security: postcss CVE via styled-components bump + next/postcss resolution (Dependabot alert 1061) (#21438)
Closes the postcss Dependabot alert — [1061](https://github.com/twentyhq/twenty/security/dependabot/1061) — by **bumping one parent** and using a **scoped resolution** only where there's no other path. postcss `< 8.5.10` (XSS via unescaped `</style>` in stringify output) was bundled by two parents: ### styled-components → bumped (no resolution) `styled-components 6.4.2` (in-range for our `^6.1.0`; we were on a stale 6.3.12) **dropped its postcss dependency entirely**, so a plain `yarn up` removes the 8.4.49 copy — no override. (styled-components is only used in one component-renderer Storybook showcase; product UI is on Linaria.) Re-built `twenty-front-component-renderer` to confirm the bump. ### next → scoped resolution (no parent path) `next` pins postcss `8.4.31` **exact on every stable release** — next@latest (16.2.9) still pins it; the fix (8.5.10) exists only in the **16.3.0 canary** (unreleased). So `next/postcss: 8.5.15` is the only mechanism, scoped to next and documented in the top-level `//resolutions` note with a removal trigger. ### Verification - Every postcss now resolves `>= 8.5.14` (safe); `yarn install --immutable` ✓. - postcss is build-time and **CI doesn't build twenty-website on regular PRs**, so verified locally: **twenty-website** (Next production build) ✓ and **twenty-front-component-renderer** ✓. |
||
|
|
6756ea628d |
Add People Data Labs enrichment logic functions (#21254)
## Add People Data Labs enrichment logic functions Implements the **enrichment logic functions** that call the PDL API and map responses onto standard + `pdl*` fields. - **Logic functions** — shared core powers bulk workflow actions (`enrich-person` / `enrich-company`) and single-record AI tools. Each guards a TTL, matches via identifier, fills standard fields only when empty, always writes `pdl*` fields, and normalizes SELECT values against field options. - **Data model** — PDL employer now links via the **standard `company` relation** (find-or-create, fill-only-if-empty); removed the dedicated `pdlCurrentCompany` relation, six `pdlJobCompany*` scalars, and the `pdl*` indexes. **Not functional yet:** the post-install workflow seeding (`seed-enrichment-workflow.ts`) is left in place but blocked — it needs workflow-builder mutations that the CRUD-only app SDK schema doesn't expose. **Deferred:** metering/billing and auto-enrichment triggers. https://github.com/user-attachments/assets/a570a484-ae79-4c57-a274-e068fdab78e4 https://github.com/user-attachments/assets/6edfb5e1-cada-4892-87e0-b485eb359692 |
||
|
|
28ab160b48 |
i18n - website translations (#21439)
Created by Github action --------- Co-authored-by: github-actions <github-actions@twenty.com> |
||
|
|
d596c26f46 |
Migrate twenty UI (#21407)
## Migrate all `twenty-ui-deprecated` components into `twenty-ui` Ports all **192 components** and **70 stories** into the new `twenty-ui` package with full public-API parity (export diff: 0 missing / 0 extra across all 13 modules; story titles byte-identical for the Argos cross-package diff). - **Styling:** Linaria → SCSS Modules, `var(--t-*)` tokens, `data-*` state. Canonical pattern in `Button.module.scss`. - **Behavior:** Base UI where mapped (Checkbox, Radio, Modal→Dialog, Tooltip drops `react-tooltip`, JSON tree→Collapsible); framer kept only where animation is the public contract. - **Fixed an inert axe gate** in `.storybook/vitest.setup.ts` (a11y addon annotations were never registered). Now live; 119 stories carry `a11y: 'todo'` overrides pending a fix pass. |
||
|
|
c05c34aaec |
[Website] Convert remaining images to WebP and compress some current ones. (#21404)
As title. Also deleted some unused assets that are no longer required. |
||
|
|
2da28cb03e |
security: upgrade express 4.22.2 + qs 6.15.2 resolution for dev-tool holdouts (Dependabot alert 1305) (#21434)
Closes the qs Dependabot alert — [1305](https://github.com/twentyhq/twenty/security/dependabot/1305) — by **upgrading express where possible** and using a **documented qs resolution** only for the irreducible dev-only holdouts. ### What's vulnerable `qs 6.14.x` (the `qs.stringify` DoS) is pulled by `express 4.22.1` / `body-parser 1.x`. The fix is `qs 6.15.2`, and there's **no backport to the 6.14 line**. ### Upgrade what we can (no resolution) `express 4.22.2` / `body-parser 1.20.5` moved to the patched `qs ~6.15.1`. So this PR bumps the app + in-range tooling to **express 4.22.2**: - twenty-server's stale direct pin `4.22.1 → 4.22.2` (its runtime HTTP is already express 5.2.1 via `@nestjs/platform-express`; this just patches the redundant direct dep — typecheck passes), - nx / electron-forge / webpack-dev-server / companion follow via `yarn up -R express body-parser`. ### Resolution only for the two holdouts Two **dev-only** tools pin express *exactly* with no patched release on a line we can use, so they still drag in `qs 6.14.2`: - **verdaccio** `4.22.1` — express 5 only landed in the **v7 beta** ([verdaccio#5680](https://github.com/verdaccio/verdaccio/issues/5680), [#2479](https://github.com/verdaccio/verdaccio/issues/2479)), **not** backported to the 6.x line we use. - **@mintlify/previewing** `4.22.0` — closed-source, latest still pins 4.22.0, no movement. A `qs: 6.15.2` resolution covers those, documented with a top-level `//resolutions` note and a removal trigger. ### Verification - `yarn install --immutable` ✓; every `qs` resolves to `6.15.2`; express app/tooling on `4.22.2` (only verdaccio/mintlify remain on old express, neutralized by the resolution). - `twenty-server` typecheck ✓ (90 files import express types; 4.22.1→4.22.2 is a patch). - Non-exploitable in prod regardless (express/body-parser use `qs.parse`, not the vulnerable `stringify`). |
||
|
|
233a6f9fb1 |
fix(server): register Lingui message compiler to stop "Uncompiled message detected" log flood (#21416)
## Summary Fixes #21415. Server-side `` t`…` `` macro calls (e.g. `FlatEntityMapsException`) resolve against Lingui's global `i18n` singleton, which `I18nService` never loads a catalog into and never registers a messages compiler on. With no `_messageCompiler` set, every such lookup logs `Uncompiled message detected!` and falls back to the raw string — flooding server logs (enough to hit hosting log rate limits) and disabling ICU interpolation on those messages. The warning is emitted unconditionally by `@lingui/core` (not `NODE_ENV`-gated). ## Changes Register `compileMessage` via `setMessagesCompiler` in `I18nService.loadTranslations()`: - on the global `i18n` singleton (used by the `t` macro), and - on each per-locale instance. `@lingui/message-utils` is already a transitive **runtime** dependency of `@lingui/core` (`@lingui/core@5.1.2 → @lingui/message-utils@^5.1.2`), so no new dependency is added. ## Testing Deployed on a real instance: before, the server emitted hundreds of `Uncompiled message detected` lines/sec (saturating the log rate limit); after, steady-state shows `0`, and the worker (which shares the code path) likewise shows `0`. App behaviour is unchanged — messages already rendered via fallback; this silences the warning and enables ICU on the affected messages. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Félix Malfait <felix.malfait@gmail.com> Co-authored-by: Félix Malfait <felix@twenty.com> |
||
|
|
20c83e1f86 |
fix(kanban): preserve scroll on board re-init + propagate same-column reorders via SSE (#20637)
closes https://discord.com/channels/1130383047699738754/1504130730840821860 https://github.com/user-attachments/assets/d5833031-01c6-4e46-b699-c29c42435a53 ## Summary Fixes two related issues with the kanban (board view) collaboration experience: 1. **Scroll-to-top on every data change** — `triggerRecordBoardInitialQuery` always scrolled the board to the top, even when re-initializing for a single-record data change (SSE echo of your own mutation, a collaborator's update). Scroll reset only makes sense when the dataset itself changes (filter / sort / group). 2. **Same-column reorders by other users did not propagate** — the server's diff function stripped `FieldMetadataType.POSITION`, so position-only updates produced empty `updatedFields` and short-circuited event emission entirely. SSE clients never received them. ## What's in here - **Frontend** — `useTriggerRecordBoardInitialQuery` now exposes a `triggerRecordBoardInitialQueryWithoutScrollReset` variant; data-driven re-inits in `RecordBoardDataChangedEffect` use it, while genuine filter / sort / group changes keep the scroll-resetting `triggerRecordBoardInitialQuery`. `getRecordBoardEffectsForUpdateInputs` classifies each update as `trigger-initial-query` / `reposition-records` / `none`. For position- or group-only changes we skip the re-query and reposition records in place in the store (`useRepositionRecordsOnBoard`), which avoids the flicker and preserves scroll. - **Server** — removes `POSITION` from `objectRecordChangedValues`' strip list, so position-only updates emit a non-empty diff and flow through SSE. Position is now treated as a field like any other across all event consumers (SSE, webhooks, workflows, logic functions); a trigger with an explicit field filter still excludes it. |
||
|
|
9100fb1e9f |
security: scoped resolution for webpack-dev-server 5.2.4 (Dependabot alerts 1237/691/692) (#21420)
Closes 3 webpack-dev-server Dependabot alerts — [1237](https://github.com/twentyhq/twenty/security/dependabot/1237), [691](https://github.com/twentyhq/twenty/security/dependabot/691), [692](https://github.com/twentyhq/twenty/security/dependabot/692) — with a **scoped** resolution: `@electron-forge/plugin-webpack/webpack-dev-server: 5.2.4`. (These numbers are Dependabot **alert** IDs, not issue/PR numbers — written without `#` to avoid cross-linking unrelated issues, per review feedback.) ### Why a resolution (the one place it's unavoidable) webpack-dev-server is pulled **only** by `@electron-forge/plugin-webpack` (twenty-companion's build tooling), and **no electron-forge release uses webpack-dev-server 5** — not even `8.0.0-alpha.9` still pins `^4`. There is no parent-upgrade path, so a resolution is the only mechanism. ### Scoped, not global Per review feedback, the resolution targets `@electron-forge/plugin-webpack/webpack-dev-server` rather than a global override — it only forces v5 under electron-forge (the sole consumer), limiting blast radius. Verified the scoped syntax is honored: removing it reverts the lockfile to `webpack-dev-server@npm:^4.0.0`; with it, the lock pins `webpack-dev-server@npm:5.2.4` and `yarn install --immutable` passes. ### Why it's safe (constructor did NOT change v4→v5) `@electron-forge/plugin-webpack@7` calls `new WebpackDevServer(this.devServerOptions(), compiler)`. webpack-dev-server's constructor is `constructor(options, compiler)` in **both v4 and v5** (verified in `lib/Server.js:331` and `types/lib/Server.d.ts:1179`). The `(compiler, options)` → `(options, compiler)` swap happened at **v3 → v4**, not v4 → v5. The plugin passes only options unchanged in v5 (`hot`, `devMiddleware.writeToDisk`, `historyApiFallback`, `port`, `setupExitSignals`, `static`, `headers`) and uses none of the hooks v5 removed. ### Scope / verification - `yarn install --immutable` ✓; webpack-dev-server resolves to 5.2.4 only (was 4.15.2), no vulnerable copy remains. - Only exercised by `electron-forge start` (dev HMR); production `make`/`package` builds don't use it, and **twenty-companion has no CI workflow**, so this can't affect CI. - Residual manual check (not CI-covered): `yarn start:electron` in twenty-companion still boots the dev server. |
||
|
|
9d7f0c405f |
fix(twenty-front): new layout fast-follows — command menu, field options & logs (#21429)
Fast-follows for the new layout — the remaining open sub-issues of
twentyhq/core-team-issues#2478.
## Changes
- **Command menu items should not have extra right padding**
(twentyhq/core-team-issues#2500)
`SidePanelList` set `width: calc(100% - spacing[4])` on top of its own
8px left/right padding. Under the global `box-sizing: border-box`, that
extra `-16px` shrinks the list and, because it's left-aligned, dumps the
whole gap on the right. Switched to `width: 100%` so item highlights
inset 8px symmetrically. This is shared by every side-panel list — they
all had the same right-only gutter, so they're all corrected the same
way.
- **Field options should not be cropped and should keep row gaps**
(twentyhq/core-team-issues#2503)
The option row used a fixed `height: spacing[6]`, so under border-box
the `6px` vertical padding was absorbed and consecutive rows sat flush.
Changed `height` → `min-height` so the padding separates the rows again.
- **Logs table with filters should use Background secondary**
(twentyhq/core-team-issues#2505)
The Logs filter card and the upgrade card defaulted to a transparent
background, showing the white page through. Passed
`backgroundColor={themeCssVariables.background.secondary}`, matching
`SettingsTableCard`. The results table stays on the primary surface, per
the Figma reference.
- **Command menu back chevron** (twentyhq/core-team-issues#2504)
`SidePanelTopBar` showed a back chevron whenever the nav stack had more
than one entry. A command-menu page is the root of a fresh command-menu
session, so it now only shows the chevron when it was opened from
another command-menu page. Every other side-panel page keeps standard
history-based back navigation, so workflow / page-layout / record stacks
are unaffected.
## Verification
- oxlint (`--type-aware`, full `src/`): 0 errors
- oxfmt: clean
- tsgo typecheck: no errors in the changed files (the one reported error
is pre-existing in `RestPlayground.tsx`, which this PR does not touch)
- Verified live at apple.localhost:
- #2500 — command menu item highlight insets measured 8px left / 8px
right (was 8 / 24)
- #2503 — option rows render at 38px tall with ~14px gaps, text no
longer cropped
- #2505 — filter + upgrade cards compute to background-secondary;
results table stays on primary
- #2504 — direct command menu shows the close-X with no chevron; pages
opened from the command menu still show the chevron
## Open question for review (#2504)
The issue also describes the page-header three-dots toggle: *"the three
dots icon button should remain visible if the side panel is on a page
that is not a child of the command menu (AI chat, or a page opened
directly)."* Today that toggle morphs to an X for any non-command-menu
side-panel page (e.g. Ask AI). Honoring that touches the shared
`SidePanelToggleButton`, and there's a related decision: search / Ask AI
opened from the command menu currently reset the nav stack rather than
push, so they don't get a "back to command menu" chevron. I left those
out here since they're a behavior change to a shared control with a
product call attached — happy to follow up once you confirm the intended
toggle behavior.
Closes twentyhq/core-team-issues#2500
Closes twentyhq/core-team-issues#2503
Closes twentyhq/core-team-issues#2505
Refs twentyhq/core-team-issues#2504
Refs twentyhq/core-team-issues#2478
|
||
|
|
f55a45f4e0 |
chore(deps-dev): bump storybook from 10.2.13 to 10.4.3 (#21428)
Bumps [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/core) from 10.2.13 to 10.4.3. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/storybookjs/storybook/releases">storybook's releases</a>.</em></p> <blockquote> <h2>v10.4.3</h2> <h2>10.4.3</h2> <ul> <li>Addon Docs: Fix Primary and Controls blocks not rendering in custom MDX pages - <a href="https://redirect.github.com/storybookjs/storybook/pull/34496">#34496</a>, thanks <a href="https://github.com/NYCU-Chung"><code>@NYCU-Chung</code></a>!</li> <li>Core: Respect !dev tag on MDX docs in sidebar - <a href="https://redirect.github.com/storybookjs/storybook/pull/35031">#35031</a>, thanks <a href="https://github.com/JReinhold"><code>@JReinhold</code></a>!</li> <li>React: Add support for resolving subcomponents attached as properties of a parent component - <a href="https://redirect.github.com/storybookjs/storybook/pull/34967">#34967</a>, thanks <a href="https://github.com/yatishgoel"><code>@yatishgoel</code></a>!</li> <li>UI: Prevent docs page scroll reset on HMR re-render - <a href="https://redirect.github.com/storybookjs/storybook/pull/35021">#35021</a>, thanks <a href="https://github.com/LongTangGithub"><code>@LongTangGithub</code></a>!</li> </ul> <h2>v10.4.2</h2> <h2>10.4.2</h2> <ul> <li>Bug: Fix Windows command resolution for non-Node package managers - <a href="https://redirect.github.com/storybookjs/storybook/pull/33534">#33534</a>, thanks <a href="https://github.com/copilot-swe-agent"><code>@copilot-swe-agent</code></a>!</li> <li>Build: Upgrade type-fest to latest version 5.6.0 - <a href="https://redirect.github.com/storybookjs/storybook/pull/34791">#34791</a>, thanks <a href="https://github.com/tobiasdiez"><code>@tobiasdiez</code></a>!</li> <li>CSF: Fix parsing of string literal export names - <a href="https://redirect.github.com/storybookjs/storybook/pull/34901">#34901</a>, thanks <a href="https://github.com/shilman"><code>@shilman</code></a>!</li> <li>Publish: Add npm provenance attestations - <a href="https://redirect.github.com/storybookjs/storybook/pull/34936">#34936</a>, thanks <a href="https://github.com/copilot-swe-agent"><code>@copilot-swe-agent</code></a>!</li> </ul> <h2>v10.4.1</h2> <h2>10.4.1</h2> <ul> <li>Angular: Detect model() signal outputs (type inference + compodoc autodocs + runtime binding) - <a href="https://redirect.github.com/storybookjs/storybook/pull/34833">#34833</a>, thanks <a href="https://github.com/valentinpalkovic"><code>@valentinpalkovic</code></a>!</li> <li>Build: Upgrade type-fest to latest version 5.6.0 - <a href="https://redirect.github.com/storybookjs/storybook/pull/34791">#34791</a>, thanks <a href="https://github.com/tobiasdiez"><code>@tobiasdiez</code></a>!</li> <li>CLI: Run `npx expo install --fix` after init for Expo projects - <a href="https://redirect.github.com/storybookjs/storybook/pull/34803">#34803</a>, thanks <a href="https://github.com/ndelangen"><code>@ndelangen</code></a>!</li> <li>CLI: Support `peerDependencies` in framework detection for component libraries - <a href="https://redirect.github.com/storybookjs/storybook/pull/34516">#34516</a>, thanks <a href="https://github.com/zhyd1997"><code>@zhyd1997</code></a>!</li> <li>Next.js: Add useLinkStatus mock to next/link export mock - <a href="https://redirect.github.com/storybookjs/storybook/pull/34593">#34593</a>, thanks <a href="https://github.com/philwolstenholme"><code>@philwolstenholme</code></a>!</li> <li>Vue3: Specify a specific version for non-dev dependency - <a href="https://redirect.github.com/storybookjs/storybook/pull/34794">#34794</a>, thanks <a href="https://github.com/ScopeyNZ"><code>@ScopeyNZ</code></a>!</li> </ul> <h2>v10.4.0</h2> <h2>10.4.0</h2> <blockquote> <p><em>AI-assisted setup, change-aware review, and stronger framework support</em></p> </blockquote> <p>Storybook 10.4 contains hundreds of fixes and improvements including:</p> <ul> <li>🤖 Agentic Setup: New CLI workflow for AI-assisted Storybook setup and onboarding</li> <li>🔍 Change review: Sidebar filtering to highlight new, modified, and related stories based on git changes</li> <li>🧭 Sidebar review tools: Status filtering, URL-persisted filters, and clearer review signals in the sidebar</li> <li>⚛️ TanStack React: New `@storybook/tanstack-react` framework with routing and server function support</li> <li>🧩 React MCP: Faster, more accurate component docgen powered by the TypeScript Language Server</li> <li>📱 React Native: Zero config RN project initialization</li> <li>🤝 Sharing: Easily publish and share your local Storybook with teammates, powered by Chromatic</li> </ul> <!-- raw HTML omitted --> <ul> <li>A11y: Add aria-live announcements via <code>@react-aria/live-announcer</code> - <a href="https://redirect.github.com/storybookjs/storybook/pull/33970">#33970</a>, thanks <a href="https://github.com/copilot-swe-agent"><code>@copilot-swe-agent</code></a>!</li> <li>A11y: Improve boolean control contrast in forced colors mode - <a href="https://redirect.github.com/storybookjs/storybook/pull/34204">#34204</a>, thanks <a href="https://github.com/anchmelev"><code>@anchmelev</code></a>!</li> <li>Actions: Fix state mutation and keep newest actions when limit reached - <a href="https://redirect.github.com/storybookjs/storybook/pull/34286">#34286</a>, thanks <a href="https://github.com/Sidnioulz"><code>@Sidnioulz</code></a>!</li> <li>Addon-Docs: Add Reset story button to re-render stories in docs - <a href="https://redirect.github.com/storybookjs/storybook/pull/34086">#34086</a>, thanks <a href="https://github.com/6810779s"><code>@6810779s</code></a>!</li> <li>Addon-Docs: Avoid rerendering static Source blocks - <a href="https://redirect.github.com/storybookjs/storybook/pull/34206">#34206</a>, thanks <a href="https://github.com/anchmelev"><code>@anchmelev</code></a>!</li> <li>Addon-Vitest: Use Vitest's provide-API for injecting values - <a href="https://redirect.github.com/storybookjs/storybook/pull/34518">#34518</a>, thanks <a href="https://github.com/JReinhold"><code>@JReinhold</code></a>!</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md">storybook's changelog</a>.</em></p> <blockquote> <h2>10.4.3</h2> <ul> <li>Addon Docs: Fix Primary and Controls blocks not rendering in custom MDX pages - <a href="https://redirect.github.com/storybookjs/storybook/pull/34496">#34496</a>, thanks <a href="https://github.com/NYCU-Chung"><code>@NYCU-Chung</code></a>!</li> <li>Core: Respect !dev tag on MDX docs in sidebar - <a href="https://redirect.github.com/storybookjs/storybook/pull/35031">#35031</a>, thanks <a href="https://github.com/JReinhold"><code>@JReinhold</code></a>!</li> <li>React: Add support for resolving subcomponents attached as properties of a parent component - <a href="https://redirect.github.com/storybookjs/storybook/pull/34967">#34967</a>, thanks <a href="https://github.com/yatishgoel"><code>@yatishgoel</code></a>!</li> <li>UI: Prevent docs page scroll reset on HMR re-render - <a href="https://redirect.github.com/storybookjs/storybook/pull/35021">#35021</a>, thanks <a href="https://github.com/LongTangGithub"><code>@LongTangGithub</code></a>!</li> </ul> <h2>10.4.2</h2> <ul> <li>Bug: Fix Windows command resolution for non-Node package managers - <a href="https://redirect.github.com/storybookjs/storybook/pull/33534">#33534</a>, thanks <a href="https://github.com/copilot-swe-agent"><code>@copilot-swe-agent</code></a>!</li> <li>Build: Upgrade type-fest to latest version 5.6.0 - <a href="https://redirect.github.com/storybookjs/storybook/pull/34791">#34791</a>, thanks <a href="https://github.com/tobiasdiez"><code>@tobiasdiez</code></a>!</li> <li>CSF: Fix parsing of string literal export names - <a href="https://redirect.github.com/storybookjs/storybook/pull/34901">#34901</a>, thanks <a href="https://github.com/shilman"><code>@shilman</code></a>!</li> <li>Publish: Add npm provenance attestations - <a href="https://redirect.github.com/storybookjs/storybook/pull/34936">#34936</a>, thanks <a href="https://github.com/copilot-swe-agent"><code>@copilot-swe-agent</code></a>!</li> </ul> <h2>10.4.1</h2> <ul> <li>Angular: Detect model() signal outputs (type inference + compodoc autodocs + runtime binding) - <a href="https://redirect.github.com/storybookjs/storybook/pull/34833">#34833</a>, thanks <a href="https://github.com/valentinpalkovic"><code>@valentinpalkovic</code></a>!</li> <li>Build: Upgrade type-fest to latest version 5.6.0 - <a href="https://redirect.github.com/storybookjs/storybook/pull/34791">#34791</a>, thanks <a href="https://github.com/tobiasdiez"><code>@tobiasdiez</code></a>!</li> <li>CLI: Run <code>npx expo install --fix</code> after init for Expo projects - <a href="https://redirect.github.com/storybookjs/storybook/pull/34803">#34803</a>, thanks <a href="https://github.com/ndelangen"><code>@ndelangen</code></a>!</li> <li>CLI: Support <code>peerDependencies</code> in framework detection for component libraries - <a href="https://redirect.github.com/storybookjs/storybook/pull/34516">#34516</a>, thanks <a href="https://github.com/zhyd1997"><code>@zhyd1997</code></a>!</li> <li>Next.js: Add useLinkStatus mock to next/link export mock - <a href="https://redirect.github.com/storybookjs/storybook/pull/34593">#34593</a>, thanks <a href="https://github.com/philwolstenholme"><code>@philwolstenholme</code></a>!</li> <li>Vue3: Specify a specific version for non-dev dependency - <a href="https://redirect.github.com/storybookjs/storybook/pull/34794">#34794</a>, thanks <a href="https://github.com/ScopeyNZ"><code>@ScopeyNZ</code></a>!</li> </ul> <h2>10.4.0</h2> <blockquote> <p><em>AI-assisted setup, change-aware review, and stronger framework support</em></p> </blockquote> <p>Storybook 10.4 contains hundreds of fixes and improvements including:</p> <ul> <li>🤖 Agentic Setup: New CLI workflow for AI-assisted Storybook setup and onboarding</li> <li>🔍 Change review: Sidebar filtering to highlight new, modified, and related stories based on git changes</li> <li>🧭 Sidebar review tools: Status filtering, URL-persisted filters, and clearer review signals in the sidebar</li> <li>⚛️ TanStack React: New <code>@storybook/tanstack-react</code> framework with routing and server function support</li> <li>🧩 React MCP: Faster, more accurate component docgen powered by the TypeScript Language Server</li> <li>📱 React Native: Zero config RN project initialization</li> <li>🤝 Sharing: Easily publish and share your local Storybook with teammates, powered by Chromatic</li> </ul> <!-- raw HTML omitted --> <ul> <li>A11y: Add aria-live announcements via <code>@react-aria/live-announcer</code> - <a href="https://redirect.github.com/storybookjs/storybook/pull/33970">#33970</a>, thanks <a href="https://github.com/copilot-swe-agent"><code>@copilot-swe-agent</code></a>!</li> <li>A11y: Improve boolean control contrast in forced colors mode - <a href="https://redirect.github.com/storybookjs/storybook/pull/34204">#34204</a>, thanks <a href="https://github.com/anchmelev"><code>@anchmelev</code></a>!</li> <li>Actions: Fix state mutation and keep newest actions when limit reached - <a href="https://redirect.github.com/storybookjs/storybook/pull/34286">#34286</a>, thanks <a href="https://github.com/Sidnioulz"><code>@Sidnioulz</code></a>!</li> <li>Addon-Docs: Add Reset story button to re-render stories in docs - <a href="https://redirect.github.com/storybookjs/storybook/pull/34086">#34086</a>, thanks <a href="https://github.com/6810779s"><code>@6810779s</code></a>!</li> <li>Addon-Docs: Avoid rerendering static Source blocks - <a href="https://redirect.github.com/storybookjs/storybook/pull/34206">#34206</a>, thanks <a href="https://github.com/anchmelev"><code>@anchmelev</code></a>!</li> <li>Addon-Vitest: Use Vitest's provide-API for injecting values - <a href="https://redirect.github.com/storybookjs/storybook/pull/34518">#34518</a>, thanks <a href="https://github.com/JReinhold"><code>@JReinhold</code></a>!</li> <li>Agentic Setup: Add --extensive for an extra prompt - <a href="https://redirect.github.com/storybookjs/storybook/pull/34730">#34730</a>, thanks <a href="https://github.com/Sidnioulz"><code>@Sidnioulz</code></a>!</li> <li>Agentic Setup: Allow failed stories to persist - <a href="https://redirect.github.com/storybookjs/storybook/pull/34717">#34717</a>, thanks <a href="https://github.com/Sidnioulz"><code>@Sidnioulz</code></a>!</li> <li>Agentic Setup: Keep sample content if users want onboarding - <a href="https://redirect.github.com/storybookjs/storybook/pull/34704">#34704</a>, thanks <a href="https://github.com/Sidnioulz"><code>@Sidnioulz</code></a>!</li> <li>Agentic Setup: Rework ai-init-opt-in logic - <a href="https://redirect.github.com/storybookjs/storybook/pull/34739">#34739</a>, thanks <a href="https://github.com/Sidnioulz"><code>@Sidnioulz</code></a>!</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/storybookjs/storybook/commit/624e6187fd462e56719cbd80c1b4bfb67b68fc89"><code>624e618</code></a> Bump version from "10.4.2" to "10.4.3" [skip ci]</li> <li><a href="https://github.com/storybookjs/storybook/commit/c89882282295be3bc05b3a366916c53d7a499841"><code>c898822</code></a> Merge pull request <a href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/34496">#34496</a> from NYCU-Chung/fix/docs-blocks-custom-mdx</li> <li><a href="https://github.com/storybookjs/storybook/commit/c920fd08c79c57879fa2ddb4e8538e1684c71ec2"><code>c920fd0</code></a> Merge pull request <a href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/35021">#35021</a> from LongTangGithub/fix/docs-hmr-scroll-to-top</li> <li><a href="https://github.com/storybookjs/storybook/commit/1750494e9f36748b2d89335e77f23f125fc5ec78"><code>1750494</code></a> Merge pull request <a href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/35031">#35031</a> from storybookjs/jeppe/fix-mdx-no-dev-tag</li> <li><a href="https://github.com/storybookjs/storybook/commit/298dea20c6370e5c670178d88a79fc9e9ff436b2"><code>298dea2</code></a> Bump version from "10.4.1" to "10.4.2" [skip ci]</li> <li><a href="https://github.com/storybookjs/storybook/commit/40c81c8187ceed7d09b32a470d6f54c91c3fba72"><code>40c81c8</code></a> Merge pull request <a href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/33534">#33534</a> from storybookjs/copilot/fix-pnpm-command-resolutio...</li> <li><a href="https://github.com/storybookjs/storybook/commit/bfb942b53274b0a1b5c6d76f669cc6f8bf1c6a12"><code>bfb942b</code></a> Merge pull request <a href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/34901">#34901</a> from storybookjs/shilman/fix-csf-export-as-string-l...</li> <li><a href="https://github.com/storybookjs/storybook/commit/fad8dd2b63840548b710457be0bd87034d0f1f3c"><code>fad8dd2</code></a> Merge pull request <a href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/34791">#34791</a> from tobiasdiez/type-fest-upgrade</li> <li><a href="https://github.com/storybookjs/storybook/commit/cc19ae1a2145e8f7cda8dc869f1b90d5346dcedb"><code>cc19ae1</code></a> Bump version from "10.4.0" to "10.4.1" [skip ci]</li> <li><a href="https://github.com/storybookjs/storybook/commit/f8c16d115cfcf0f79125b358266c37e5343bb70d"><code>f8c16d1</code></a> Bump version from "10.4.0-beta.0" to "10.4.0" [skip ci]</li> <li>Additional commits viewable in <a href="https://github.com/storybookjs/storybook/commits/v10.4.3/code/core">compare view</a></li> </ul> </details> <br /> [](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] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
dac36b83ce |
chore(deps-dev): bump @types/aws-lambda from 8.10.161 to 8.10.162 (#21427)
Bumps [@types/aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/aws-lambda) from 8.10.161 to 8.10.162. <details> <summary>Commits</summary> <ul> <li>See full diff in <a href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/aws-lambda">compare view</a></li> </ul> </details> <br /> [](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] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
f8b0dca3f9 |
chore(deps): bump @tabler/icons-react from 3.31.0 to 3.44.0 (#21426)
Bumps [@tabler/icons-react](https://github.com/tabler/tabler-icons/tree/HEAD/packages/icons-react) from 3.31.0 to 3.44.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/tabler/tabler-icons/releases">@tabler/icons-react's releases</a>.</em></p> <blockquote> <h2>Release 3.44.0</h2> <!-- raw HTML omitted --> <h3>18 new icons:</h3> <ul> <li><code>outline/code-ai</code></li> <li><code>outline/email-stamp</code></li> <li><code>outline/foodsteps</code></li> <li><code>outline/git-pull-request-conflict</code></li> <li><code>outline/noise-reduction</code></li> <li><code>outline/photo-alt</code></li> <li><code>outline/pointer-2</code></li> <li><code>outline/pointer-collaboration-2</code></li> <li><code>outline/pointer-collaboration</code></li> <li><code>outline/roulette</code></li> <li><code>outline/scan-cube</code></li> <li><code>outline/sketching</code></li> <li><code>outline/sparkle-2</code></li> <li><code>outline/sparkle-highlight</code></li> <li><code>outline/sparkle</code></li> <li><code>outline/sphere-2</code></li> <li><code>outline/text-scan-ai</code></li> <li><code>outline/vignette</code></li> </ul> <p>Fixed icons: <code>outline/air-balloon</code>, <code>outline/body-scan</code>, <code>outline/chart-sankey</code>, <code>outline/ear-scan</code>, <code>outline/grid-scan</code>, <code>outline/line-scan</code>, <code>outline/object-scan</code>, <code>outline/photo-scan</code>, <code>outline/route-scan</code>, <code>outline/scan-eye</code>, <code>outline/scan-letter-a</code>, <code>outline/scan-letter-t</code>, <code>outline/scan-position</code>, <code>outline/scan-traces</code>, <code>outline/scan</code>, <code>outline/text-scan-2</code>, <code>outline/user-scan</code>, <code>outline/zoom-scan</code></p> <h2>Release 3.43.0</h2> <!-- raw HTML omitted --> <h3>18 new icons:</h3> <ul> <li><code>outline/acorn</code></li> <li><code>outline/acrobatic</code></li> <li><code>outline/banana</code></li> <li><code>outline/brand-audible</code></li> <li><code>outline/building-eiffel-tower</code></li> <li><code>outline/car-door</code></li> <li><code>outline/car-lifter</code></li> <li><code>outline/chocolate</code></li> <li><code>outline/dumbbell</code></li> <li><code>outline/exercise-ball</code></li> <li><code>outline/flood</code></li> <li><code>outline/hula-hoop</code></li> <li><code>outline/leaf-maple</code></li> <li><code>outline/notdef</code></li> <li><code>outline/rugby</code></li> <li><code>outline/taiwan-dollar</code></li> <li><code>outline/target-2</code></li> <li><code>outline/unicycle</code></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/tabler/tabler-icons/commit/6d128ed935d4546607b1e4d5d08c8b27bdbe7758"><code>6d128ed</code></a> Release 3.44.0</li> <li><a href="https://github.com/tabler/tabler-icons/commit/e40738b64486f857128ae58335354681e4e9dc9b"><code>e40738b</code></a> Release 3.43.0</li> <li><a href="https://github.com/tabler/tabler-icons/commit/076f4a9e4d705d6f2cb6fc7f1417501117de12e8"><code>076f4a9</code></a> Release 3.42.0</li> <li><a href="https://github.com/tabler/tabler-icons/commit/9b27b65e3d2e72ff4fd219b2dc21da81ea9cbab8"><code>9b27b65</code></a> Release 3.41.1</li> <li><a href="https://github.com/tabler/tabler-icons/commit/ebad60b50af5ba521245ab982a3fe69df0e5efd9"><code>ebad60b</code></a> Update homepage links in documentation and package files to point to the new ...</li> <li><a href="https://github.com/tabler/tabler-icons/commit/8ed617b1b7153d1d35910cda09861077a6f649b9"><code>8ed617b</code></a> Update README files to wrap images in anchor tags linking to the Tabler Icons...</li> <li><a href="https://github.com/tabler/tabler-icons/commit/ef6e875bbef5252b3627fd1281421b10ddd04a16"><code>ef6e875</code></a> Update dependencies in pnpm-lock.yaml and package.json files (<a href="https://github.com/tabler/tabler-icons/tree/HEAD/packages/icons-react/issues/1497">#1497</a>)</li> <li><a href="https://github.com/tabler/tabler-icons/commit/6cbe8857c8baa758383bb0a9e0f6922cf82da01c"><code>6cbe885</code></a> Release 3.41.0</li> <li><a href="https://github.com/tabler/tabler-icons/commit/19d735e6206997fe06a42f6546188b9678ad57de"><code>19d735e</code></a> Add JSDoc with previews in icons-react (<a href="https://github.com/tabler/tabler-icons/tree/HEAD/packages/icons-react/issues/1472">#1472</a>)</li> <li><a href="https://github.com/tabler/tabler-icons/commit/e4ca37707bd3f165a75ffa050755116ccde5a9a0"><code>e4ca377</code></a> Release 3.40.0</li> <li>Additional commits viewable in <a href="https://github.com/tabler/tabler-icons/commits/v3.44.0/packages/icons-react">compare view</a></li> </ul> </details> <br /> [](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] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
941c9e7586 |
fix: match relation field filters in optimistic & RLS record matchers (#21301)
Closes #21345. ## What It should be caused by the GraphQL optimistic query. `isRecordMatchingFilter` (front, Apollo optimistic cache) and `isRecordMatchingRLSRowLevelPermissionPredicate` (server, RLS) now handle a view filter that targets a **relation field object** (e.g. an "is (not) empty" filter on a relation) by matching against the related record id, instead of throwing. <img width="3436" height="2250" alt="CleanShot 2026-06-08 at 06 44 01@2x" src="https://github.com/user-attachments/assets/1dccbd1e-133c-4f4a-a0a9-7ccd02a9a0ae" /> <img width="1496" height="380" alt="CleanShot 2026-06-08 at 06 45 34@2x" src="https://github.com/user-attachments/assets/e5c2071e-69df-4d99-bb7d-66d503a175b6" /> ## Why Both matchers only implemented the relation **join column** branch (`fooId`) and threw `Not implemented yet, use UUID filter instead on the corresponding "fooId" field` for the relation field itself (`foo`). In practice the UI still stores relation filters keyed on the relation object, so any view with such a filter made every create/update/delete on that object throw: the optimistic effect re-evaluates all active view filters against the changed record and hits the unimplemented branch. Repro: add a self-relation field on People (e.g. "Referred By"), put it in a view filter as "is not empty", then edit any Person. The optimistic update throws. ## Behaviour change | Scenario | Before | After | |---|---|---| | View filter on relation object (`referredBy is not empty`), then edit a record | Throws `Not implemented yet...` | Record matched by related id; update succeeds | | Filter on relation join column (`referredById`) | Worked | Unchanged | ## Test plan ```bash cd packages/twenty-front && npx jest isRecordMatchingFilter cd packages/twenty-server && npx jest is-record-matching-rls-row-level-permission-predicate ``` - [x] Front: relation `is empty` / `is not empty` / `in` match by related id; join-column path still passes (20/20) - [x] Server: relation `is empty` / `is not empty` match by related id (9/9) - [x] `lint:diff-with-main` clean on both packages Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Félix Malfait <felix.malfait@gmail.com> |
||
|
|
61b76b681e |
fix: i18n missing hardcoded strings in settings (#21424)
## What Two user-visible strings in the Settings area were never wrapped with Lingui, so they were excluded from i18n extraction and shipped untranslated regardless of the selected language: - **"Remote"** — the type chip shown for remote objects in **Settings → Data Model** (`SettingsItemTypeTag`) - **"Done"** — the confirm button of the fields configuration group rename input (`FieldsConfigurationGroupRenameInput`) ## Changes - Wrap the `Chip` `label` with the `t` macro in `SettingsItemTypeTag.tsx` (the `placeholder` / `placeholderColorSeed` props are intentionally left as-is — they drive the avatar initial and color hash, not display text). - Wrap the `Button` `title` with the existing `t` from `useLingui()` in `FieldsConfigurationGroupRenameInput.tsx`. - Add the corresponding source entries to `en.po` so Crowdin can propagate the translations to all supported locales. Both follow i18n patterns already used throughout the codebase — these two were simply missed. ## Screenshots Both components rendered via Storybook (source `en` locale) after the change — the strings now resolve through Lingui's `t` macro without breaking rendering:  ## How to test 1. Switch the workspace language to a non-English locale. 2. Go to **Settings → Data Model** with a remote object present → the type chip reads "Remote" translated. 3. Rename a fields configuration group → the confirm button reads "Done" translated. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
615c3d8dbe |
security: drop end-of-life apollo-server-core (#735, #736) (#21418)
Closes the `apollo-server-core` alerts (**#735**, **#736**) by
**removing the dependency** — no Apollo migration, no resolution.
### Why these were flagged "no patch available"
`apollo-server-core` is **Apollo Server v3, which is end-of-life** (per
its npm deprecation notice). No patched release of this package will
ever exist — the CVE fix lives only in the renamed `@apollo/server` v4
package.
### Why we can just drop it
twenty-server **doesn't use Apollo Server** — its GraphQL runtime is
**GraphQL Yoga** (`YogaDriver`). `apollo-server-core` was imported for
one thing only: the `gql` template tag in **6 integration test files**.
`gql` from `graphql-tag` is identical (apollo-server-core merely
re-exports it), `graphql-tag` is **already a direct dependency**, and
**15 other twenty-server tests already import `gql` from it**.
### Change
- Swapped `import { gql } from 'apollo-server-core'` → `import { gql }
from 'graphql-tag'` in the 6 test files.
- Removed `apollo-server-core` from
`packages/twenty-server/package.json`.
- Result: `apollo-server-core` (and its transitive surface) is gone from
`yarn.lock` entirely.
### Verification
- `yarn install --immutable` ✓
- No `apollo-server-core` references remain in source or lockfile
- Integration tests (which exercise the swapped `gql` imports) run in CI
|
||
|
|
1b26061992 |
security: close ws & file-type alerts via parent upgrades (no resolution) (#21417)
Closes 3 more Dependabot alerts via **parent upgrades only — no `resolutions`**. ### Closes - **ws #1238** (`>= 8.0.0, < 8.20.1`) - **file-type #622** (`>= 13.0.0, < 21.3.1`) and **#635** (`>= 20.0.0, <= 21.3.1`) ### How - **ws** — two parents pinned vulnerable copies; both have safe releases: - `wrangler`/`miniflare`: `ws 8.18.0 → 8.20.1` - `socket.io`/`engine.io`/`socket.io-adapter`: `ws ~8.17.1 → ~8.20.1` - Every `ws` now resolves `>= 8.20.1` (or non-vulnerable 6.x/7.x). - **file-type** — bumped `@swc/cli ^0.7.10 → ^0.8.1`, which pulls the newer `@xhmikosr` bin-wrapper → downloader → decompress/archive-type chain (`file-type ^20.5.0 → ^21.3.x`). `@swc/cli` is a devDependency that isn't directly invoked (nx's swc compiler uses `@swc/core`), so this is dev-tooling-only with no runtime impact. ### Verification - `yarn install --immutable` ✓ (passes the hardened 3-day age gate) - No vulnerable `ws` (`< 8.20.1`) or `file-type` (`20.x`) remains in `yarn.lock` ### Remaining open alerts (not closeable without a `resolution` or a major migration) - `apollo-server-core` (#735/#736) — needs Apollo Server 3 → 4 - `webpack-dev-server` (#1237/#691/#692) — `@electron-forge/plugin-webpack` only pins `^4` (no stable v5 consumer); dev-tooling - `qs` (#1305) — `express`/`body-parser` pin `~6.14`, which has no patched release - `uuid` (#1289) — spread across many `^8`/`^9`/`^10` transitives; v11 is a breaking jump - `postcss` (#1061) — bundled exact by `next` and `styled-components` - `ajv` (#481) — `@cyntler/react-doc-viewer` pins `^7` (latest still does) |
||
|
|
868cb02e45 |
security: close lodash CVEs (#824/#823/#385) via parent upgrades, no resolution (#21414)
Closes the remaining lodash Dependabot alerts **without any `resolutions` override** — by upgrading the parent packages that pinned the vulnerable lodash. Every `lodash` in the tree now resolves to **4.18.1**. ### Closes - **#824 — `_.template` code injection (HIGH)** - #823 / #385 — prototype pollution in `_.unset` / `_.omit` ### What changed (4 parents pinned vulnerable lodash 4.17.x; all upgraded, no override) - **`@stoplight/spectral-functions`** → 1.10.2 (in-range; now uses `lodash ^4.18.1`) - **`zapier-platform-core`** 15.5.1 → 19.0.0 — aligns with the already-present `zapier-platform-cli ^19` (they were mismatched). v19 tightened the `Bundle` types, so 3 call sites now type their bundle as `Bundle<InputData>` and the test bundle includes the new `meta` fields. - **`@graphql-codegen`** → `cli 6.3.1`, `typescript 5.0.10`, `typescript-operations 5.1.0`, `typed-document-node 6.1.8`. These depend on `@graphql-codegen/plugin-helpers ^6.3.0`, the release that dropped lodash. (Stayed on the 6.x/5.x line on purpose — 7.x changes generated output far more.) ### About the generated-file changes — they are cosmetic, not real changes The codegen bump touches one generated file. **Verified there is zero semantic change:** - Only `src/generated-metadata/graphql.ts` changes. `src/generated/graphql.ts` (data) and `src/generated-admin/graphql.ts` (admin) are **byte-identical**. - Same 1,638 type declarations before and after — none added, none removed. - After stripping whitespace and union pipes, the file is **byte-for-byte identical** — no type, field, or union member changed. The entire diff is one formatting change from `typescript-operations@5.x`: multi-member union types are now printed multi-line with a leading `|` instead of on one line — which TypeScript treats identically: ```ts // before payload?: { …ObjectMetadata… } | { …Path… } | null // after payload?: | { …ObjectMetadata… } | { …Path… } | null ``` Only metadata is affected because only its operations select GraphQL union types. To keep generated types otherwise behavior-identical, `defaultScalarType: 'any'` was added to the three codegen configs (codegen 6 would otherwise default unmapped scalars to `unknown`). ### Verification - `twenty-front` typecheck ✓, `twenty-zapier` typecheck ✓ - `yarn install --immutable` ✓ (passes the hardened 3-day age gate) - CI green — including the `graphql:generate` freshness check, which regenerates against the canonical schema and confirms the committed output is exactly what codegen produces - No `lodash@4.17.x` remains anywhere in `yarn.lock` Supersedes #21411 (which closed these via a one-line resolution). |
||
|
|
6e147a548b |
security: clear twenty-apps & seed-dependencies CVE alerts (#21410)
Clears the Oneleet/dependency CVE alerts from the `twenty-apps` example/internal app lockfiles and the application-package `seed-dependencies` template — all via parent/direct dependency upgrades, **no `resolutions` overrides**. ## Lock refresh (non-breaking, within existing ranges) - **postcss** 8.5.8/8.5.9 → 8.5.15 — CVE-2026-41305 — postcard, hello-world, self-hosting - **ip-address** 10.1.0 → 10.2.0 — CVE-2026-42338 — postcard, hello-world, self-hosting, twenty-for-twenty - **yaml** 1.10.2 → 1.10.3 — CVE-2026-33532 — call-recording ## seed-dependencies (direct/parent bumps) - **uuid** `^10.0.0 → ^11.1.1` (direct) — CVE-2026-41907 - **body-parser** `^1.20.4 → ^1.20.5`, which pulls **qs** 6.15.2 — CVE-2026-8723 - **socks** 2.8.3 → 2.8.9 (refresh), which pulls **ip-address** 10.2.0 — CVE-2026-42338 ## twenty-for-twenty - **resend** 6.12.0 → 6.12.4 (refresh): 6.12.4 drops the `svix` dep that pulled the vulnerable **uuid** 10.0.0, leaving only uuid 13.0.2 — CVE-2026-41907 All flagged packages were transitive (except the direct seed-deps `uuid`); no app source changes. |
||
|
|
a825dcf2cc |
security: clear 8 Dependabot alerts via transitive/parent bumps (no resolutions) (#21409)
Clears 8 Dependabot alerts via in-range transitive/parent bumps and one dead-dependency removal. **No `resolutions` overrides** were used — every fix is a real version bump within existing semver ranges or a parent upgrade. ### Root `yarn.lock` - **react-router** 6.30.3 → 6.30.4 (open redirect via protocol-relative URL) — pulled through react-router-dom, ranges unchanged — alert #1382 - **yaml** 2.8.1 → 2.9.0 (stack overflow on deeply nested collections) — alert #734 - **uuid** `^13.0.0` → 13.0.2 in twenty-sdk + create-twenty-app (buffer bounds check) — alert #1164 - **ip-address** `^9.0.5` dropped by bumping **socks** 2.8.3 → 2.8.9 (now depends on `ip-address ^10.1.1`, which is unaffected) — alert #1171 ### `seed-dependencies` lockfile - **uuid** `^10.0.0` → `^11.1.1` (direct dep; removed now-redundant `@types/uuid` since uuid v11 ships its own types) — alert #1287 - **ip-address** `^9.0.5` dropped via the same socks bump — alert #1170 ### `twenty-for-twenty` lockfile - **resend** bumped to 6.12.4 (`^6.12.0` range kept), which drops its `svix@1.90.0 → uuid@^10` transitive chain — alert #1278 ### `twenty-companion` - Removed the unused **simplemde** dependency. The note editor loads SimpleMDE from a CDN `<script>` tag and never imports the npm package; `easymde` (its maintained fork) is already a dependency — alert #690 ### Not addressed here The remaining alerts can't be closed without `resolutions` overrides (deliberately avoided in this PR) or a larger migration: - **qs** (#1305, #1304), **lodash** (#824 high / #823 / #385), **ws** (#1238), **postcss** (#1061) — vulnerable copies are pinned exact / bundled by parents (express, body-parser, @nestjs/*, next, styled-components, zapier) with no in-range patch. - **webpack-dev-server** (#1237/#692/#691) — pinned by `@electron-forge/plugin-webpack` (still on v4); dev-tooling only. - **uuid <11.1.1** (#1289) — spread across `^3`/`^8`/`^9` transitive ranges; reaching v11 is a breaking jump. - **apollo-server-core** (#735/#736) — requires an Apollo Server 3 → 4 migration. |
||
|
|
e357116024 |
fix(ui): freeze framer-motion in Argos runs to stop flaky visual diffs (#21412)
## Problem twenty-ui Argos visual tests are flaky — `Loader`, `CircularProgressBar`, `ProgressBar` get flagged as changed with no relevant code change. ## Cause Argos screenshots use Playwright's `animations: "disabled"`, which only freezes CSS animations. These components animate via framer-motion (main-thread rAF), so each run captures a different frame. ## Fix Set `MotionGlobalConfig.skipAnimations = true` in the Vitest setup of both UI packages — freezes framer-motion to a deterministic state during Argos runs only (interactive Storybook unaffected). Removes the now-redundant per-story `disableSnapshot` opt-outs. Note: removing `CircularProgressBar`'s opt-out adds new baselines (one-time Argos approval, not flakiness). |
||
|
|
2514cab860 |
fix(server): include relation join column names in updatedFields of update events (#21405)
## Context Since #21052, update-event diffs are keyed by the relation field name (e.g. `company`) instead of the join column name (e.g. `companyId`). `updatedFields` is derived from the diff keys, so any **workflow database-event trigger** (or webhook) configured with a field filter on a relation join column **silently stopped firing** — no run is created at all. We hit this in production: a `cloudWorkspace.updated` trigger filtered on `twentyContactId` stopped creating runs the same day #21052 was deployed. Updating the record's relation produced `updatedFields: ["twentyContact"]`, which no longer matches the stored settings `fields: ["twentyContactId"]` in `WorkflowDatabaseEventTriggerListener.shouldTriggerJob`. ## Solution Keep the diff keyed by relation field name (the timeline rendering from #21052 relies on it — adding both keys to the diff would display relation changes twice), but expose **both** the relation field name and its join column name in `updatedFields`: - New `computeUpdatedFieldsFromDiff()` in `object-record-changed-values.ts`: expands MANY_TO_ONE relation diff keys with their join column name. - Used in `formatTwentyOrmEventToDatabaseBatchEvent` for UPDATED/DELETED/RESTORED and UPSERTED events instead of `Object.keys(diff)`. This restores matching for pre-existing trigger/webhook configurations (join column names) while keeping configurations using relation field names working. ## Test plan - [x] Unit tests: relation diff keyed by relation name; `updatedFields` contains both `company` and `companyId` - [x] End-to-end util test on UPDATED event: `updatedFields: ['company', 'companyId']`, diff keyed by `company` - [x] Downstream consumer specs pass (workflow trigger listener, webhooks, subscriptions, logic-function triggers) - [x] Verified against the production workspace that a `twentyContactId` update currently produces no workflow run with the old behavior |
||
|
|
6971d6fa95 |
Prevent self-hosting app from re-matching/re-creating people on no-op updates (#21406)
The match-telemetry-event-with-people logic function triggers on selfHostingUser.* (both created and updated) and unconditionally wrote personId back to the record on every run. Since the handler's own write produces an updated event — and the telemetry webhook also updates unrelated fields (name, serverUrl, etc.) on returning signups — the matching logic re-ran unnecessarily, querying people and writing on each pass. This adds an early-return guard so the handler only does work when there's actually something to match: Skip when the selfHostingUser is already linked (personId set) and the primary email hasn't changed. Still (re)match on first link and on genuine email changes — the legitimate reasons for listening on updated. The guard reads before.email.primaryEmail via an 'before' in properties narrowing so it stays type-safe across the create/update event union. |
||
|
|
7258722754 |
security: upgrade @nestjs/graphql 12→13 + @ptc-org/nestjs-query 4→9 (+ @nestjs/config 4) (#21402)
## What Upgrades the NestJS GraphQL stack to clear the High **`ws`** alert (GHSA-3h5v-q93c-6h6q) and modernize off two heavily-patched majors. `@nestjs/graphql@13` pulls `ws@8.20.1` (was 8.16.0). This had to be a **coordinated** upgrade: `@ptc-org/nestjs-query@4.2.0` doesn't support `@nestjs/graphql@13`, so all three move together. | Package | From → To | |---|---| | `@nestjs/config` | 3.3.0 → ^4.0.4 | | `@nestjs/graphql` | 12.1.1 → ^13.4.2 | | `@ptc-org/nestjs-query-{core,graphql,typeorm}` | 4.x → ^9.4.0 | ## The tricky bits - **Re-ported the custom `@nestjs/graphql` patch onto v13.** v13 rewrote the schema builder and added its *own* native multi-schema support (`includeModules`, native `clear()`). Twenty's patch (`resolverSchemaScope` + `computeReachableTypes` — the core/metadata/admin split) is re-merged into v13's new `generate(options, includeModules, reachableTypes)` flow, with a link-preserving `storage.clear()` so cross-schema `resolveType` closures keep working. - **Re-ported the `@ptc-org` patch onto 9.4.0**: removes the `@shareable` federation directive from built-in connection/response types, **and** adds a `.js` extension to its extensionless deep import of `@nestjs/graphql` internals — which v13's new `"exports"` map otherwise rejects at runtime (this was the boot blocker). - **`AppTokenService`**: nestjs-query 9 requires custom services to inject their repo and `super(repo)` it (added an `@InjectRepository` constructor). - **`gridPosition` input fields**: dropped the `deprecationReason` (a *required* input field can't be `@deprecated` under the upgraded graphql) — fields keep their original nullability, so the **schema is unchanged**. - **Service specs**: nestjs-query 9's `TypeOrmQueryService` reads the repo's driver/metadata at construction, so the mocked repos now include `manager`/`metadata`. ## Verification - `nx typecheck twenty-server`: **0 errors**; lint clean - Server boots; **all 3 GraphQL schemas** (`/graphql`, `/metadata`, `/admin-panel`) generate and respond `200` - `graphql:generate` for all 3 schemas is **byte-identical** to before the upgrade (the reachable-types re-port is faithful) - **108 service unit tests pass** (incl. all 6 `TypeOrmQueryService` services) - `ws@8.16.0` gone (now 8.17.1 + 8.18.0); `yarn install --immutable` clean ## Note on lodash `lodash@4.17.21` still remains via `zapier-platform-core` (runtime) and `@stoplight/spectral`, so the lodash alert is **reduced but not fully cleared** by this PR — it needs those separate sources addressed (or a resolution). |
||
|
|
f1c7aecadb |
fix(front): sanitize optimistic input when creating a record (#21076)
## Summary Closes #15800. Clicking **+ Add New** from a relation cell to create a **Task** or **Note** (e.g. from a custom object's Tasks/Notes section in the list view) throws: ``` Uncaught (in promise) Error: Should never occur, encountered unknown fields name in objectMetadataItem task ``` ### Root cause `useCreateOneRecord` computes a **sanitized** input (with `sanitizeRecordInput`, which strips fields that don't belong to the object) and sends it to the GraphQL mutation. But it still feeds the **raw** input to the optimistic cache computation: ```ts const sanitizedInput = { ...sanitizeRecordInput({ objectMetadataItem, recordInput }), id: idForCreation }; const optimisticRecordInput = computeOptimisticRecordFromInput({ ... recordInput: { ...computeOptimisticCreateRecordBaseRecordInput(objectMetadataItem), ...recordInput, // ← raw input, may contain fields unknown to the object id: idForCreation, }, ... }); // mutation uses the sanitized input: mutate({ variables: { input: sanitizedInput } }); ``` `computeOptimisticRecordFromInput` asserts that every input key maps to a field on the object and `throw`s otherwise. So when the create input carries a field the target object doesn't have (the relation-create path passes a `name`, but Task/Note use `title`), the optimistic step throws before the mutation ever runs. `useCreateManyRecords` does **not** have this problem — it already feeds the sanitized input to `computeOptimisticRecordFromInput`. ### Fix Feed the sanitized input to the optimistic computation in `useCreateOneRecord`, exactly as `useCreateManyRecords` does: ```ts recordInput: { ...computeOptimisticCreateRecordBaseRecordInput(objectMetadataItem), ...sanitizedInput, }, ``` This is safe and behavior-preserving for valid creates: `computeOptimisticRecordFromInput` only ever reads *known* fields (it iterates the object's field metadata); unknown input keys never contribute to the optimistic record — they only trip the invariant. Relations are resolved through their join columns, which sanitization keeps. ## Test plan - [x] `npx oxlint --type-aware` — passes on the changed files - [x] `npx oxfmt --check` — passes - [x] `tsc --noEmit` — no type errors in the changed files - [x] `npx jest computeOptimisticRecordFromInput` — passes, including a new case asserting that input which has been through `sanitizeRecordInput` no longer trips the "Should never occur, encountered unknown fields" invariant (the existing test already covers the raw input throwing) - [ ] Manual: from a custom object's Notes/Tasks relation, use **+ Add New** to create a Note/Task — no error, the record is created ### Note on test scope The crash only reproduces through the full relation-create flow with live metadata; at the hook level in jsdom the create resolves regardless, so a hook-level test would not guard the regression. The added test instead locks the underlying mechanism the fix relies on — that sanitized input is safe for `computeOptimisticRecordFromInput` — alongside the existing test that proves raw unknown fields throw. --------- Co-authored-by: Charles Bochet <charles@twenty.com> |
||
|
|
09cc0c6f21 |
security: clear yeoman-environment High alert via resolution to 6.0.1 (#21400)
## What
Clears the `yeoman-environment` High alert (GHSA-vv9j-gjw2-j8wp —
*arbitrary package install without confirmation*).
`yeoman-environment@4.4.3` is exact-pinned by `zapier-platform-cli`.
**There is no parent-bump fix**: `zapier-platform-cli@19.0.0` is the
latest stable and still pins 4.4.3 — cli 17→3.19.3, 18/19→4.4.3, all in
the vulnerable `< 6.0.1` range.
## Why a resolution (and why it's safe for us)
zapier-cli **lazy-loads** `yeoman-environment` via dynamic `import()`
*only* inside its `init` and `pull` scaffolding command handlers.
twenty-zapier only ever runs `validate` / `versions` / `push` /
`promote` (see `project.json`), so the vulnerable code path is never
imported here.
Since no zapier-cli release carries the fix, the only way to remove the
vulnerable version is a resolution:
```jsonc
"yeoman-environment": "6.0.1"
```
The 4→6 major only affects zapier-cli's `init`/`pull` (which we never
invoke); all our commands are unaffected.
## Verification
- `yeoman-environment` now **6.0.1** (no 4.4.3 in the lockfile)
- `nx build` + `typecheck` twenty-zapier ✅
- `zapier-platform validate` → **35/35 checks pass** with yeoman 6
forced
- `yarn install --immutable` clean
|
||
|
|
e53f877559 |
security: clear picomatch High alert via @angular-devkit/core resolution (#21398)
## What Clears the root `picomatch` High alert (GHSA-c2c7-rcm5-vvqj, range `>=4.0.0 <4.0.4`). `picomatch@4.0.2` is exact-pinned by `@angular-devkit/core@19.2.x`, pulled by NestJS's codegen tooling (`@nestjs/schematics` + `@nestjs/cli` use Angular's schematics engine). angular-devkit/core backported the picomatch 4.0.4 fix in **19.2.24**. ## Why a resolution here (not a parent bump) The clean parent-bump — bumping `@nestjs/cli` so it pulls patched angular-devkit — **breaks `nest build`**. `@nestjs/cli` 11.0.17+ has an SWC-builder output-path change: it writes compiled files under `dist/`**`src/`**`…` instead of `dist/…`, breaking every `node dist/<path>` reference (`main`, `command`, worker, `database/scripts/*`). This is what failed in the first revision of this PR (`Cannot find module '…/dist/database/scripts/truncate-db.js'`). - The cli's angular-devkit pin is **exact**, so there's no clean refresh. - Every `@nestjs/cli` ≥11.0.17 (incl. the latest 11.0.23) has the regression. - There's no stable NestJS 12/13 to move to (12 is alpha-only). - `tsconfig` `rootDir` doesn't override the output base. So a one-patch resolution is genuinely the cleaner, lower-risk fix: ```jsonc "@angular-devkit/core": "19.2.24" // patch within the same 19.2 minor ``` `@nestjs/cli` stays 11.0.16 (correct `dist/` layout), and picomatch resolves to 4.0.4. ## Verification - picomatch now **4.0.4 + 2.3.2** (both patched); no 4.0.2 in the lockfile - `nx build twenty-server` emits `dist/main.js` and `dist/database/scripts/*.js` at the correct paths (the prior CI failure) - `yarn install --immutable` clean |
||
|
|
402e4b6a78 |
fix(docker): upgrade Alpine system OpenSSL libs to patched 3.5.7-r0 (#21399)
## Context Image scanner flags the `prod-twenty` server image for OpenSSL CVEs. The image carries **two independent OpenSSL surfaces**, and they are fixed by different levers: | Surface | Version (before) | Used by app at runtime? | Fix lever | |---|---|---|---| | **Node-bundled** OpenSSL | `3.5.6` | ✅ yes (Node links its own) | Node base bump (separate; `24.16.0-alpine3.23` is already the latest digest) | | **Alpine system** `libcrypto3`/`libssl3` | `3.5.6-r0` | ❌ no (`ldd node` shows no link) | **this PR** — apk upgrade to `3.5.7-r0` | The pinned `node:24.16.0-alpine3.23` base bakes `libcrypto3`/`libssl3` at `3.5.6-r0`, while the Alpine v3.23 repo now ships `3.5.7-r0`. These libs ship as deps of `apk-tools`/`libapk`/`ssl_client` (so they can't be removed), and Node does not link them — but the scanner still flags them by version. ## Change Pin a patched floor (`libcrypto3>=3.5.7-r0`, `libssl3>=3.5.7-r0`) in the `apk add` lines of both runtime stages (`twenty-server` and `twenty-app-dev`) so apk upgrades them at build time. Same technique already used for `curl`/`nghttp2-libs`/`postgresql18-client` (#20805). ## Verification - Built `--target twenty-server`; image builds clean. - On the built image, `libcrypto3` and `libssl3` resolve to `3.5.7-r0`. - Node-bundled OpenSSL is unaffected by this change (separate surface, no Dockerfile-side upgrade path until a newer Node release links a patched OpenSSL). |
||
|
|
1c3ae92c04 |
fix(server): prevent SSE stream teardown errors from crashing all pods (#21395)
## Context
In prod-eu, **all `twenty-server` API pods crash simultaneously**
several times per hour (then restart in lockstep) since ~Jun 2. Each
crash is an **unhandled promise rejection** in SSE event-stream teardown
— `exitCode=1`, identical stack on every one of the 7 pods:
```
Error: Failed to acquire lock for key: workspace:<id>:activeStreams
at CacheLockService.withLock (cache-lock.service.ts:53)
at async EventStreamService.destroyEventStream (event-stream.service.ts:75)
at async cleanup (wrap-async-iterator-with-lifecycle.ts)
at async Object.return (wrap-async-iterator-with-lifecycle.ts)
at async Object.cancel (graphql-yoga/.../result-processor/sse.js:68)
```
### Mechanism
1. A busy workspace's SSE clients reconnect (no client backoff), so
connect/disconnect contend on a **single per-workspace Redis lock**
`workspace:<id>:activeStreams`.
2. Under contention `CacheLockService.withLock` exhausts its retries and
**throws**.
3. In the `destroyEventStream` teardown path the throw escapes
`wrapAsyncIteratorWithLifecycle`'s `cleanup()` — `return()` does `try {
await cleanup() } finally { … }` and does **not** catch a cleanup throw.
4. graphql-yoga invokes this from `cancel()` as a **fire-and-forget**
`Promise.all` on connection abort. With **no global `unhandledRejection`
handler**, Node's default policy terminates the process with **exit code
1**.
5. The crash drops all that pod's SSE clients → they reconnect to
surviving pods → contention moves there → the whole fleet crashes
together → restarts → reconnect storm → repeats (~14 min period,
matching the metrics).
## Changes
Crash-stopping hotfix (defense in depth). Does **not** change the
locking design or client reconnect behavior — see follow-ups.
- **`wrapAsyncIteratorWithLifecycle`**: `onCleanup()` is now best-effort
— wrapped in try/catch so teardown can never reject out of
`next()`/`return()`/`throw()`. The original iterator error is still
rethrown unchanged. Adds an `onCleanupError` hook so the swallowed error
is still reported.
- **`EventStreamResolver`**: wires `onCleanupError` to
`ExceptionHandlerService.captureExceptions` (→ Sentry) with workspace +
channel context, so these failures stay visible.
- **`main.ts`**: registers a global `process.on('unhandledRejection')`
that reports via `ExceptionHandlerService` (Sentry) instead of letting
Node terminate. Registering the listener also suppresses Node's default
process-termination. Non-`Error` reasons are formatted with
`util.inspect` (per Copilot review) so Sentry gets a readable message
rather than `[object Object]`.
## Verification
The fix was checked against the exact crash path — a wrapped iterator
whose `onCleanup` rejects:
- `return()` (graphql-yoga's `cancel()` path) **resolves** instead of
rejecting → no unhandled rejection.
- `next()` on a completed stream **resolves** despite a rejecting
cleanup.
- A genuine iterator error still surfaces on `next()` (cleanup failure
doesn't mask it).
- `onCleanupError` receives the original `Error`.
All four pass. `nx lint twenty-server` + `oxfmt` clean; no new `tsc`
errors in the changed files.
## Follow-ups (not in this PR)
- Remove the unnecessary `withLock` around the already-atomic Redis
`SADD`/`SREM` in `event-stream.service.ts` (the contention source).
- Restore exponential backoff + jitter on the frontend SSE reconnect
(regressed in #21061) to stop the thundering herd.
- Infra: make `/healthz` a meaningful liveness signal and add
`maxUnavailable` + a PodDisruptionBudget so pods can't all die together.
|
||
|
|
3655942fa4 |
fix: reload stale clients on any older app version, not just major (#21011)
## Context
The GraphQL error handler emits an `APP_VERSION_MISMATCH` error
(surfaced on the client as a "your app version is out of date, please
refresh" prompt) when a client's app version is behind the server's.
Today that comparison only fires when the **major** version differs:
```ts
const frontEndMajor = semver.parse(frontEndAppVersion)?.major;
const backendMajor = semver.parse(backendAppVersion)?.major;
if (isDefined(frontEndMajor) && isDefined(backendMajor) && frontEndMajor < backendMajor) { ... }
```
Twenty ships schema changes in minor and patch releases too. A tab left
open across a minor/patch deploy keeps sending GraphQL documents built
against the previous schema. If a field was removed or renamed, those
operations fail with opaque field-level errors and the user never gets
the refresh prompt — a hard reload is the only recovery.
## What this does
- **Server:** fires the mismatch whenever the client version is strictly
older than the server (`semver.lt`), regardless of which version
component changed.
- **Client:** `onAppVersionMismatch` now reloads the page once (in
addition to the existing snackbar) to pull the current `index.html` and
hashed assets, guarded by a short `sessionStorage` window so a
still-stale reload can't cause a refresh loop.
## Notes
- No behavior change for clients on the same or newer version.
- Relies on the existing `x-app-version` header and `APP_VERSION` config
that already drive this check.
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
|
||
|
|
abbb1bdf98 |
security: clear serialize-javascript High alert (terser-webpack-plugin refresh) (#21397)
## What
Clears the High `serialize-javascript` alert (GHSA-5c6j-r48x-rmvq) — a
plain in-range refresh, **no resolution**, only `yarn.lock` (net −22
lines).
`serialize-javascript@6.0.2` was pulled only by
**`terser-webpack-plugin@5.3.16`** (webpack's minifier). The patched
line (7.x) is outside terser's old `^6.0.2` range — but
**`terser-webpack-plugin@5.6.1` dropped the `serialize-javascript`
dependency entirely**, and webpack already requests
`terser-webpack-plugin@^5.3.16` (which allows 5.6.1).
So `yarn up -R terser-webpack-plugin` → 5.6.1 removes the vulnerable
6.0.2; only the patched **7.0.5** (twenty-website's direct dep) remains.
## Verification
- No `serialize-javascript@6.x` left in the lockfile
- `nx build twenty-server` (exercises the `@nestjs/cli` webpack/terser
path) ✅
- `yarn install --immutable` clean
|
||
|
|
3ee82c7a3c |
security: clear koa High alert by bumping nx 22.5.4 → 22.7.5 (#21396)
## What Clears the High `koa` alert (GHSA-7gcc-r8m5-44qm) — via a parent bump, **no resolution**. `koa@3.0.3` was a deep transitive of the module-federation build tooling: `koa` ← `@module-federation/dts-plugin@0.21.4` ← `@module-federation/enhanced@0.21.4`, pulled via **two** paths — `@nx/module-federation@22.5.4` (directly) and `@module-federation/node` (pinning the old `enhanced@0.21.x` line). `@module-federation/dts-plugin` 2.x dropped koa, so the fix moves both paths onto the 2.x line: - bump `nx` + `@nx/{jest,js,react,storybook,vite,web}` **22.5.4 → 22.7.5** (minor): `@nx/module-federation@22.7.5` uses `@module-federation/enhanced@^2.3.3` - refresh `@module-federation/node` within its existing `^2.7.21` range → 2.7.44, which uses `@module-federation/enhanced@2.5.1` Result: `@module-federation/enhanced` + `dts-plugin` collapse to 2.5.1, and **koa is gone from the tree entirely** (net −309 lockfile lines after dedup). ## Verification (nx is the monorepo task runner — verified broadly) - `nx build` + `typecheck`: twenty-shared, twenty-ui, twenty-front ✅ - `nx typecheck twenty-server` ✅ - `nx test twenty-shared` ✅ - `yarn install --immutable` clean The only `package.json` change is the nx version bump; everything else is lockfile. |
||
|
|
99bd1daaec |
feat(twenty-partners): website field + restructured partner & opportunity views (#21385)
## What Twenty Partners app — partner enrichment + a simpler, partner-centric view structure. **Partner** - New `website` (LINKS) field. - Icons for the opportunity `partner` relation and `matchStatus` fields (were the default "123"). **Partner views** (Partners folder → Applications / Validated / All) - **Applications**: grouped by validation stage, showing Application + Potential; columns Categories / Skills / Type of Team / Languages / Country / LinkedIn. - **Validated**: grouped by availability; columns harmonized with Applications, plus Partner Tier. - Wider Name / Categories columns. **Opportunity pipeline** (Pipeline folder, simplified by partner presence) - `OPP without partner` / `OPP with partner` tables (filtered on partner *is empty* / *is not empty*), `OPP all`, and a kanban **board** grouped by match status. - Sort by match status (uses the option position, i.e. pipeline order). - Removes the previous matching views (waiting-for-match, matches-overview, partner-deals). ## Version Patch bump `0.4.2 → 0.4.3` (relative to main). |
||
|
|
232ca8eec2 |
security: clear happy-dom High alerts by upgrading wyw-in-js 0.7 → 1.1 (#21394)
## What Clears the 2 High `happy-dom` alerts (GHSA-w4gp-fjgq-3q4g, GHSA-6q6h-j7hj-3r64) via a parent bump — **no resolution**. `happy-dom@15.11.7` came from **`@wyw-in-js/transform@0.7.0`** (Linaria's CSS transform), pinned by a root resolution + a local `.yarn` patch and requested by `@wyw-in-js/vite@^0.7.0` in twenty-front + twenty-ui-deprecated. - `@wyw-in-js/vite` `^0.7.0` → `^1.1.0` (twenty-front, twenty-ui-deprecated) - `@wyw-in-js/babel-preset` `^0.6.0` → `^1.1.0` (twenty-ui-deprecated) - **drop the `@wyw-in-js/transform` 0.7.0 resolutions + the `.yarn` patch** — the patch added a `visited` cycle-guard to `TransformCacheCollection.invalidateIfChanged`, which is **already upstream** in transform 1.1.0, so it's obsolete. `@wyw-in-js/transform` now resolves to **1.1.0** (→ happy-dom 20.10.2) and 0.8.1 (website, unchanged, → happy-dom 20.8.9). The vulnerable 0.7.0/15.11.7 are gone. ## Required config change wyw-in-js 1.x resolves modules in its CSS pre-build via vite's `resolve.alias` instead of `vite-tsconfig-paths`. So twenty-front's `@/` and `~/` tsconfig path aliases are mirrored into `vite.config` `resolve.alias` — otherwise the CSS evaluator throws `Cannot find module '@/...'` for aliased imports used inside `styled` definitions. ## Verification - happy-dom now **20.8.9 + 20.10.2** (both patched); no 15.x left - `nx build twenty-front` — CSS extraction works (**1018 files transformed**) + `typecheck` - `nx build twenty-ui`, `twenty-ui-deprecated` (Linaria CSS extraction) - website's Linaria transform runs fine (local build only stops on a missing `TWENTY_PARTNERS_API_URL` env var, unrelated) - `yarn install --immutable` clean |
||
|
|
71480c3888 |
fix: gracefully handle missing logic functions during workflow destroy (#21362)
## Summary - Wraps `deleteOneWithSource` calls in `.catch()` during workflow/step destruction so that a missing logic function (valid UUID but already deleted) no longer crashes the entire destroy operation - Adds a `Logger` to `WorkflowVersionStepOperationsWorkspaceService` for the warning - Fixes test mock to return a resolved Promise and use a valid UUID ## Context When a CODE step references a `logicFunctionId` that is a valid UUID but the logic function no longer exists (e.g. deleted by a previous operation or orphaned), the destroy fails with "Logic function with id X not found". This blocks users from cleaning up workflows. ## Test plan - [x] Destroy a workflow with CODE steps whose logic functions already exist → succeeds as before - [ ] Destroy a workflow with CODE steps referencing a deleted/non-existent logic function → succeeds with a warning log instead of crashing |
||
|
|
adba66caea |
fix(twenty-front): new layout fast-follows — settings drawer, loading & command menu (#21389)
Second batch of new-layout fast-follows (master: twentyhq/core-team-issues#2478). All changes verified live against a running workspace. ## Settings drawer & header - **twentyhq/core-team-issues#2489** — sidebar icons render as plain 16px icons, no background tiles. - **twentyhq/core-team-issues#2488** — Advanced toggle spans the full drawer width; yellow dot removed. - **twentyhq/core-team-issues#2497** — page title stays centered in the settings header (breadcrumb stays left). - **twentyhq/core-team-issues#2490** — Exit Settings control aligned to the workspace switcher (24px, matching padding/gap). - **twentyhq/core-team-issues#2499** — 2px vertical gap restored between collapsible drawer section items. - **twentyhq/core-team-issues#2491** — settings drawer rhythm now matches the main app (28px items, 2px gaps, 28px section headers). - **twentyhq/core-team-issues#2492** — Home/Chat tab switch no longer flickers: both tab subtrees stay mounted (a shared `NavigationDrawerTabbedContent` toggles visibility instead of remounting + flashing the chat skeleton). ## Loading states - **twentyhq/core-team-issues#2486** — metadata loading shows an empty body (no dense skeleton rows). - **twentyhq/core-team-issues#2487** — settings table keeps its layout while loading, with the shimmer localized to the first row's first cell. ## Command menu & navigation - **twentyhq/core-team-issues#2501** — navigation section header height matches the nav item rhythm (28px). - **twentyhq/core-team-issues#2502 (part 1)** — the page side-panel toggle stays as the dots glyph while the command menu is open, instead of morphing into a second close control. ## New-field flow - **twentyhq/core-team-issues#2494** — the new-field stepper moved from a breadcrumb dropdown into a centered secondary wizard bar (back chevron + Save on the configure step); breadcrumb stays clean and the object label is the centered title. ## Descoped (substantive bugs already fixed) - **twentyhq/core-team-issues#2500** — command-menu highlight right gutter: the menu-item base measures full-width, so it's likely a scrollbar gutter on the list, not the shared component. Left for a focused follow-up. - **twentyhq/core-team-issues#2502 part 2** — moving the command-menu close from left to right is cosmetic (the duplicate-control bug is fixed by part 1) and would touch the shared `SidePanelTopBar` used by search/AI panels. ## Verification typecheck (tsgo) + oxlint + oxfmt green for all changed files; each change DOM-measured / screenshotted in the running app. |
||
|
|
6525af5ba4 |
Improve log visibility in dev mode (#21393)
Small PR to improve logging in twenty sdk dev mode ## After <img width="1406" height="580" alt="image" src="https://github.com/user-attachments/assets/a14edc2d-2194-420a-8b0b-b3ca35c31ccd" /> |
||
|
|
fc764115ef |
security: clear all High next alerts by upgrading react-email 5 → 6 (#21377)
## What Clears **all 9 High `next` Dependabot alerts** (incl. GHSA-26hh-7cqf-hhc6) in twenty-emails — via a parent bump, no resolutions. All 9 traced to a stale **`next@16.0.10`** pulled by `@react-email/preview-server` 5.x. The latest preview-server 5.x still ships a vulnerable next (16.1.7 < 16.2.6), so bumping it alone wouldn't help. **react-email 6.x** is a rewrite that no longer depends on next or on a separate preview-server. - bump `react-email` `5.1.0` → `6.5.0` - remove the obsolete `@react-email/preview-server` devDependency - add `@react-email/ui` `6.5.0` devDependency ### Why `@react-email/ui` (the CI fix) react-email 6's `email dev` preview server loads its UI from `@react-email/ui`, and **prompts to install it interactively** if missing — which hangs the `emails-test` CI job (no TTY), so the server never starts and the `/preview/test.email` smoke check fails. Pinning `@react-email/ui` makes `email dev` start non-interactively. ### Net effect on `next` The vulnerable `16.0.10` is gone. `@react-email/ui@6.5.0` pulls **`next@16.2.6`** — the **patched** version (≥ every current next advisory fix), so all 9 alerts clear and **no vulnerable next remains**. ## Notes - `react-email` and `@react-email/ui` pinned to exact `6.5.0` (matching the prior react-email pin) because the `6.6.0` line was published today and is still registry-quarantined. - react-email is a dev-only preview tool; CI builds emails via `vite` + typecheck. ## Verification - No `next < 16.2.6` in `yarn.lock` - `nx build` + `nx typecheck` twenty-emails - `email dev -d src/emails -p 4001` starts non-interactively and serves `/preview/test.email` → HTTP 200 (reproduces the emails-test check, now passing) - `yarn install --immutable` clean |