Arcade 1.11.0

App version 5e1519c · released 2026-09-29 · previous 1.10.1

Release notes

This release removes the engine's chat completions API, changes the shape of every list response, turns a gateway built-in on by default, and changes five tool contracts. Read the Upgrade notes before upgrading. The first one blocks helm upgrade for any install with Redis TLS on; most of the rest are for the teams that call Arcade's APIs rather than for the cluster.

Database migrations

This release applies schema changes. Migrations run automatically on helm upgrade unless <service>.database.migrations is false.

  • Engine — records when a credential renewal ended without a token. Required by the credential-renewal fix below.
  • Engine — replaces the index behind the tool-execution listing with one that carries the tie-breaker, in two steps: create the new index, then drop the one it supersedes. Supports the list-ordering fix below; the listing is correct without it but sorts instead of reading the order from the index.
  • Engine — adds a nullable column for MCP tool metadata to the tool catalog. Not required by anything else in this release, but the new engine reads and writes it, so it must apply before the new image serves.
  • Engine — adds a table. Not required by anything in this release.
  • Engine — adds three columns, with defaults, to an existing table. Not required by anything in this release.
  • Coordinator and experience-api — none.

The index is built concurrently, so writes are not blocked, but the pre-upgrade migration hook waits for it: on a large execution history, allow for the build in your helm upgrade --timeout. Everything else is additive. Rolling back does not run down-migrations; the new columns and table stay, and the previous engine image's execution listing is served by the replacement index.

Security

  • GET /v1/tools/{name} and GET /v1/formatted_tools/{name} no longer return the full definition of a tool the access policy denies. They answer 404, as for an unregistered name. The read could be used to discover exactly what governance was meant to hide.
  • A tool the access policy refuses returns 400 tool_not_found over REST, identical to an unregistered name. It previously ran the call and answered 200 with "access denied", which confirmed the tool existed.
  • A failed call to an unreachable server no longer returns the server's address. The same error carried the SSRF guard's refusals, so anyone able to register a worker could map internal reachability from tool-call errors. A worker response is also capped at 10 MB when it omits or understates its length.
  • An engine restricted to a set of organizations can no longer start a tool-authorization flow for an organization outside that set.
  • A malformed request URL no longer crashes the experience API — an unauthenticated denial of service.
  • The worker no longer logs third-party request and response payloads. Libraries such as the GraphQL client logged full Linear responses — issue text, names, email addresses — and other toolkits logged URLs with their query strings. Third-party libraries now log at WARNING and above; Arcade's own worker logs are unchanged.
  • The dashboard CSP drops unsafe-inline and unsafe-eval, and the experience API sends CSP, X-Frame-Options, Referrer-Policy, Permissions-Policy and nosniff. Both send HSTS. See Upgrade notes.

Resolved CVEs

Advisories remediated in the bundled application images since fd0f5f2:

  • CVE-2026-45820 — fflate 0.8.3 in the dashboard
  • CVE-2026-56854 — golang.org/x/crypto 0.56.0
  • CVE-2026-56855 — golang.org/x/crypto 0.56.0
  • CVE-2026-78662 — golang.org/x/crypto 0.56.0
  • CVE-2026-81870 — go.opentelemetry.io/otel/sdk 1.45.0
  • CVE-2026-84378 — httpx2 / httpcore2 2.12.0 in the Mixpanel toolkit
  • CVE-2026-84381 — httpx2 / httpcore2 2.12.0 in the Mixpanel toolkit
  • GHSA-22p9-wv53-3rq4 — linkify-it 5.0.2 in the dashboard
  • GHSA-5p39-cfhj-2xmp — anyio 4.14.2 in the coordinator and across worker toolkits
  • GHSA-82r6-8w77-94w6 — anyio 4.14.2 in the coordinator and across worker toolkits
  • GHSA-866g-f22w-33x8 — @ai-sdk/provider-utils 4.0.51 in the experience API
  • GHSA-f38q-mgvj-vph7 — protobufjs 7.6.6 in the experience API
  • GHSA-gjv8-xp57-g29c — soupsieve 2.9.2 across worker toolkits
  • GHSA-j3f2-48v5-ccww — protobufjs 7.6.6 in the experience API
  • GHSA-j934-xhv5-fg8f — soupsieve 2.9.2 across worker toolkits
  • GHSA-v245-v573-v5vm — linkify-it 5.0.2 in the dashboard

