d2cfbf319b96bb29311bec32089ac96cae7a652e
11870
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d2cfbf319b |
[Website] Implement translations. (#20171)
As title. --------- Co-authored-by: Cursor <[email protected]> |
||
|
|
a3cf565ba3 |
feat(server): add heartbeat gauge + first-export-attempt log for OTLP (#20230)
## Summary - Adds a trivial always-on observable gauge (`twenty.heartbeat = 1`) so the OTLP exporter fires on every 10s collection tick, even on idle pods. Without this, `PeriodicExportingMetricReader` skips the export when `scopeMetrics` is empty, so the process-log wrapper never runs and we can't prove OTLP connectivity. - Adds a one-time "first periodic export attempt" log line inside the wrapped exporter, completing the startup log sequence: `OTLP reader enabled` → `first periodic export attempt` → `first export ok` / `export failed`. Co-authored-by: Cursor <[email protected]> |
||
|
|
fa8304d323 |
Fix record table dashboard save (#20202)
## Summary Fixes `METADATA_VALIDATION_FAILED` / “view field already exists” when saving dashboard **record table** widgets after the first persist (e.g. several table widgets on one dashboard). ## Problem Draft view columns used **client-generated** `viewField` ids. After save, the API stored **different** ids. The next upsert still sent the old draft ids as `viewFieldId`. The server only matched on that id, missed every row, and tried to **create** columns that already existed for the same `fieldMetadataId` + view. |
||
|
|
467ddaa27a |
feat(server): OTLP metrics export logs for troubleshooting (#20228)
## Summary Adds **grep-friendly** `console` logging around the OpenTelemetry metrics OTLP exporter in [`packages/twenty-server/src/instrument.ts`](packages/twenty-server/src/instrument.ts) so production / staging can confirm whether the app is exporting metrics and why exports fail. ## Log format - Prefix: **`[Twenty OTEL metrics]`** (easy to filter in Loki / `kubectl logs | grep`). - **Startup:** whether the OTLP reader is enabled, `exportIntervalMs`, and endpoint as `protocol//host/path` only (no credentials). - **First successful export:** one `console.log` per process (`first export ok`) with metric data point count — avoids spamming every 10s. - **Each failed export:** `console.warn` with result code, point count, and serialized error (including nested `AggregateError` causes when present). Co-authored-by: Cursor <[email protected]> |
||
|
|
fc4cf7fe09 |
i18n - translations (#20226)
Created by Github action --------- Co-authored-by: github-actions <[email protected]> |
||
|
|
9e94045fa5 |
feat(apps): generic OAuth provider support for app SDK (#20181)
## Summary
App developers can now declare third-party OAuth integrations (GitHub,
Linear, Slack, etc.) in their manifest and the platform handles the full
authorize → callback → token-exchange → refresh → injection lifecycle.
The dev writes ~10 lines of config and reads tokens via
`useOAuth('linear')` inside any logic function.
```ts
// app/src/oauth-providers/linear.ts
export default defineOAuthProvider({
universalIdentifier: '...',
name: 'linear',
displayName: 'Linear',
authorizationEndpoint: 'https://linear.app/oauth/authorize',
tokenEndpoint: 'https://api.linear.app/oauth/token',
scopes: ['read', 'write'],
connectionMode: 'per-user',
clientIdVariable: 'LINEAR_CLIENT_ID',
clientSecretVariable: 'LINEAR_CLIENT_SECRET',
tokenRequestContentType: 'form-urlencoded',
});
// app/src/logic-functions/handlers/...
const { accessToken } = useOAuth('linear'); // throws OAuthNotConnectedError if missing
```
## Architecture
- **Storage**: extends the existing `connectedAccount` table — new
nullable `applicationOAuthProviderId` FK + new `app` value on the
`ConnectedAccountProvider` enum. Existing Google/Microsoft flows are
untouched.
- **OAuth flow**: a single `/apps/oauth/authorize` +
`/apps/oauth/callback` controller pair handles every app provider. State
travels in a JWT signed via the existing `JwtWrapperService` (new
`APP_OAUTH_STATE` token type).
- **Token exchange**: goes through
`SecureHttpClientService.createSsrfSafeFetch()` (so an installed app
can't point `tokenEndpoint` at internal hosts).
- **Refresh**: piggybacks on the existing
`ConnectedAccountRefreshTokensService` dispatch — Google/Microsoft
drivers untouched, new app driver lives engine-side under
`application-oauth-provider/refresh/`.
- **Injection**: the executor injects refreshed tokens as env vars
(`OAUTH_<NAME>_ACCESS_TOKEN`, `_HANDLE`, `_SCOPES`, `_CONNECTED`); the
SDK helpers `useOAuth` / `useOptionalOAuth` read them.
- **Frontend**: auto-rendered "OAuth Connections" section under each
app's settings tab (no custom front component needed). App-managed
connections are filtered out of `/settings/accounts` so the
email/calendar page stays focused.
- **Disconnect**: best-effort revoke against the manifest's
`revokeEndpoint` before deleting the row.
## Reference app
`packages/twenty-apps/internal/twenty-linear/` exercises the full
pipeline:
- `defineOAuthProvider` for Linear
- `POST /linear/create-issue` and `GET /linear/teams` HTTP-route logic
functions
- Vitest tests for the handlers
## Tests
- 14 server-side Jest tests: token-exchange util (form-urlencoded vs
JSON, PKCE, error paths), flow service (authorize URL shape, state
binding, ConnectedAccount upsert on first/reconnect, per-workspace mode,
invalid state)
- 8 app-level Vitest tests: handler error paths, GraphQL request shape,
Linear error propagation
- All 4 packages clean: `npx nx lint:diff-with-main` and `npx tsc
--noEmit`
## Test plan
- [ ] Apply migration on a dev DB: `npx nx run
twenty-server:database:migrate:prod`
- [ ] Regenerate frontend types: `npx nx run
twenty-front:graphql:generate --configuration=metadata`
- [ ] Create a Linear OAuth app at
https://linear.app/settings/api/applications/new with redirect URI
`<SERVER_URL>/apps/oauth/callback`
- [ ] Deploy + install `twenty-linear` on a workspace, paste the Linear
client id/secret into the app's variables
- [ ] Click "Connect Linear" in the app's settings tab → complete OAuth
→ verify `connectedAccount` row created with `provider = 'app'`
- [ ] Trigger `POST /linear/create-issue` with a valid teamId → verify
issue lands in Linear
- [ ] Disconnect → verify the row is deleted and (if Linear's revoke
endpoint is configured in the manifest) the revoke call fires
- [ ] Verify `/settings/accounts` does NOT show the Linear connection —
it appears only under the Linear app's settings tab
## Out of scope (deliberately)
- **Cron + per-user providers**: a cron-triggered function with a
per-user OAuth provider currently returns `CONNECTED=false` (no user
context). The follow-up design is `useOAuthForUser(name,
userWorkspaceId)` paired with a `POST /apps/oauth/connection-token`
endpoint, deferred to keep this PR focused.
- **Token encryption at rest**: tokens stored as plain `varchar`
matching the existing Google/Microsoft pattern. Worth a separate
cross-cutting PR.
- **Manifest endpoint pinning**: a malicious app upgrade could change
`tokenEndpoint` silently. Same trust model as logic-function source code
(which already runs arbitrary server-side); worth tightening across the
whole upgrade pipeline rather than just OAuth.
- **CLI helpers** (`twenty oauth show-callback-url`, `twenty oauth
connect`): manual setup for v1.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
|
||
|
|
ff22988caf |
revert: Sentry #20064 + @sentry 10.27 (prod bisect) (#20221)
## Summary Reverts **#20064** (`feat(sentry): propagate workspace context to all spans`) and downgrades **@sentry** packages from **10.51** back to **10.27** (reversing **#20149**), to validate in production whether recent Sentry/instrumentation changes correlate with OTLP/metrics issues. ## Changes 1. **Revert #20064** — removes `beforeSendSpan` from `instrument.ts`, restores `WorkspaceAuthContextMiddleware` / `BullMQDriver` behavior, and deletes the three `apply-workspace-sentry-*` utils added in that PR. 2. **Sentry versions** — `packages/twenty-server` (`@sentry/nestjs`, `@sentry/node`, `@sentry/profiling-node`) and `packages/twenty-front` (`@sentry/react`) set to `^10.27.0`; `yarn.lock` regenerated via `yarn install`. --------- Co-authored-by: Cursor <[email protected]> |
||
|
|
74cc2b4c87 | Twenty email deps (#20223) | ||
|
|
7aa2afc67e |
fix(shared): add uuid, @types/uuid, @types/qs for Docker CD (#20222)
## Summary - `twenty-shared` imports `uuid` (in `actor.composite-type.ts` and `createAnyFieldRecordFilterBaseProperties.ts`) and `qs` (in `getAppPath.ts`, `getSettingsPath.ts`), but `uuid` was not declared in `twenty-shared/package.json` and `@types/uuid` / `@types/qs` were missing as devDependencies. - After scoped/hoisted deps (#20140) those types/runtime came from the root `package.json` and are no longer guaranteed in the Docker `common-deps` graph, so `twenty-shared:build` (pulled in before `twenty-website-new` build) fails with `TS7016: Could not find a declaration file for module 'uuid' / 'qs'` in the CD pipeline (see [twenty-infra run 25309442711](https://github.com/twentyhq/twenty-infra/actions/runs/25309442711)). - Same shape of fix as #20219 which added `@types/lodash.camelcase`. ## Test plan - [x] `npx nx build twenty-shared` succeeds locally - [ ] CD pipeline succeeds for `Build website-new` |
||
|
|
a025dc368b |
fix(shared): @types/lodash.camelcase for Docker CD (#20219)
Adds `@types/lodash.camelcase` to `twenty-shared`. **Why:** `lodash.camelcase` has no bundled types. Those types used to come from the root `devDependencies`; after scoped/hoisted deps (#20140), they are no longer guaranteed in the Docker `common-deps` graph, so `twenty-shared:build` (pulled in before server Lingui) fails with TS7016. Declaring the types on the package that imports `lodash.camelcase` fixes CD. Co-authored-by: Cursor <[email protected]> |
||
|
|
5bf7e8b101 |
test(upgrade): assert sequence-runner error structurally instead of snapshot (#20213)
## Summary The integration test `should throw when cursor command is not found in the sequence` in `failing-sequence-runner.integration-spec.ts` used `toThrowErrorMatchingSnapshot()`. The captured snapshot included the literal `TWENTY_CROSS_UPGRADE_SUPPORTED_VERSIONS` list from `upgrade-sequence-reader.service.ts`, which grows by one entry on every Twenty release. As a result, the snapshot drifted and broke whenever a new instance command landed (noticed during PR #20181), creating recurring "snapshot needs updating" churn with no real signal value. This PR replaces the snapshot assertion with a regex match on the structural part of the error message: ```ts ).rejects.toThrow(/Step "RemovedCommand" not found in upgrade sequence/); ``` The regex still catches the same class of regressions (the runner failing to surface a missing-step error) without pinning the version list. The now-empty snap file is removed (it had only this one entry). ## Test plan - [ ] CI integration tests pass on this branch - [ ] No remaining references to the deleted snapshot 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]> |
||
|
|
276d4f6e84 |
fix(code-interpreter): three correctness fixes for the TwentyMCP helper + tool output shape (#20103)
## Summary
Three independently-useful correctness fixes for the `code_interpreter`
tool, all surfaced while standing up a self-hosted code interpreter
against MCP. Each is isolated to one bug and applies regardless of
`CODE_INTERPRETER_TYPE`.
### 1. UI: unwrap `execute_tool` envelope when rendering
`code_interpreter` output
When `code_interpreter` is invoked through MCP's `execute_tool`
meta-tool, the result arrives wrapped: `{success, result: {stdout,
exitCode, files, ...}, ...}`. `ToolStepRenderer` reads `exitCode` at the
top level, which is `undefined` → the step renders as "Failed" even on a
clean `exitCode === 0`. Symmetric to the input-side unwrap that already
exists; the fix lifts `outputObj.result` when `rawToolName ===
'execute_tool'`.
### 2. Helper: route `TwentyMCP.call_tool` through `execute_tool` for
catalog tools
The `TwentyMCP` helper injected into every code-interpreter sandbox
exposes a `call_tool(name, arguments)` method. Direct MCP calls only
work for the 5 meta-tools (`get_tool_catalog`, `learn_tools`,
`execute_tool`, `load_skills`, `search_help_center`); the 250+ catalog
tools are accessed through `execute_tool`. Today
`twenty.call_tool('find_companies', {...})` raises "Unknown tool". This
commit detects catalog tools and auto-routes them through
`execute_tool`. It also flattens the nested `{catalog: {category:
[...]}}` shape returned by `list_tools()` and propagates `{success:
false}` envelopes as explicit exceptions (they were being silently
returned as dicts).
### 3. Prompt: stop the agent from hallucinating \`import twenty\`
Despite the helper being pre-injected, models frequently emitted
\`import twenty\` and crashed with \`ModuleNotFoundError\`. Two
contributing sources: the helper docstring did not explicitly say "do
not import," and the code-interpreter skill template's example block
referenced placeholder tool names. Fix: explicit "DO NOT import twenty"
block in the helper + rewritten skill examples using real tool names and
real response shapes.
## Test plan
- [ ] Existing \`code_interpreter\` tests still pass.
- [ ] Run a chat turn that invokes \`code_interpreter\` indirectly via
MCP \`execute_tool\` and confirm the UI no longer flips to "Failed" on
\`exitCode === 0\`.
- [ ] From inside the sandbox, run \`twenty.call_tool('find_companies',
{limit: 5})\` and confirm records return (was raising "Unknown tool").
- [ ] Confirm \`twenty.list_tools()\` returns a flat list, not the
nested \`{catalog: {...}}\` envelope.
- [ ] Trigger a tool error from inside the sandbox and confirm it raises
rather than returning a \`{success: false}\` dict.
- [ ] Ask an LLM to use \`code_interpreter\`; confirm it does not emit
\`import twenty\`.
---------
Co-authored-by: Félix Malfait <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Félix Malfait <[email protected]>
|
||
|
|
4f439bbe43 | [AI] Prefer batch tools in system prompts (#20173) | ||
|
|
4fbd8b207d |
chore: sync AI model catalog from models.dev (#20178)
Automated daily sync of `ai-providers.json` from [models.dev](https://models.dev). This PR updates pricing, context windows, and model availability based on the latest data. New models meeting inclusion criteria (tool calling, pricing data, context limits) are added automatically. Deprecated models are detected based on cost-efficiency within the same model family. **Please review before merging** — verify no critical models were incorrectly deprecated. Co-authored-by: FelixMalfait <[email protected]> |
||
|
|
f7d812fca6 |
fix: disable sync on seeded message and calendar channels (#20168)
## Summary The dev seeder creates `ConnectedAccount` records with fake OAuth tokens (`'exampleRefreshToken'` / `'exampleAccessToken'`) and points `MessageChannel` / `CalendarChannel` records at them with `isSyncEnabled: true`. When the sync cron jobs run in the demo workspace, they: 1. Pick up these seeded channels (filter is `isSyncEnabled: true` + pending sync stage) 2. Try to refresh the fake OAuth tokens 3. Mark the channels as `FAILED_INSUFFICIENT_PERMISSIONS` 4. Surface a "Sync lost with mailbox X — please reconnect" banner in the UI This banner appears every time the demo workspace is loaded, even though nothing is actually broken. ## Fix Set `isSyncEnabled: false` on all 12 seeded channels (6 message, 6 calendar). This is the canonical "don't sync this channel" mechanism — the same state a real user lands in when they toggle sync off in account settings. ## Why this approach - **ConnectedAccount records stay**: the demo workspace still shows Tim, Jony, Phil, Jane as having connected their email/calendar — realistic - **Pre-seeded messages and calendar events stay visible**: those don't depend on `isSyncEnabled` - **Crons no longer pick them up**: they filter on `isSyncEnabled: true`, so `false` short-circuits the entire sync attempt — no failure, no banner - **Semantically correct**: the seeded accounts have fake tokens that were never going to sync successfully; `isSyncEnabled: true` was effectively a lie - **No production code touched**: no `isDemo` flags, no magic-string detection, no workspace-ID filters in the cron path ## Alternatives considered and rejected - **Add an `isDemo` flag**: schema change, leaks demo knowledge into production tables - **Skip channels with fake tokens (`example*` pattern)**: hacky magic-string detection in the auth refresh path - **Filter demo workspace IDs in the cron**: production paths shouldn't reference demo IDs - **Don't activate demo workspaces**: breaks the demo workspace UX entirely ## Test plan - [ ] Reset the database and reseed (`npx nx database:reset twenty-server`) - [ ] Load the demo workspace — confirm no "Sync lost with mailbox" banner appears - [ ] Confirm seeded connected accounts still show in Settings → Accounts - [ ] Confirm pre-seeded messages and calendar events still appear in the UI - [ ] Confirm a real connected account (added via OAuth) still syncs normally — its channel will have `isSyncEnabled: true` and the cron will pick it up ## Related Companion to https://github.com/twentyhq/twenty/pull/20167, which removes the `--dev-mode` cron filter that was masking this banner issue in the dev image. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 <[email protected]> |
||
|
|
c3a320c27b |
fix: register all cron jobs in twenty-app-dev image (#20167)
## Summary The `twenty-app-dev` Docker image previously passed `--dev-mode` to `cron:register:all`, which skipped all calendar, messaging, and workflow sync cron jobs (only 4 generic crons were registered). This caused periodic sync to silently stop after the initial import for community members using the dev image as their actual instance. ## What changed - Removed `--dev-mode` flag from `packages/twenty-docker/twenty-app-dev/rootfs/etc/s6-overlay/scripts/register-crons.sh` so the dev image registers all cron jobs (matching production behavior) - Removed the now-unused `--dev-mode` option, `DEV_MODE_COMMANDS` set, and conditional filtering logic from `cron-register-all.command.ts` ## Why this is safe - **No log noise**: cron jobs gracefully no-op when no connected accounts exist — they query for pending channels, find zero, and exit early - **No false banner**: the "reconnect account" banner only shows when a user explicitly connected an account whose OAuth later fails, which is correct behavior. No seed/demo data creates connected accounts, so a fresh dev instance won't see any banner - **Hiding crons just hid the symptom**: silently breaking sync with no user feedback is worse than showing the banner if OAuth is misconfigured ## Context Surfaced by a community member who reported that calendar sync cron jobs never appeared in the queue after restarting the dev image, and only the initial import worked. `--dev-mode` was added in #19138 as an optimization for development but it doesn't match how the dev image is actually used by community members deploying Twenty. ## Test plan - [ ] Build/run the `twenty-app-dev` image - [ ] Confirm worker logs show all cron jobs registering (calendar, messaging, workflow, etc.) - [ ] With no connected accounts: confirm no errors or log noise - [ ] With a connected Google calendar: confirm periodic sync triggers after ~5 minutes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 <[email protected]> |
||
|
|
85752f8a61 | Bump 2.3.0 (#20169) | ||
|
|
8a0225e974 |
Dispatch root package.json hoisted deps and devDeps (#20140)
# Introduction Dispatching root package.json devDeps, prod deps Taking care of keeping non imported module used at build/ci level in the root package.json ## Motivation Avoid redundant deps declaration, better scoping allow better workspace deps granularity installation. <img width="385" height="247" alt="image" src="https://github.com/user-attachments/assets/9d7162ec-ba01-4f58-8563-38333733fdf0" /> --------- Co-authored-by: Charles Bochet <[email protected]> |
||
|
|
abc67efd40 |
i18n - docs translations (#20166)
Created by Github action Co-authored-by: github-actions <[email protected]> |
||
|
|
636deffb93 |
i18n - translations (#20164)
Created by Github action --------- Co-authored-by: github-actions <[email protected]> |
||
|
|
e1828b6f41 |
[AI] Add thread actions, filters, and archive support (#20068)
## PR Description ### Summary - Add AI chat thread actions: rename, archive (soft-delete via `deletedAt`), and hard-delete with confirmation. - Add chat thread filtering by status (active/archived/all), group-by mode, and last activity. - Rework drawer/side-panel thread lists to share thread sections, item menus, archive icons, and empty-state behavior. - Extend server chat thread model/API with `deletedAt`, mutations, broadcasts, and archive-aware stream guards. ### Decisions - Two-stage lifecycle: Archive sets `deletedAt` (soft); Delete is a separate action on archived threads that hard-deletes the row. Aligns with Twenty's soft-delete convention (Felix's suggestion). - `lastMessageAt` is derived from `MAX(agentMessage.createdAt)` on read, not stored. List query does inline aggregation for sort; `@ResolveField` covers single-thread / mutation paths so the schema contract is honest everywhere. Matches `timeline-messaging.service.ts` precedent and the existing `totalInputCredits` / `totalOutputCredits` `@ResolveField` pattern in the same resolver. - Replaced auto-CRUD `chatThreads` (cursor-paginated Connection) with a custom `[AgentChatThreadDTO!]` resolver. Frontend metadata-store treats threads as a flat collection and filters/sorts client-side, so cursor pagination was performative. - Sending in an archived chat unarchives it optimistically on the client and authoritatively on the server. - Grouping and last-activity filtering use `lastMessageAt ?? updatedAt` so archive/rename don't bump threads in the list. - Kept metadata-store core API unchanged; AI chat uses the same local cast pattern already used by other metadata-store partial updates. https://github.com/user-attachments/assets/1b179b7b-1a2a-4a7a-aa0a-c88f6f051a87 |
||
|
|
4b76457217 |
Select application excluding logo (#20159)
## Context This is a temporary fix for cross-version upgrade process, a better fix would be to expose an hasInstanceCommandBeenRun() util (and later a decorator)v2.2.0 |
||
|
|
d8bd717f1f |
Update doc screenshots (#20160)
fixes https://discord.com/channels/1130383047699738754/1496579088889024542 |
||
|
|
b44fb1ad23 |
fix(security): reject ?token= URL query parameter for authentication (#20154)
## Summary
Removes the `?token=` URL query-parameter fallback from JWT
authentication. Every authenticated route (`/graphql`, `/metadata`,
REST, etc.) used to accept a full workspace JWT in the URL alongside the
`Authorization` header. The fallback was intended for the REST API
Playground only, but it was wired into the global Passport JWT extractor
and applied to every route.
URL-borne tokens leak into:
- Server access logs (nginx / Apache / CDN / proxy / load balancer)
- Log aggregators (Datadog, CloudWatch, Loki, Sumo, …)
- Browser history (and synced across devices)
- `Referer` headers when navigating to external pages
- Browser extensions with `tabs`/`webNavigation` permissions
A leaked log line was equivalent to a leaked workspace credential for
the lifetime of the token.
## What changed
- **`jwt-wrapper.service.ts`** — `extractJwtFromRequest()` is now
header-only (`ExtractJwt.fromAuthHeaderAsBearerToken()`). No URL
fallback anywhere in the system.
- **`open-api.service.ts` / `base-schema.utils.ts`** — Dropped the
`token?: string` plumbing that propagated the URL token into the schema
description. The "Authentication" section gains a "Never put your token
in a URL" warning. The "Usage with LLMs" section is rewritten to point
at the **Twenty MCP server** (header-authenticated, exposes typed tools
— the right tool for AI agents) instead of telling users to paste
tokenized OpenAPI URLs into Cursor/ChatGPT.
- **`RestPlayground.tsx`** — Now fetches the OpenAPI schema with
`Authorization: Bearer ${playgroundApiKey}` and passes the JSON document
to Scalar via `spec.content` instead of constructing a URL with
`?token=`. Aborts in-flight fetches on unmount/key change.
- **New integration test** — Asserts `?token=` is rejected on `/rest/*`,
`/graphql`, `/metadata`, and that `/rest/open-api/core?token=` returns
the unauthenticated base schema (no workspace object paths).
## Why not keep `?token=` scoped to the OpenAPI endpoint only
The first instinct was to narrow the fallback to just
`/rest/open-api/*`, since that endpoint is what the Scalar playground
component fetches. But the same log-leakage attack still applies to that
endpoint — the workspace JWT would still sit in access logs, just from
one URL pattern instead of all of them. The cleaner long-term fix is to
remove the URL pattern entirely and let the playground fetch with a
header (Scalar supports `spec.content` natively). For LLM agent use, the
MCP server is a strictly better path — typed tools, OAuth or
header-based API key auth, no tokens in URLs anywhere.
## Not affected
File downloads at `file-url.service.ts` also use `?token=` URLs but with
separate, short-lived `FILE`-typed tokens validated by
`file-by-id.guard.ts` directly (not via `extractJwtFromRequest`). That
mechanism is scoped per-file with limited TTL and is acceptable.
## Action required for users
Anyone who previously pasted `?token=` URLs into LLM tools, scripts,
bookmarks, or shared configs should rotate their workspace API keys.
Those tokens are likely captured in server logs / chat histories
somewhere.
## Test plan
- [x] `npx nx typecheck twenty-server` — clean
- [x] `npx nx typecheck twenty-front` — clean
- [x] `npx nx lint:diff-with-main twenty-server` — clean
- [x] `npx nx lint:diff-with-main twenty-front` — clean
- [x] OpenAPI utils unit tests + snapshots — 11/11 pass
- [ ] Run the new integration test against a live server: `nx run
twenty-server:test:integration:with-db-reset` and verify
`url-token-auth-rejection.integration-spec.ts` passes
- [ ] Manually open Settings → Playground → REST, confirm the schema
loads (now via Bearer header instead of `?token=` URL)
- [ ] Manually verify `POST /metadata?token=<jwt>` (no Authorization
header) returns Forbidden, and the same request with the token in the
header returns the user
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
|
||
|
|
f32b03a3ec |
i18n - docs translations (#20161)
Created by Github action Co-authored-by: github-actions <[email protected]> |
||
|
|
c8e405cb4e |
Add twenty sdk server upgrade command (#20158)
## The command pulls the image, compares it against the one the container was created from, and only recreates the container if the image actually changed. Your data volumes are preserved — only the container is replaced. |
||
|
|
83db37d33f |
chore(deps): bump @sentry/profiling-node from 10.27.0 to 10.51.0 (#20149)
Bumps [@sentry/profiling-node](https://github.com/getsentry/sentry-javascript) from 10.27.0 to 10.51.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/getsentry/sentry-javascript/releases"><code>@sentry/profiling-node</code>'s releases</a>.</em></p> <blockquote> <h2>10.51.0</h2> <h3>Important Changes</h3> <ul> <li> <p><strong>feat(cloudflare): Add trace propagation for RPC method calls (<a href="https://redirect.github.com/getsentry/sentry-javascript/pull/20343">#20343</a>)</strong></p> <p>Trace context is now propagated across Cloudflare Workers RPC calls, connecting traces between Workers and Durable Objects. This feature is opt-in and requires setting <code>enableRpcTracePropagation: true</code> in your SDK configuration:</p> <pre lang="ts"><code>// Worker export default Sentry.withSentry( env => ({ dsn: env.SENTRY_DSN, enableRpcTracePropagation: true, }), handler, ); <p>// Durable Object<br /> export const MyDurableObject = Sentry.instrumentDurableObjectWithSentry(<br /> env => ({<br /> dsn: env.SENTRY_DSN,<br /> enableRpcTracePropagation: true,<br /> }),<br /> MyDurableObjectBase,<br /> );<br /> </code></pre></p> </li> <li> <p><strong>feat(hono)!: Change setup for <code>@sentry/hono/node</code> (<code>init</code> in external file) (<a href="https://redirect.github.com/getsentry/sentry-javascript/pull/20497">#20497</a>)</strong></p> <p>To improve Node.js instrumentation, the <code>sentry()</code> middleware exported from <code>@sentry/hono/node</code> no longer accepts configuration options. Instead, you must configure the SDK by calling <code>Sentry.init()</code> in a dedicated instrumentation file that runs before your application code (read more in the <a href="https://github.com/getsentry/sentry-javascript/blob/develop/packages/hono/README.md">Hono SDK readme</a>:</p> <pre lang="ts"><code>// instrument.mjs (or instrument.ts) import * as Sentry from '@sentry/hono/node'; <p>Sentry.init({<br /> dsn: '<strong>DSN</strong>',<br /> tracesSampleRate: 1.0,<br /> });<br /> </code></pre></p> </li> <li> <p><strong>feat(nitro): Add <code>@sentry/nitro</code> SDK (<a href="https://redirect.github.com/getsentry/sentry-javascript/pull/19224">#19224</a>)</strong></p> <p>A new <code>@sentry/nitro</code> package provides first-class Sentry support for <a href="https://nitro.build/">Nitro</a> applications, with HTTP handler and error instrumentation, middleware tracing, request isolation, and build-time source map uploading via <code>withSentryConfig</code>. Read more in the <a href="https://docs.sentry.io/platforms/javascript/guides/nitro/">Nitro SDK docs</a> and the <a href="https://github.com/getsentry/sentry-javascript/blob/develop/packages/nitro/README.md">Nitro SDK readme</a>.</p> </li> </ul> <h3>Other Changes</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md"><code>@sentry/profiling-node</code>'s changelog</a>.</em></p> <blockquote> <h2>10.51.0</h2> <h3>Important Changes</h3> <ul> <li> <p><strong>feat(cloudflare): Add trace propagation for RPC method calls (<a href="https://redirect.github.com/getsentry/sentry-javascript/pull/20343">#20343</a>)</strong></p> <p>Trace context is now propagated across Cloudflare Workers RPC calls, connecting traces between Workers and Durable Objects. This feature is opt-in and requires setting <code>enableRpcTracePropagation: true</code> in your SDK configuration:</p> <pre lang="ts"><code>// Worker export default Sentry.withSentry( env => ({ dsn: env.SENTRY_DSN, enableRpcTracePropagation: true, }), handler, ); <p>// Durable Object<br /> export const MyDurableObject = Sentry.instrumentDurableObjectWithSentry(<br /> env => ({<br /> dsn: env.SENTRY_DSN,<br /> enableRpcTracePropagation: true,<br /> }),<br /> MyDurableObjectBase,<br /> );<br /> </code></pre></p> </li> <li> <p><strong>feat(hono)!: Change setup for <code>@sentry/hono/node</code> (<code>init</code> in external file) (<a href="https://redirect.github.com/getsentry/sentry-javascript/pull/20497">#20497</a>)</strong></p> <p>To improve Node.js instrumentation, the <code>sentry()</code> middleware exported from <code>@sentry/hono/node</code> no longer accepts configuration options. Instead, you must configure the SDK by calling <code>Sentry.init()</code> in a dedicated instrumentation file that runs before your application code (read more in the <a href="https://github.com/getsentry/sentry-javascript/blob/develop/packages/hono/README.md">Hono SDK readme</a>:</p> <pre lang="ts"><code>// instrument.mjs (or instrument.ts) import * as Sentry from '@sentry/hono/node'; <p>Sentry.init({<br /> dsn: '<strong>DSN</strong>',<br /> tracesSampleRate: 1.0,<br /> });<br /> </code></pre></p> </li> <li> <p><strong>feat(nitro): Add <code>@sentry/nitro</code> SDK (<a href="https://redirect.github.com/getsentry/sentry-javascript/pull/19224">#19224</a>)</strong></p> <p>A new <code>@sentry/nitro</code> package provides first-class Sentry support for <a href="https://nitro.build/">Nitro</a> applications, with HTTP handler and error instrumentation, middleware tracing, request isolation, and build-time source map uploading via <code>withSentryConfig</code>. Read more in the <a href="https://docs.sentry.io/platforms/javascript/guides/nitro/">Nitro SDK docs</a> and the <a href="https://github.com/getsentry/sentry-javascript/blob/develop/packages/nitro/README.md">Nitro SDK readme</a>.</p> </li> </ul> <h3>Other Changes</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/getsentry/sentry-javascript/commit/dc0b839ff4896cf90a02f5c1a6de54a31302dcf3"><code>dc0b839</code></a> release: 10.51.0</li> <li><a href="https://github.com/getsentry/sentry-javascript/commit/b3cabee9a9348b9e67332262d44d3d1900424199"><code>b3cabee</code></a> Merge pull request <a href="https://redirect.github.com/getsentry/sentry-javascript/issues/20599">#20599</a> from getsentry/prepare-release/10.51.0</li> <li><a href="https://github.com/getsentry/sentry-javascript/commit/3be99a9afa77e49578e6839e4b32f97fb04fb0f8"><code>3be99a9</code></a> meta(changelog): Update changelog for 10.51.0</li> <li><a href="https://github.com/getsentry/sentry-javascript/commit/bea1aad42277db894d5a299bfec3cdd633d6baf0"><code>bea1aad</code></a> test(browser): Unflake some more tests (<a href="https://redirect.github.com/getsentry/sentry-javascript/issues/20591">#20591</a>)</li> <li><a href="https://github.com/getsentry/sentry-javascript/commit/50aa0859b3a188d34d0317dab3ad57f2140f02fe"><code>50aa085</code></a> test(node): Unflake postgres tests (<a href="https://redirect.github.com/getsentry/sentry-javascript/issues/20593">#20593</a>)</li> <li><a href="https://github.com/getsentry/sentry-javascript/commit/1166839112c4766f210124dc0486ebbfd6db104b"><code>1166839</code></a> fix(hono): Distinguish <code>.use()</code> middleware in sub-apps from <code>.all()</code> handlers...</li> <li><a href="https://github.com/getsentry/sentry-javascript/commit/217ad4a69554281806eccbfeac1b27c4f43f6ffa"><code>217ad4a</code></a> test(node): Fix flaky ANR test (<a href="https://redirect.github.com/getsentry/sentry-javascript/issues/20592">#20592</a>)</li> <li><a href="https://github.com/getsentry/sentry-javascript/commit/91ffb3fac90835ab160f8152527a54a5d64f3250"><code>91ffb3f</code></a> test(node): Fix flaky worker thread integration test (<a href="https://redirect.github.com/getsentry/sentry-javascript/issues/20588">#20588</a>)</li> <li><a href="https://github.com/getsentry/sentry-javascript/commit/c4e3902c9297147158e730f017aba96e83ef619e"><code>c4e3902</code></a> chore(ci): Do not report flaky test issues if we cannot find a test name (<a href="https://redirect.github.com/getsentry/sentry-javascript/issues/20">#20</a>...</li> <li><a href="https://github.com/getsentry/sentry-javascript/commit/c0005cd387f3a7ea6fbb2e85041562c7f32e0484"><code>c0005cd</code></a> test(node): Update timeout for cron integration tests (<a href="https://redirect.github.com/getsentry/sentry-javascript/issues/20586">#20586</a>)</li> <li>Additional commits viewable in <a href="https://github.com/getsentry/sentry-javascript/compare/10.27.0...10.51.0">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] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Charles Bochet <[email protected]> |
||
|
|
5bdbfe651e |
chore(deps): bump postal-mime from 2.6.1 to 2.7.4 (#20150)
Bumps [postal-mime](https://github.com/postalsys/postal-mime) from 2.6.1 to 2.7.4. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/postalsys/postal-mime/releases">postal-mime's releases</a>.</em></p> <blockquote> <h2>v2.7.4</h2> <h2><a href="https://github.com/postalsys/postal-mime/compare/v2.7.3...v2.7.4">2.7.4</a> (2026-03-17)</h2> <h3>Bug Fixes</h3> <ul> <li>add missing originalKey to Header type and Uint8Array to Attachment content (<a href="https://github.com/postalsys/postal-mime/commit/92cc91c1c8477e0462cb0e93ddf8ea6aec6534d0">92cc91c</a>)</li> <li>include originalKey in parsed headers output (<a href="https://github.com/postalsys/postal-mime/commit/83521c87f62e5e095ae09913c70798f20e2ab347">83521c8</a>)</li> <li>preserve __esModule and .default in CJS build for bundler interop (<a href="https://github.com/postalsys/postal-mime/commit/1466910e31608b9e5307724ecc6a0a3a70556048">1466910</a>)</li> <li>prevent RFC 2047 encoded-word address fabrication (<a href="https://github.com/postalsys/postal-mime/commit/844f92023d49d819ef13b9ad5c50b7c346eb02d3">844f920</a>)</li> </ul> <h2>v2.7.3</h2> <h2><a href="https://github.com/postalsys/postal-mime/compare/v2.7.2...v2.7.3">2.7.3</a> (2026-01-09)</h2> <h3>Bug Fixes</h3> <ul> <li>correct TypeScript type definitions to match implementation (<a href="https://github.com/postalsys/postal-mime/commit/b225d7cca422cb9bc3ab5301e94c4c0bef9a69e2">b225d7c</a>)</li> </ul> <h2>v2.7.2</h2> <h2><a href="https://github.com/postalsys/postal-mime/compare/v2.7.1...v2.7.2">2.7.2</a> (2026-01-08)</h2> <h3>Bug Fixes</h3> <ul> <li>add null checks for contentType.parsed access (<a href="https://github.com/postalsys/postal-mime/commit/ad8f4c62e0972fd0244859ee5a5184b2cac26395">ad8f4c6</a>)</li> <li>improve RFC compliance for MIME parsing (<a href="https://github.com/postalsys/postal-mime/commit/e004c3acb29d72ed7eaf1b0b66351cf8b82b970d">e004c3a</a>)</li> </ul> <h2>v2.7.1</h2> <h2><a href="https://github.com/postalsys/postal-mime/compare/v2.7.0...v2.7.1">2.7.1</a> (2025-12-22)</h2> <h3>Bug Fixes</h3> <ul> <li>Add null checks for contentDisposition.parsed access (<a href="https://github.com/postalsys/postal-mime/commit/fd54c37093cc64737c6bb17986bc9d052d2d5add">fd54c37</a>)</li> </ul> <h2>v2.7.0</h2> <h2><a href="https://github.com/postalsys/postal-mime/compare/v2.6.1...v2.7.0">2.7.0</a> (2025-12-22)</h2> <h3>Features</h3> <ul> <li>add headerLines property exposing raw header lines (<a href="https://github.com/postalsys/postal-mime/commit/c79a02ab05d9cac44e05e95a433752ff292aa5eb">c79a02a</a>)</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/postalsys/postal-mime/blob/master/CHANGELOG.md">postal-mime's changelog</a>.</em></p> <blockquote> <h2><a href="https://github.com/postalsys/postal-mime/compare/v2.7.3...v2.7.4">2.7.4</a> (2026-03-17)</h2> <h3>Bug Fixes</h3> <ul> <li>add missing originalKey to Header type and Uint8Array to Attachment content (<a href="https://github.com/postalsys/postal-mime/commit/92cc91c1c8477e0462cb0e93ddf8ea6aec6534d0">92cc91c</a>)</li> <li>include originalKey in parsed headers output (<a href="https://github.com/postalsys/postal-mime/commit/83521c87f62e5e095ae09913c70798f20e2ab347">83521c8</a>)</li> <li>preserve __esModule and .default in CJS build for bundler interop (<a href="https://github.com/postalsys/postal-mime/commit/1466910e31608b9e5307724ecc6a0a3a70556048">1466910</a>)</li> <li>prevent RFC 2047 encoded-word address fabrication (<a href="https://github.com/postalsys/postal-mime/commit/844f92023d49d819ef13b9ad5c50b7c346eb02d3">844f920</a>)</li> </ul> <h2><a href="https://github.com/postalsys/postal-mime/compare/v2.7.2...v2.7.3">2.7.3</a> (2026-01-09)</h2> <h3>Bug Fixes</h3> <ul> <li>correct TypeScript type definitions to match implementation (<a href="https://github.com/postalsys/postal-mime/commit/b225d7cca422cb9bc3ab5301e94c4c0bef9a69e2">b225d7c</a>)</li> </ul> <h2><a href="https://github.com/postalsys/postal-mime/compare/v2.7.1...v2.7.2">2.7.2</a> (2026-01-08)</h2> <h3>Bug Fixes</h3> <ul> <li>add null checks for contentType.parsed access (<a href="https://github.com/postalsys/postal-mime/commit/ad8f4c62e0972fd0244859ee5a5184b2cac26395">ad8f4c6</a>)</li> <li>improve RFC compliance for MIME parsing (<a href="https://github.com/postalsys/postal-mime/commit/e004c3acb29d72ed7eaf1b0b66351cf8b82b970d">e004c3a</a>)</li> </ul> <h2><a href="https://github.com/postalsys/postal-mime/compare/v2.7.0...v2.7.1">2.7.1</a> (2025-12-22)</h2> <h3>Bug Fixes</h3> <ul> <li>Add null checks for contentDisposition.parsed access (<a href="https://github.com/postalsys/postal-mime/commit/fd54c37093cc64737c6bb17986bc9d052d2d5add">fd54c37</a>)</li> </ul> <h2><a href="https://github.com/postalsys/postal-mime/compare/v2.6.1...v2.7.0">2.7.0</a> (2025-12-22)</h2> <h3>Features</h3> <ul> <li>add headerLines property exposing raw header lines (<a href="https://github.com/postalsys/postal-mime/commit/c79a02ab05d9cac44e05e95a433752ff292aa5eb">c79a02a</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/postalsys/postal-mime/commit/178f1ef0b1cd0047e1b8e690beabfec541b4daa7"><code>178f1ef</code></a> chore(master): release 2.7.4 (<a href="https://redirect.github.com/postalsys/postal-mime/issues/88">#88</a>)</li> <li><a href="https://github.com/postalsys/postal-mime/commit/1f7ba618d42d34b779157dfa33794cbae383a24d"><code>1f7ba61</code></a> chore: bump devDependencies</li> <li><a href="https://github.com/postalsys/postal-mime/commit/83521c87f62e5e095ae09913c70798f20e2ab347"><code>83521c8</code></a> fix: include originalKey in parsed headers output</li> <li><a href="https://github.com/postalsys/postal-mime/commit/b0d7b11550a2a3c65a52a2adf4f8281058023cab"><code>b0d7b11</code></a> test: improve test coverage across codebase</li> <li><a href="https://github.com/postalsys/postal-mime/commit/ebc5ce619649d13ad72f4d12414f3e337a9e248c"><code>ebc5ce6</code></a> refactor: simplify and clean up codebase</li> <li><a href="https://github.com/postalsys/postal-mime/commit/1466910e31608b9e5307724ecc6a0a3a70556048"><code>1466910</code></a> fix: preserve __esModule and .default in CJS build for bundler interop</li> <li><a href="https://github.com/postalsys/postal-mime/commit/844f92023d49d819ef13b9ad5c50b7c346eb02d3"><code>844f920</code></a> fix: prevent RFC 2047 encoded-word address fabrication</li> <li><a href="https://github.com/postalsys/postal-mime/commit/24dc6c64dfb43d89a8c8837ec941c96ebfa2c1fa"><code>24dc6c6</code></a> test: update type check test with originalKey property</li> <li><a href="https://github.com/postalsys/postal-mime/commit/92cc91c1c8477e0462cb0e93ddf8ea6aec6534d0"><code>92cc91c</code></a> fix: add missing originalKey to Header type and Uint8Array to Attachment content</li> <li><a href="https://github.com/postalsys/postal-mime/commit/aa5baeafa6ffd093ab447c22d20e5da25051faff"><code>aa5baea</code></a> docs: add link to full documentation site</li> <li>Additional commits viewable in <a href="https://github.com/postalsys/postal-mime/compare/v2.6.1...v2.7.4">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] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Charles Bochet <[email protected]> |
||
|
|
3fbb70c13f |
i18n - docs translations (#20157)
Created by Github action Co-authored-by: github-actions <[email protected]> |
||
|
|
c6b6c824d4 |
i18n - translations (#20156)
Created by Github action --------- Co-authored-by: github-actions <[email protected]> |
||
|
|
b21bf66b38 |
i18n - translations (#20155)
Created by Github action --------- Co-authored-by: github-actions <[email protected]> |
||
|
|
22838ac6de |
chore(deps-dev): bump @babel/preset-typescript from 7.24.7 to 7.28.5 (#20151)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.24.7 to 7.28.5. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/babel/babel/releases"><code>@babel/preset-typescript</code>'s releases</a>.</em></p> <blockquote> <h2>v7.28.5 (2025-10-23)</h2> <p>Thank you <a href="https://github.com/CO0Ki3"><code>@CO0Ki3</code></a>, <a href="https://github.com/Olexandr88"><code>@Olexandr88</code></a>, and <a href="https://github.com/youthfulhps"><code>@youthfulhps</code></a> for your first PRs!</p> <h4>👓 Spec Compliance</h4> <ul> <li><code>babel-parser</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17446">#17446</a> Allow <code>Runtime Errors for Function Call Assignment Targets</code> (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> <li><code>babel-helper-validator-identifier</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17501">#17501</a> fix: update identifier to unicode 17 (<a href="https://github.com/fisker"><code>@fisker</code></a>)</li> </ul> </li> </ul> <h4>🐛 Bug Fix</h4> <ul> <li><code>babel-plugin-proposal-destructuring-private</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17534">#17534</a> Allow mixing private destructuring and rest (<a href="https://github.com/CO0Ki3"><code>@CO0Ki3</code></a>)</li> </ul> </li> <li><code>babel-parser</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17521">#17521</a> Improve <code>@babel/parser</code> error typing (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> <li><a href="https://redirect.github.com/babel/babel/pull/17491">#17491</a> fix: improve ts-only declaration parsing (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> <li><code>babel-plugin-proposal-discard-binding</code>, <code>babel-plugin-transform-destructuring</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17519">#17519</a> fix: <code>rest</code> correctly returns plain array (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> <li><code>babel-helper-create-class-features-plugin</code>, <code>babel-helper-member-expression-to-functions</code>, <code>babel-plugin-transform-block-scoping</code>, <code>babel-plugin-transform-optional-chaining</code>, <code>babel-traverse</code>, <code>babel-types</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17503">#17503</a> Fix <code>JSXIdentifier</code> handling in <code>isReferencedIdentifier</code> (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> <li><code>babel-traverse</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17504">#17504</a> fix: ensure scope.push register in anonymous fn (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> </ul> <h4>🏠 Internal</h4> <ul> <li><code>babel-types</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17494">#17494</a> Type checking babel-types scripts (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> </ul> <h4>🏃♀️ Performance</h4> <ul> <li><code>babel-core</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17490">#17490</a> Faster finding of locations in <code>buildCodeFrameError</code> (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> </ul> <h4>Committers: 8</h4> <ul> <li>Babel Bot (<a href="https://github.com/babel-bot"><code>@babel-bot</code></a>)</li> <li>Byeongho Yoo (<a href="https://github.com/youthfulhps"><code>@youthfulhps</code></a>)</li> <li>Huáng Jùnliàng (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> <li>Hyeon Dokko (<a href="https://github.com/CO0Ki3"><code>@CO0Ki3</code></a>)</li> <li>Nicolò Ribaudo (<a href="https://github.com/nicolo-ribaudo"><code>@nicolo-ribaudo</code></a>)</li> <li><a href="https://github.com/Olexandr88"><code>@Olexandr88</code></a></li> <li><a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a></li> <li>fisker Cheung (<a href="https://github.com/fisker"><code>@fisker</code></a>)</li> </ul> <h2>v7.28.4 (2025-09-05)</h2> <p>Thanks <a href="https://github.com/gwillen"><code>@gwillen</code></a> and <a href="https://github.com/mrginglymus"><code>@mrginglymus</code></a> for your first PRs!</p> <h4>🏠 Internal</h4> <ul> <li><code>babel-core</code>, <code>babel-helper-check-duplicate-nodes</code>, <code>babel-traverse</code>, <code>babel-types</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17493">#17493</a> Update Jest to v30.1.1 (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> <li><code>babel-plugin-transform-regenerator</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17455">#17455</a> chore: Clean up <code>transform-regenerator</code> (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/babel/babel/blob/main/CHANGELOG.md"><code>@babel/preset-typescript</code>'s changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <blockquote> <p><strong>Tags:</strong></p> <ul> <li>💥 [Breaking Change]</li> <li>👓 [Spec Compliance]</li> <li>🚀 [New Feature]</li> <li>🐛 [Bug Fix]</li> <li>📝 [Documentation]</li> <li>🏠 [Internal]</li> <li>💅 [Polish]</li> </ul> </blockquote> <p><em>Note: Gaps between patch versions are faulty, broken or test releases.</em></p> <p>This file contains the changelog starting from v8.0.0-alpha.0.</p> <ul> <li>See <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v7.15.0-v7.28.5.md">CHANGELOG - v7.15.0 to v7.28.5</a> for v7.15.0 to v7.28.5 changes (the last common release between the v8 and v7 release lines was v7.28.5).</li> <li>See <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v7.0.0-v7.14.9.md">CHANGELOG - v7.0.0 to v7.14.9</a> for v7.0.0 to v7.14.9 changes.</li> <li>See <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v7-prereleases.md">CHANGELOG - v7 prereleases</a> for v7.0.0-alpha.1 to v7.0.0-rc.4 changes.</li> <li>See <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v4.md">CHANGELOG - v4</a>, <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v5.md">CHANGELOG - v5</a>, and <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-v6.md">CHANGELOG - v6</a> for v4.x-v6.x changes.</li> <li>See <a href="https://github.com/babel/babel/blob/main/.github/CHANGELOG-6to5.md">CHANGELOG - 6to5</a> for the pre-4.0.0 version changelog.</li> <li>See <a href="https://github.com/babel/babel/blob/main/packages/babel-parser/CHANGELOG.md">Babylon's CHANGELOG</a> for the Babylon pre-7.0.0-beta.29 version changelog.</li> <li>See <a href="https://github.com/babel/babel-eslint/releases"><code>babel-eslint</code>'s releases</a> for the changelog before <code>@babel/eslint-parser</code> 7.8.0.</li> <li>See <a href="https://github.com/babel/eslint-plugin-babel/releases"><code>eslint-plugin-babel</code>'s releases</a> for the changelog before <code>@babel/eslint-plugin</code> 7.8.0.</li> </ul> <!-- raw HTML omitted --> <!-- raw HTML omitted --> <h2>v8.0.0-rc.4 (2026-04-29)</h2> <h4>👓 Spec Compliance</h4> <ul> <li><code>babel-parser</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17954">#17954</a> fix(parser): ts parser small fixes (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> <li><a href="https://redirect.github.com/babel/babel/pull/17923">#17923</a> Support flow extends bound (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> <li><a href="https://redirect.github.com/babel/babel/pull/17888">#17888</a> TS parser small fixes (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> <li><a href="https://redirect.github.com/babel/babel/pull/17865">#17865</a> Fix(parser): flow parser small fixes (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> <li><code>babel-generator</code>, <code>babel-parser</code>, <code>babel-plugin-transform-spread</code>, <code>babel-types</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17871">#17871</a> Disallow super call after new (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> </ul> <h4>💥 Breaking Change</h4> <ul> <li><code>babel-cli</code>, <code>babel-helper-transform-fixture-test-runner</code>, <code>babel-helpers</code>, <code>babel-node</code>, <code>babel-register</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17938">#17938</a> Bundle more packages (<a href="https://github.com/JLHwung"><code>@JLHwung</code></a>)</li> </ul> </li> <li><code>babel-traverse</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17937">#17937</a> Remove <code>Scope#buildUndefinedNode</code> (<a href="https://github.com/nicolo-ribaudo"><code>@nicolo-ribaudo</code></a>)</li> </ul> </li> <li><code>babel-helper-wrap-function</code>, <code>babel-plugin-transform-block-scoping</code>, <code>babel-plugin-transform-regenerator</code>, <code>babel-traverse</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17907">#17907</a> Remove <code>NodePath#toComputedKey</code> (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> <li><code>babel-plugin-external-helpers</code>, <code>babel-template</code>, <code>babel-traverse</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17830">#17830</a> Replace remaining whitelist/blacklist with inclusive alternatives (<a href="https://github.com/stuckvgn"><code>@stuckvgn</code></a>)</li> </ul> </li> <li><code>babel-plugin-transform-property-mutators</code>, <code>babel-standalone</code> <ul> <li><a href="https://redirect.github.com/babel/babel/pull/17882">#17882</a> Remove <code>@babel/plugin-transform-property-mutators</code> (<a href="https://github.com/liuxingbaoyu"><code>@liuxingbaoyu</code></a>)</li> </ul> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/babel/babel/commit/61647ae2397c82c3c71f077b5ab109106a5cac0f"><code>61647ae</code></a> v7.28.5</li> <li><a href="https://github.com/babel/babel/commit/42cb285b59fc99a8102d69bef6223b75617e9f46"><code>42cb285</code></a> Improve <code>@babel/core</code> types (<a href="https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript/issues/17404">#17404</a>)</li> <li><a href="https://github.com/babel/babel/commit/eebd3a06021c13d335b5b0bd79734df3abbea678"><code>eebd3a0</code></a> v7.27.1</li> <li><a href="https://github.com/babel/babel/commit/fdc0fb59e119ee0b38bced63867a344a5b4bc2f3"><code>fdc0fb5</code></a> [Babel 8] Bump nodejs requirements to <code>^20.19.0 || >= 22.12.0</code> (<a href="https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript/issues/17204">#17204</a>)</li> <li><a href="https://github.com/babel/babel/commit/5c350eab83dd12268add44cce0eeda6c898211e3"><code>5c350ea</code></a> v7.27.0</li> <li><a href="https://github.com/babel/babel/commit/ca4865a7f43a6a56aec242e23e4a3e318cf0ca92"><code>ca4865a</code></a> Fix: align behaviour to tsc <code>rewriteRelativeImportExtensions</code> (<a href="https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript/issues/17118">#17118</a>)</li> <li><a href="https://github.com/babel/babel/commit/cd24cc07ef6558b7f6510f9177f6393c91b0549f"><code>cd24cc0</code></a> chore: Update TS 5.7 (<a href="https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript/issues/17053">#17053</a>)</li> <li><a href="https://github.com/babel/babel/commit/63d30381c169780460e01bdb6669c5e01af1dfbe"><code>63d3038</code></a> v7.26.0</li> <li><a href="https://github.com/babel/babel/commit/bfa56c49569f0bfd5579e0e1870ffa92f74fad48"><code>bfa56c4</code></a> Support <code>import()</code> in <code>rewriteImportExtensions</code> (<a href="https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript/issues/16794">#16794</a>)</li> <li><a href="https://github.com/babel/babel/commit/b07957ebb316a1e2fc67454fc7423508bb942e63"><code>b07957e</code></a> v7.25.9</li> <li>Additional commits viewable in <a href="https://github.com/babel/babel/commits/v7.28.5/packages/babel-preset-typescript">compare view</a></li> </ul> </details> <details> <summary>Maintainer changes</summary> <p>This version was pushed to npm by <a href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new releaser for <code>@babel/preset-typescript</code> since your current version.</p> </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] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
bddd23fd9c |
Fix application icons (#20142)
fixes application chip (icon Name) in all setting tables ## After <img width="1200" height="896" alt="image" src="https://github.com/user-attachments/assets/bd377f47-1d52-4142-b904-f2ce90c1db78" /> <img width="1200" height="917" alt="image" src="https://github.com/user-attachments/assets/f49cc742-f11e-47e3-86ed-34beffe493c7" /> <img width="1234" height="878" alt="image" src="https://github.com/user-attachments/assets/2ab459de-5f9d-4d39-9490-eec4ed9ee432" /> <img width="1239" height="845" alt="image" src="https://github.com/user-attachments/assets/3c1bf258-285a-47b9-a60d-05ba1564334d" /> <img width="1183" height="907" alt="image" src="https://github.com/user-attachments/assets/715b2470-2d88-48e3-88ac-d3daf3451717" /> <img width="1300" height="912" alt="image" src="https://github.com/user-attachments/assets/d7c829fa-bf1d-4f19-82de-a8bf29e22bfa" /> |
||
|
|
842e679cc6 |
fix(billing): gate AI credit-cap at entry points instead of workflow executor (#20096)
## Background The 2026-04-26 incident saw 716M Sonnet 4.6 tokens consumed in a single trial workspace. Two causes: failed agent executions weren't billed (addressed by #20065) and the credit-cap gate had been removed from `WorkflowExecutorWorkspaceService.executeStep` in #19904, leaving no enforcement point at all. ## Why not just revert #19904 #19904 was right that gating at the workflow executor is too coarse. When one user exhausted a workspace's credits via chat, *all* workflows hard-failed mid-run — including cheap DB/CRUD/branch automations costing essentially nothing. Reverting would re-introduce that cliff. ## New design: gate at the AI entry points The chat resolver already gates this way (`agent-chat.resolver.ts:137-148`). This PR replicates the same pattern at every other point where the workspace can incur real AI cost: - `executeAgent` in `agent-async-executor.service.ts` - the REST handler in `ai-generate-text.controller.ts` - `generateThreadTitle` in `agent-title-generation.service.ts` In each, after auth/validation: skip if `IS_BILLING_ENABLED` is false; otherwise call `BillingService.canBillMeteredProduct(workspaceId, BillingProductKey.WORKFLOW_NODE_EXECUTION)`; on `false`, throw `BillingException(BILLING_CREDITS_EXHAUSTED)`. No new method, no new exception code, no new product key. This matches industry convention (Lovable/Replit also gate at the expensive-operation boundary, not at every cheap step). ## Deliberately not gated - `WorkflowExecutorWorkspaceService.executeStep` — the design choice is now intentional, so the #19904 TODO is replaced by a one-line absolute-behavior comment explaining why the gate isn't here. Cheap workflow steps (DB CRUD, branching, action steps) are not gated, so a chat-driven cap exhaustion does not block non-AI automations. - `repair-tool-call.util` — repair is a sub-call inside an already-gated AI flow. If the parent is gated, repair will naturally not run. Adding a gate here adds complexity without value. ## Net effect A workspace that exhausts credits via chat or AI agent stops making AI calls. Its non-AI workflows continue running normally. A workflow with both AI and non-AI steps fails at the AI step with `BILLING_CREDITS_EXHAUSTED`, but downstream non-AI steps that don't depend on the AI output still run. ## Conflicts This PR overlaps with three other in-flight PRs in the same files. None of them touch the gate logic; rebasing on top of any of them is trivial: - #20065 (agent-async-executor): adds `workspaceId` to `executeAgent` args and bills in `finally`. The gate at the top of `executeAgent` from this PR sits naturally above that. - #20066 (REST controller): adds usage billing to the controller. - #20067 (title gen): adds usage billing to title generation and tool-call repair. Recommend landing #20065/#20066/#20067 first; this PR rebases trivially on top. ## Tests Out of scope per the PR series convention. The existing chat-resolver gate isn't unit-tested either; this PR follows the same precedent. Follow-up: add integration coverage that exercises a workspace at `hasReachedCurrentPeriodCap=true` against each of the three new gates plus the pre-existing chat-resolver gate. ## Future follow-ups - Per-user soft cap inside a workspace (the Lovable Business-tier pattern), so one user can't exhaust the workspace's cap. - Pre-flight cost estimate so the user sees an "approaching cap" warning before the hard stop. - Rename `BillingProductKey.WORKFLOW_NODE_EXECUTION` — the name predates this design choice and is misleading now that it gates AI entry points rather than workflow nodes. ## Test plan - [ ] Trigger a workspace into `hasReachedCurrentPeriodCap=true`. - [ ] Send a chat message — expect failure with `BILLING_CREDITS_EXHAUSTED`. - [ ] Run a workflow whose only AI step is an `ai-agent` action — expect that step to fail with `BILLING_CREDITS_EXHAUSTED`, downstream non-AI steps still run. - [ ] POST to `/rest/ai/generate-text` — expect `BILLING_CREDITS_EXHAUSTED`. - [ ] Create a new chat thread (which kicks off `generateThreadTitle`) — expect `BILLING_CREDITS_EXHAUSTED`. - [ ] Run a workflow with no AI step (only DB CRUD/branching/actions) — expect it to run unaffected. --------- Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]> |
||
|
|
a713f8d87f |
CalDAV: support Digest auth (#20135)
Adds digest auth support for CalDAV, mostly used by legacy servers /closes https://github.com/twentyhq/twenty/issues/19922 |
||
|
|
fd6d5f895d |
Ai Chat - Caching optim (#20126)
EDIT :
- solving auto-caching from Anthropic by updating ai-sdk/anthropic +
adding providerOption at stream level
- concerning Bedrock, it needs breakpoint
**1. Breakpoints were only on the system prompt**
The code already placed a cache marker on the system prompt (~10K
tokens). But the conversation history — which can grow to hundreds of
thousands of tokens — had no marker, so Anthropic re-read it at full
price on every turn.
The fix adds a prepareStep hook inside streamText that stamps the last
message with a cache breakpoint before every LLM call. Anthropic then
caches the entire conversation prefix, and subsequent turns read it at
$0.30/M instead of $3/M.
prepareStep is used rather than a one-shot pre-processing step because
an agentic turn makes multiple internal LLM calls as tool results
accumulate — the hook refreshes the breakpoint before each one.
**2. Bedrock was using the wrong field**
The system prompt marker for Bedrock was set as cacheControl: { type:
'ephemeral' } — which is the Anthropic wire format. The Bedrock Converse
API expects cachePoint: { type: 'default' }. The system prompt was
silently not being cached on Bedrock at all.
Both the system prompt and the new prepareStep now go through a shared
getCacheProviderOptions helper that returns the correct field per
provider.
**3. Persisted cached token usage to monitor cache strat. efficiency**
|
||
|
|
11628d19a3 |
add recurring calendar events for google cal (#19748)
Co-authored-by: Charles Bochet <[email protected]> |
||
|
|
46ba5fd16c |
i18n - translations (#20138)
Created by Github action --------- Co-authored-by: github-actions <[email protected]> |
||
|
|
4649736d49 |
[Command Menu] Fix record-selection command filtering in edit mode (#20034)
https://github.com/user-attachments/assets/fe1461c7-0d5c-4c6f-8c2e-2cf569e7de90 ## What Fix `RECORD_SELECTION` items leaking into the command menu when nothing is selected, and unify how the menu renders in normal vs edit mode. ## The bug `RECORD_SELECTION`-availability items were showing up even when `numberOfSelectedRecords === 0`. New util `doesCommandMenuItemMatchSelectionState` gates them, applied consistently in the runtime provider and the editor. ## The refactor `PinnedCommandMenuItemButtonsEditMode` was a 140-line near-duplicate of `PinnedCommandMenuItemButtons` with its own (drifting) filter logic. Killed it. Edit mode now flows through the same `CommandMenuContextProvider` with a new `isInPreviewMode` flag — one filter chain, one rendering path. ## Behavior in edit mode **Header (pinned buttons in page header):** - Runs the full filter chain — object metadata, page type, selection state, page layout, *and the conditional availability expression* - Buttons render at full styling but are inert via `pointer-events: none` + `cursor: not-allowed` - Preview now reflects exactly what users will see on the live page (not a grayed-out approximation) **Side panel editor:** - New `useEditableCommandMenuItems` hook - Same filters as runtime *minus* the conditional availability expression and `FALLBACK` items — so it surfaces everything that's actually configurable for this page context - Still gates on selection state — if no records selected, `RECORD_SELECTION` items are hidden from the editor too. Open to feedback if we'd rather always show them so users can pin them ahead of time. ## Misc - `usePinnedCommandMenuItemsInlineLayout` — visible count now waits until every item is measured before committing. Fixes a flash of wrong counts on mount/resize - Renamed `useCommandMenuContextApi` → `useCurrentCommandMenuContextApi` — name now conveys it reads from the *current* scoped context store - Copy: "Records selected" → "Record(s) selected" |
||
|
|
51384bc085 |
refactor: optimize website visual runtime (#20120)
Refactors the website visual runtime to make WebGL-heavy sections more reliable and less expensive. This adds shared image/model loading caches, safer WebGL context recovery, staggered visual mounting, and static rendering for decorative Helped card visuals. It also removes a large bespoke Helped renderer in favor of the shared halftone model canvas, reduces scroll/layout work in the Helped section, and cleans up duplicated model-loading code across several visuals. |
||
|
|
abfa6200dd |
ssrf hardening (#19963)
Hardened CalDav with new approach of wrapping axios ssrf http agent to fetch via `@lifeomic/axios-fetch` because `tsdav` only accept `fetch` override. Also Hardened test endpoint |
||
|
|
480e5796ec |
fix(ai): render record links inside markdown headings in AI chat (#20074)
## Summary Adds `h1`–`h6` component overrides to `LazyMarkdownRenderer` so that `[[record:...]]` references placed inside markdown headings in the AI chat are parsed by `processChildrenForRecordLinks` and rendered as clickable `RecordLink` chips, matching the behavior already in place for `p`, `li`, `td`, `th`, and `a`. Fixes #20072 ## Test plan - [ ] In AI chat, ask a question whose answer places a record reference inside a markdown heading (e.g. `## Found [[person:uuid:John Doe]]`) and confirm a clickable `RecordLink` chip renders instead of the raw `[[...]]` text. - [ ] Verify heading styling (sizes, weights, margins) is unchanged. Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: nitin <[email protected]> |
||
|
|
d8e2de48e6 |
Fix stale UI state after stop-impersonation (#20088)
## Summary A customer reported that after **Stop Impersonating**, the sidebar still showed the impersonated user's pinned favorites, the AI chat tab toggle, and the AI chat history — even though the original admin's session was correctly restored. ## Root cause The refactor in #19597 replaced the previous `signOut()`-based stop flow with an in-place token swap, but only cleared Apollo cache + reloaded the user. Several user-scoped client stores were left untouched: - **`metadataStoreState`** is localStorage-backed (`navigationMenuItems`, `agentChatThreads`, `views`, `pageLayouts`, etc.) and only refreshed by `MinimalMetadataLoadEffect`. That effect is gated by `metadataLoadedVersion` + `desiredLoadState`, neither of which flips on a same-workspace token swap, so the effect never re-runs. - **In-memory AI atoms** (`currentAiChatThreadState`, `agentChatInputState`, `hasInitializedAgentChatThreadsState`) keep pointing at the impersonated user's selected thread / input. - **Session localStorage keys** (`agentChatDraftsByThreadIdState`, `lastVisitedObjectMetadataItemIdState`, `lastVisitedViewPerObjectMetadataItemState`, `playgroundApiKeyState`) carry the impersonated user's drafts and navigation state. `clearSession()` (used by logout) avoids this because it calls `applyMockedMetadata()` and flips `desiredLoadState` mocked↔real, which chain-triggers a full metadata reload on next sign-in. ## Fix Extract a `resetUserScopedClientState` helper inside `useImpersonationSession` that: 1. Calls `clearSessionLocalStorageKeys()` to drop user-scoped localStorage keys. 2. Resets the in-memory AI session atoms. 3. Marks `metadataStoreState['agentChatThreads']` as `'empty'`. `useLoadStaleMetadataEntities` does **not** handle this entity key, so without an explicit reset to `'empty'` the `AgentChatThreadInitializationEffect` (which only fires on `'empty'`) would never refetch. 4. Calls `invalidateMetadataStore()` to clear all `currentCollectionHash` values and bump `metadataLoadedVersion`, forcing `MinimalMetadataLoadEffect` to re-run and refetch `navigationMenuItems`, `views`, `pageLayouts`, etc. against the new token. The helper is applied to both `startImpersonating` and `stopImpersonating` — start had the same latent bug; the impersonated user could see the admin's favorites until the cache happened to refresh. ## Test plan - [ ] As an admin user, pin some favorites in the sidebar - [ ] Impersonate a user with different favorites → favorites should switch to the impersonated user's - [ ] Click "Stop Impersonating" → sidebar should immediately show the admin's favorites (not the impersonated user's) - [ ] As an admin **without** AI permission, impersonate a user **with** AI permission, open AI chat, send a message, then stop impersonating → AI chat history should be empty / inaccessible (the AI tab visibility itself is fixed in a separate PR) - [ ] Type a draft in AI chat as the impersonated user → after stop, the draft should be gone - [ ] Verify regular sign-out still works while impersonating - [ ] Verify the impersonation banner still shows / hides correctly 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> |
||
|
|
b49e58dfc6 |
Fix click house migration (#20127)
`it does not support renaming of multiple tables in single query.` @etiennejouan manually fix the corrupted clickhouse instance |
||
|
|
a6118b7dc3 |
i18n - translations (#20125)
Created by Github action --------- Co-authored-by: github-actions <[email protected]> |
||
|
|
19ee9444ed | add UpsertViewWidget resolver (#20053) | ||
|
|
b92617d46e | Copy twenty-shared in twenty-website deploy (#20124) | ||
|
|
c476c6c80b |
chore: sync AI model catalog from models.dev (#20122)
Automated daily sync of `ai-providers.json` from [models.dev](https://models.dev). This PR updates pricing, context windows, and model availability based on the latest data. New models meeting inclusion criteria (tool calling, pricing data, context limits) are added automatically. Deprecated models are detected based on cost-efficiency within the same model family. **Please review before merging** — verify no critical models were incorrectly deprecated. Co-authored-by: FelixMalfait <[email protected]> |
||
|
|
d2dda67596 |
Fix upgrade --start-from-workspace-id (#20116)
# Introduction Prevent using both `--start-from-workspace-id` and `--workspace` When any of the two are being passed we prevent passing to the next instance segment, it would require an upgrade re run even if legit When `--start-from-workspace-id` is passed we filter from all the fetched active or suspended workspace ids and apply equivalent filter as before |
||
|
|
6aec449a56 |
refactor: harden website runtime, routing, and hero visual (#20113)
This centralizes routing/SEO ownership, replaces deprecated middleware with proxy, adds safer lifecycle/runtime primitives, and introduces visual error boundaries so broken WebGL/canvas-heavy visuals can fail gracefully instead of taking down the page. It also hardens animation, resize, visibility, cleanup, and WebGL fallback paths for a broader range of browsers and devices. The hero visual was split from large monolithic files into focused domain folders for shell, pages, shared primitives, window interactions, terminal conversation, prompt, editor, and traffic-light behavior. Legacy unused section code was removed, visual configs were extracted, state/geometry logic was moved into testable modules, and coverage was added across routing, SEO, lifecycle, animation, visual runtime, halftone behavior, and hero interactions. More changes on the way, but this should make the website a lot more stable - disabling WebGL on Firefox and loading the website does not cause crashes on local any longer, will test on dev once this is merged. |