Arcade 1.10.1
App version fd0f5f2 · released 2026-09-11 · previous 1.10.0
This release has upgrade notes
Read the upgrade notes before upgrading: they list what you must do before or during the upgrade.
Release notes
Do not treat the patch number as a safe upgrade. This release renames a Secret, adds three values, and changes four tool contracts. If you resolve the chart through a range such as ~1.10.0 you will pick it up automatically — pin an exact version until you have read the Upgrade notes.
Database migrations
This release applies schema changes. Migrations run automatically on helm upgrade unless <service>.database.migrations is false.
- Engine — a renewal claim and version stamp on the stored OAuth credential tables. Required by the concurrent-renewal fix below.
- Engine — an exchange claim on the remote-MCP authorization request table. Required by the double-redeem fix below.
- Engine — two tables for gateway suggestions and supporters. Not required by anything else here; nothing reads them yet, but the upgrade runs the DDL.
- Coordinator and experience-api — none.
All three are additive, so nothing is rewritten and no meaningful lock is held. Rolling back does not run down-migrations; the new columns and tables stay and the previous engine image ignores them.
Security
- A JWKS response marked
no-storeis no longer retained and re-served on a later failed refresh. A client could not previously useno-storeto stop an old key being accepted once its key server became unreachable — the situation while rotating away from a compromised key. - Concurrent credential renewals no longer replay an already-exchanged refresh token, and one remote-MCP authorization code is no longer redeemed twice. An authorization server implementing replay detection reads either as theft and revokes the whole grant, so both were silently destroying working connections.
Resolved CVEs
Advisories remediated in the bundled application images since bc1509f:
- CVE-2026-39821 (GO-2026-5026) — Go standard library; bundled OpenFGA server rebuilt on go1.26.8 at v1.20.0
- CVE-2026-63072 —
openssl3.5.8-r0 in the dashboard nginx runtime image - CVE-2026-84304 —
google.golang.org/grpc1.83.1 - CVE-2026-84445 —
google.golang.org/grpc1.83.2 - GHSA-5278-rrxc-mgf7 — OpenFGA server v1.19.0
- GHSA-vp52-pcj8-j9qc —
grpc-health-probev0.4.57, in the OpenFGA image
Added
- Tools can carry a user interface. The engine reads MCP resources from an HTTP worker and preserves a tool's
_meta, so a client that can render an interface receives one. The Math toolkit ships the first. Interfaces stay off the REST tool responses. experienceApi.publicCatalog.enabledserves credential-free branded tool catalog endpoints at/api/public/tool_catalogand/api/public/tools. Defaultfalse, andengine.publicCatalog.enabledmust be on too.…metadataUrldefaults to the Arcade design-system CDN — repoint it for a private deployment. A branding outage degrades to null metadata; an engine outage returns 503.postgres.directHost/.directPort, plus per-service<service>.database.directHost/.directPort, name an endpoint reaching PostgreSQL directly past a pooler. Set them whenhostis PgBouncer in transaction pooling mode: migrations take a session-scoped advisory lock andCREATE DATABASEneeds thepostgresdatabase, and a transaction pooler provides neither. Each falls back tohost/port.engine.toolsListPageSize— tools per MCPtools/listpage.0(default) keeps the engine's own default of 100.encrypt-execution-payloadsconverts tool-execution rows recorded before payload encryption was enabled, andrekey --payload-to-keyrotates the two execution tables onto a new payload key.delete-accountperforms a GDPR/CCPA deletion across the identity provider, the messaging platform and both databases, dry-run until--commit.- Every Outlook Mail and Calendar tool publishes an
outputSchema. They returned an untyped object before, so a model could not see that a listed event carries an id without guessing.
Changed
- Gateway bootstrap runs in its own Job. See Upgrade notes.
- A job spanning two services reports itself not ready when either is unauthorized. It previously returned the authorized half and appended the authorization link, and agents pushed on about 90% of the time — answering from partial data while the link went stale.
- The bundled OpenFGA server moves from v1.18.3 to v1.20.0. No schema change, so the migration is a no-op and rollback is unconstrained.
- An invitation to an existing project member is refused whatever the casing or stray whitespace of the address typed. It was previously accepted whenever the spelling differed from the stored one, sending a real email and listing the person under both Members and Pending invitations.
- Shipped example configs source payload keys from paired
EXECUTION_PAYLOAD_KEY_<n>_NAME/_VALUEvariables, so a rotation adds a slot instead of editing one. The chart's own rendering is unchanged. - The post-install notes no longer tell every operator to backfill authorization grants on 1.9.8 — that applies only to organizations never enrolled in operator RBAC.
Fixed
- Two callers needing the same expired credential no longer destroy it. Both presented the same refresh token; where the server rotates them, the second presentation is of an already-exchanged token, indistinguishable from a stolen one, so the whole grant is revoked. Renewal is now claimed once and rejected if the credential moved underneath it. Affects tool authorization and remote MCP.
- Authorizing a remote MCP server no longer reports success then 401s every tool fetch. Waiters on several replicas adopted the same pending request and each redeemed the same single-use code. The exchange is now claimed once.
- Every OAuth-protected remote MCP server reported
no valid token available, authorization requiredon every status poll, whatever was stored. Two causes: the authorize handler looked for a server-wide default credential rather than the caller's and built a client with no token store, and the OAuth-detection probe swapped in a throwaway client and never swapped it back. The message was manufactured locally — the credential was never read and the remote never contacted. - The "Waiting for Authorization" spinner resolves, and the servers list stops showing Pending Auth beside authorized servers. With no status read available, waiters re-sent the authorize request, which rediscovered scopes and minted a second flow that replaced the one being polled.
- One unreachable server no longer stalls the whole servers page. Requirements are read in parallel under a short deadline, the renewal wait is sized for the call it makes, and an unreachable server renders with blank requirements while the rest of the list loads.
- Authorizing any Google tool could fail with no usable reason.
GoogleDrive.SearchDriverequested a broad Drive scope unconditionally instead of honouringARCADE_GOOGLE_DRIVE_SCOPE_MODE, and the shared Arcade Google OAuth app is not verified for it. Tool scopes are combined into one challenge, so that single tool made it refusable for every Google tool in the request, surfacing only asprovider_unavailable. Removing the tool is the fix; setARCADE_GOOGLE_DRIVE_SCOPE_MODE=fullviaworkers[].extraEnvif you run your own verified OAuth app. - Two engine replicas could claim the same due scheduled execution and run it twice. Only affects executions queued before this release — which are exactly the rows draining during the upgrade.
- Both the engine and the coordinator survive PgBouncer in transaction pooling mode. Neither disabled prepared-statement caching, producing intermittent
prepared statement ... does not existfailures under load. Session-scoped work now routes to the direct endpoint. - The custom-verifier test on the User Verification page no longer reports success for any URL you paste, including one that does not exist. The URL was never contacted — the flow completed against the signed-in tester's own address. It now fails after 90 seconds if nothing confirms.
- An MCP worker returning tool-result content the engine cannot represent gives a tool-level failure instead of a 500 that paged on-call.
- Outlook Calendar event windows no longer shift by an hour across a daylight-saving boundary. The offset came from the server clock rather than the date asked about. The shared Microsoft timezone handling was reworked underneath, so displayed times may shift for mailboxes that were wrong before.
- Engine SQL is visible in Datadog again — the statement text was recorded under a nested key rather than the scalar one dashboards read.
- Experience-api log records carry
trace_idandspan_id, closing the one hop where log-based trace correlation died. classification.service_domainsis returned again by the public tools endpoint; it had been dropped from every tool.- GitHub review comments attach to the pull request's current head rather than a commit from a paginated list, and a reply that succeeds while its thread resolution fails says so instead of inviting a duplicate.
engine.extraConfigno longer silently produces an unstartable engine, andhelm rollbackworks again across this chart version.- The generated-keys Secret is no longer deleted and recreated on every upgrade.
Removed
run_aton the tool-execute endpoint.- GitHub's
pageandper_pagearguments across every list and search tool. - Linear's separate issue-only label listing.
- Outlook Mail's
ListEmailsInFolder,ListEmailsByProperty,CreateDraftEmailandUpdateDraftEmail, each with its shared-mailbox twin. GoogleDrive.SearchDrive.
Operator impact
- Encryption keys move to
<release>-encryption-keys. Anything reading the old name by string — External Secrets configs, runbooks, backup scripts — needs updating. - New values, all defaulting off or inert:
experienceApi.publicCatalog.*,postgres.directHost/.directPort(and per-service equivalents),engine.toolsListPageSize. engine.extraConfigis validated at render time;rbac.enabled: truerenders again.engine.gatewayBootstrap.enabled: truerenders a second Job and reconciles gateways after the release is applied rather than before.- Three additive engine migrations, two of them required.
- Slack users must re-authorize; GitHub, Linear, Outlook Mail and Google Drive callers must migrate.
API & behavior
POST /v1/tools/executewithrun_at:400 malformed_request.GET /v1/public/toolsreturnsclassification.service_domainsagain.- New anonymous
/api/public/tool_catalogand/api/public/toolson the experience API, off by default. - Unrepresentable MCP tool-result content: tool-level failure, not 500.
- GitHub list and search:
limit/offsetwithnext_offset. - Linear label tools: routed by
label_type. - A tool needing two services reports the whole job unauthorized when either is.