Added

  • Group-based tool access. A group_access contextual-access plugin hides and refuses tools according to the caller's Okta, Entra ID or SailPoint ISC group membership, at both listing and execution. It is generally available with no feature switch: to stop enforcing it, set a configuration inactive or delete it. Created and edited from the dashboard or the plugins API.
  • Every MCP gateway URL is also a Registry page. Opened in a browser, the gateway URL shows a page for that gateway only: sign in (OAuth, or API key and user ID for a header-auth gateway), browse its tools grouped by app with how many you have authorized, run one, and — with suggestions on — see and back requests for tools that are missing. MCP clients are unaffected; the page is served only to browsers.
  • Gateway suggestions. Adding ?registry_suggestions=true to a gateway URL gives end users tools to file a request for a missing capability, browse existing requests and support one. Each is credited to the signed-in end user on every gateway auth type. Admins get a suggestions inbox on each gateway, with Open and Resolved tabs and an optional resolution note. 1.10.1 created the tables; this release reads and writes them.
  • A Browse tab on the Servers page adds a third-party MCP server from the shipped catalogue in one click, and shows each added server's authorization state on its tile.
  • coordinator.cspEnforce — the coordinator now sends a nonce-based Content-Security-Policy, Report-Only by default. true enforces it.
  • oauthProviders.providers[].oauth2 — an override block applied over a well-known provider's bundled endpoints, scope delimiter and PKCE setting. This is how a Microsoft provider authorizes against a single Entra tenant; see Fixed.
  • workerDefaults.telemetryOverrides — per-service telemetry for workers, shared by every worker. See Fixed.
  • engine.gatewayBootstrap.waitForWorkers (default true), and tools_source: optimized on a static gateway in the engine config, which builds its allowlist from every optimized tool in the worker catalogue at bootstrap, unioned with any explicit tools:.
  • Gateway URL presentation options. ?tool_recommendation=false lists every configured tool instead of the recommendation surface, and ?arcade_tools=false leaves out the Arcade and System tools. The saved gateway is unchanged, and the options can only narrow what it allows.
  • Per-tool requirements on the public tools endpoint. Each tool carries its own OAuth provider with only that tool's scopes, and the secrets it reads. The toolkit-wide rollup on the catalog is unchanged.
  • Audit Logs gets the standard table: page numbers with a total, a row detail you can link to, and a filter for an exact date range. Audit Logs and Tool Executions both show a Load newer banner when new rows arrive, without moving the table.
  • New toolkits: Airtable (nine tools for bases and records, beside the existing starter), Calendly (twelve tools, beside the starter), Freshservice (six read-only tools with per-user OAuth; each customer registers their own Freshworks OAuth app) and Workday (time-off self-service).
  • New tools in existing toolkits:
    • Outlook Calendar: UpdateEvent changes a meeting in place; RemoveEventFromMyCalendar drops your own copy without telling anyone; CancelEvent calls off a meeting you organize and tells the guests. GetEvent returns body_html and CreateEvent takes body_format, so formatted descriptions survive a round trip.
    • Outlook Mail: CreateMailFolder, MarkEmails (read state and the follow-up flag), MoveEmails, each with a shared-mailbox twin; replies take cc_add, cc_remove and bcc; messages report sent_date_time.
    • Figma: eighteen tools for dev resources, comment triage, file metadata and versions, variables and library analytics.
    • Firecrawl: Search, ExtractData, GetExtractStatus, SearchDeveloperDocs, SearchResearchPapers, SearchGithubIssues.
    • Linear: RemoveIssueRelation.
    • Google Calendar: RespondToEvent accepts a tentative reply.
    • Google Slides: GetSlideThumbnail can return the image itself.
    • Google Docs: comments carry the passage they are anchored to and whether they are resolved.
    • Zoom: GetMeetingTranscript reads the AI Companion transcript of a meeting that was not cloud-recorded.

Changed

  • Audit events go to the coordinator over HTTP. The engine used to write the audit stream directly; it now posts signed events to the coordinator, which owns the stream. features.auditLog.publishMethod: redis restores direct writes.
  • System_ManageAuthorization is on by default. See Upgrade notes.
  • A tool call over REST answers the way MCP does. A policy refusal is 400 tool_not_found; a 403 for an unauthorized user keeps its status and error name and adds an authorization object (url, id, provider_id, scopes); and executing a tool that needs authorization now starts the authorization flow, as MCP already did.
  • List endpoints honour the requested window. Connected accounts applied the offset twice and skipped rows on every page after the first; secrets ignored limit / offset; a worker's tool list came back unsorted in an undocumented shape and now returns documented tool responses, sorted and paged; execution, gateway and plugin listings break timestamp ties by id so rows cannot swap between pages.
  • The coordinator logs one structured line per request. Each carries request_id, method, path, status and duration, so a Datadog filter on one request_id finally returns coordinator lines. The chart passes --no-access-log so uvicorn's own access line is not written twice. Query strings are never logged. The coordinator and engine also continue a request_id that arrives only in W3C Baggage instead of minting a new one.
  • The engine reads engine.yaml once, at startup. It used to reload in place whenever the mounted ConfigMap changed, so during a helm upgrade old pods could switch to the new config one at a time before being replaced. The chart already rolls engine pods on a config change; a hand-edited ConfigMap now takes effect on the next restart.
  • Tool-access refusals are recorded in the execution history for calls over MCP and the Arcade.* built-ins, where they previously left no trace. A refusal because the policy could not be consulted has its own reason. Expect more failed rows on projects with an access policy.
  • Gateway bootstrap waits for workers and refuses to empty the gateway list. Only with engine.gatewayBootstrap.enabled: true. The bootstrap Job waits for the incoming release's workers before running, and a bootstrap that cannot resolve its allowlist now fails instead of reconciling to no static gateways at all.
  • Google file-picker links are 14 to 21 percent shorter across every Google Workspace toolkit, so an agent that writes one out is less likely to break it, and the picker page now confirms which files were shared.

Fixed

  • Unread audit events are no longer silently discarded. The engine trimmed the audit stream at 10,000 entries while the coordinator allowed 100,000, so a lagging consumer lost events it had not read. Both writers now trim at features.auditLog.streamMaxLen.
  • One refused credential renewal no longer stalls a whole tenant. Callers waiting behind the renewal lease were never told the provider had refused it, so each waited out its own 60-second deadline and received no tools. Tool listing checks every provider in the tenant, so one dead credential stalled Arcade_ListApps, Arcade_SelectTools and the MCP handshake for everyone. Waiters now learn the outcome within milliseconds. Requires the engine migration.
  • Minute-long POST /v1/tools/select stalls. Tool listing resolved authorization for every tool in the organization and then filtered, so one unrenewable credential anywhere stalled the response. Authorization is now resolved over the filtered list, and access hooks are asked only about the gateway's own tools rather than the whole catalogue.
  • Remote MCP authorization:
    • An operator's scope selection reaches the authorization link. Opening the servers list left a scope-less request behind that answered the next click, which a server requiring a scope refused for an hour.
    • An operator who holds a personal credential for a server can authorize that server once it holds none, instead of being told it is already authorized.
    • An OAuth server's tools appear in the gateway picker as soon as it is authorized, rather than after someone opened its details page.
    • A server that accepts initialize anonymously and challenges only on a tool call, such as AWS's managed MCP server, is reported as needing authorization instead of permanently requirement-free.
    • A server that rejects the legacy ping is no longer reported unhealthy.
  • A worker keeps its tools when its catalog cannot be read. An unreachable third-party MCP server used to have its whole catalog deleted until the next successful sync. A worker whose first fetch fails no longer vanishes from the admin API.
  • Tool results arrive as the tool wrote them. An upstream MCP server's content is forwarded beside its structuredContent rather than replaced by the JSON of it, and multi-block, scalar and string results are no longer escaped a second time.
  • Listing workers no longer fails in a project with none — the case on an install with no default workers configured.
  • The engine's calls to the coordinator bypass HTTP_PROXY / HTTPS_PROXY. The in-cluster service hostname did not match typical NO_PROXY entries, so API-key verification went through a corporate proxy and failed.
  • A tenant-scoped oauth2 block on a well-known provider is honoured again. Since 1.9.x a Microsoft provider configured for a single Entra tenant authorized against the multi-tenant authority, which a single-tenant app registration refuses. Set it through oauthProviders.providers[].oauth2.
  • A JWT exp claim mapped to expires_in in a custom OAuth provider no longer fails token exchange and refresh.
  • Expired execution history is marked for deletion at :00 and :30 rather than 30 minutes after each engine start, so frequent restarts no longer postpone retention for hours.
  • Worker traces on Helm installs. The chart never passed telemetry.* to the worker, so worker spans were missing even with telemetry.traces: otlp. Worker pods now restart when telemetry values change.
  • With tool discovery enabled (discovery.enabled), an engine replica recovers by itself after a discovery pod is evicted instead of failing every recommendation until restarted, and a lookup that failed reaches the agent as a retryable error rather than an empty list or an unknown tool.
  • The dashboard recovers after a deploy. A tab open across a deploy that asked for a removed file showed an error panel nothing could clear; it now reloads once onto the current build. Screens that swap a button label no longer crash with a page-translation extension running.
  • Clearing the retention-days box on the Logging Policy page no longer refills it — deleting the 7 to type a 4 saved 74.
  • New users are no longer skipped past onboarding's goal picker because of an instance-wide static gateway.
  • The published engine OpenAPI documents plugin and hook routes at the paths that exist, under /v1/orgs/{org_id}/… and /v1/orgs/{org_id}/projects/{project_id}/….
  • Toolkits:
    • Notion: every call returned 401 — the Authorization header lacked the Bearer scheme.
    • Slack: tools taking channel_name resolved it by paging the workspace's most limited API on every call, so a few agents could rate-limit every Slack tool in a workspace. Private channels are no longer labelled public.
    • Gmail: ForwardEmail quotes the original's HTML and stays in its thread.
    • Google Calendar: CreateEvent honours send_notifications_to_attendees; guests were emailed whatever was asked.
    • Google Drive: SearchFiles finds the contents of shared-drive folders and holds limit to Drive's range.
    • Figma: version history pages toward older versions.
    • Outlook Mail: multi-line replies keep their line breaks; a subject containing a line break or null is refused rather than silently altered.
    • PagerDuty: GetTeam returns members, services and schedules, which it always reported empty. It and a few user tools declare the scopes their requests need, so users may be asked to authorize again.
    • Zoom: meeting search no longer steers transcript requests to recorded meetings only, and lists every standing one-to-one.
    • Linear: project lookups by name work again. See Upgrade notes.

Removed

  • POST /v1/chat/completions, its project-scoped twin, /v1/admin/models, the chart's llm: block and engine.llmSsrfAllowlist.
  • page_count and count from list responses.
  • Cursor pagination on the audit-log listing: cursor, next_cursor, has_more.
  • The scheduled-execution runner.
  • The ArcadeEngineApi starter toolkit.
  • Outlook Mail's MoveEmailToFolder and SharedMailboxMoveEmailToFolder.
  • Outlook Calendar's online_meeting_url and WhoAmI default_timezone.
  • Firecrawl 3.x arguments listed in Upgrade notes.

Operator impact

  • redis.tls.insecureSkipVerify is required when redis.tls.enabled is true; the chart will not render without it.
  • New values, all defaulting off or to the previous behaviour except the first two: engine.manageAuthorization.* (on), features.auditLog.publishMethod (http; was effectively redis), coordinator.cspEnforce, oauthProviders.providers[].oauth2, workerDefaults.telemetryOverrides, engine.gatewayBootstrap.waitForWorkers.
  • Removed value: engine.llmSsrfAllowlist.
  • manage_authorization: in engine.extraConfig stops the render.
  • Coordinator access logs change format; update any parser keyed on uvicorn's access line.
  • A hand-edited engine ConfigMap no longer takes effect without a pod restart.
  • Worker Deployments gain a telemetry ConfigMap and restart when telemetry values change.
  • The dashboard and experience API send HSTS with includeSubDomains.
  • Engine migrations: one required, one index rebuild sized by the execution history, three with nothing depending on them.
  • Integrators must migrate off chat completions, page_count / count, audit-log cursors and single-request secret listings; Outlook Mail, Outlook Calendar, Figma, Linear and Firecrawl callers must migrate.

API & behavior

  • POST /v1/chat/completions (both paths) and /v1/admin/models: 404.
  • Every list response: exactly items, limit, offset, total_count.
  • Audit-log listing: limit / offset only; cursor ignored.
  • GET /v1/admin/secrets: default page of 100. User sources: default 100, max 500.
  • GET /v1/workers/{id}/tools: documented tool responses with qualified_name, sorted and paged.
  • GET /v1/tools/{name}, GET /v1/formatted_tools/{name}: 404 for a policy-denied tool; Arcade.* built-ins now resolve.
  • POST /v1/tools/execute: policy refusal is 400 tool_not_found; 403 carries authorization; the call starts the authorization flow.
  • POST /v1/tools/search and POST /v1/tools/select are in the published OpenAPI spec, so generated SDKs expose them.
  • The public tools endpoint: per-tool requirements.
  • Gateway URLs: ?tool_recommendation=false, ?arcade_tools=false, ?registry_suggestions=true.
  • Gateway suggestions: list, create and resolve under /v1/orgs/{org_id}/projects/{project_id}/gateways/{gateway_id}/suggestions.
  • MCP tool results: upstream content forwarded beside structuredContent; no second escaping.
  • Sessionful MCP no longer puts the engine's internal error text in a JSON-RPC error's data, matching the stateless transport.
  • Tool-call errors for an unreachable server name only the toolkit and tool.
  • System_ManageAuthorization listed on gateways by default.