95 lines · 7.4 KB · Markdown
RawDownload

Highlights

Unified credential bindings

Source credentials (OAuth tokens, header secrets, client-credential pairs) are now stored as scoped credential bindings instead of plugin-specific shapes. Two consequences for users:

  • One consistent UI for editing credentials across OpenAPI, MCP, and GraphQL sources. The old per-plugin credential forms are gone, replaced with a shared slot UI in @executor-js/react (credential-bindings, credential-slot-bindings, oauth-sign-in).
  • Existing OpenAPI / MCP / GraphQL / google-discovery credentials are migrated into the new binding rows automatically on first launch (drizzle migrations 0007, 0008, 0010 for apps/local). No user action required.

See where a secret or connection is used

A new executor.usages surface lets plugins declare every place they reference a secret or connection. The local UI uses it to:

  • Show a "used in N sources / M bindings" summary on the secret detail page.
  • Surface a clear "this secret is in use, remove the references first" toast (backed by the new SecretInUseError / ConnectionInUseError) instead of letting the delete fail silently.

Plugin authors implement usagesForSecret / usagesForConnection; the executor fans out and concatenates.

MCP source detection works on more servers

Adding an MCP source now succeeds against servers that previously failed to probe.

  • Bearer-auth MCP servers are detected on the initial probe instead of being misclassified as plain HTTP. Probe error messages also tell you what shape of auth challenge came back.
  • 401 challenges that advertise resource_metadata= are recognized as MCP-spec OAuth signals.
  • Probes accept RFC 6750-compliant body forms for the access-token check, so servers that don't honor the Authorization header on the probe path still discover correctly.
  • A live-snapshot regression suite covers 29 real public MCP servers; new probes are checked against those snapshots before shipping.
  • The MCP connection pool now keys by source identity, so two MCP sources pointing at the same upstream URL with different credentials no longer collide on one shared connection.

TypeScript code runs in dynamic-worker and QuickJS runtimes

Both runtimes strip TypeScript syntax before evaluation, so tools that pass TS source (annotations, as casts, type aliases, etc.) execute without a separate compile step. Previously you had to hand-strip types or precompile.

OpenAPI source UX

  • Source-add screens reworked: cleaner flow, the freeform combobox lists the URL you typed first, scoped credential UI clarified.
  • OpenAPI import size limit removed — large specs (Stripe, GitHub, etc.) import without truncation.
  • The OpenAPI source edit page lets you change the OAuth2 token / authorization endpoint URLs without removing and re-adding the source.
  • Source favicons render again on the sources list (regression from the source-credential cutover).
  • listSourceBindings no longer 500s when called after a source has been removed.

OAuth reliability

A pile of small fixes to the OAuth flow, individually unspectacular, collectively meaning fewer mysterious "Sign in" failures:

  • DCR registration declares the requested scopes in the body so providers that key on body-scope (rather than scope= on the auth URL) issue refresh tokens with the right grants.
  • Refresh requests use the exact scopes from the original token grant; servers that reject scope upgrades on refresh stop returning invalid_scope.
  • id_token values returned alongside an access token are stripped before validation (some providers send malformed JWTs in this slot, which used to fail the whole exchange).
  • The scope parameter is omitted entirely when empty, instead of being sent as scope=.
  • OAuth endpoint URLs from discovery / DCR are validated; obviously-broken metadata fails fast with a clear message rather than later in the popup. Exposed as assertSupportedOAuthEndpointUrl / isSupportedOAuthEndpointUrl for plugin use.
  • Token-endpoint failures now include the upstream HTTP status + body summary in the surfaced error.
  • Popup handling: the popup is reserved before the start request fires, and close events are detected reliably, so cancelling sign-in no longer leaves the UI stuck waiting.

Source-registration tools require approval

Tools that register new sources (e.g. addSource on the OpenAPI plugin) now go through the standard approval gate by default, the same way destructive tools do. Safer to point an agent at a workspace that has source-mutating tools available.

Migration safety for older CLI builds

If an older executor build opens a data directory that has been migrated by a newer build, you now get an explicit "this data directory was created by a newer version" error instead of a low-level SQLite schema mismatch crash. Drizzle migration preflight checks were also tightened so partially-applied migrations are caught earlier.

SDK additions

For plugin authors and embedders:

  • Usage, UsagesForSecretInput, UsagesForConnectionInput — the usages contract.
  • CredentialBindingKind, CredentialBindingValue, ConfiguredCredentialBinding, ConfiguredCredentialValue, ScopedSecretCredentialInput, CredentialBindingRef, SetCredentialBindingInput, RemoveCredentialBindingInput, ReplaceCredentialBindingsInput, ResolvedCredentialSlot, CredentialBindingId — the new credential bindings surface.
  • SecretInUseError, ConnectionInUseError — typed errors for blocked deletes.
  • RefreshSourceInput, RemoveSourceInput, RemoveSecretInput, RemoveToolPolicyInput, CredentialBindingRow — new typed inputs / row types.
  • ScopedDBAdapter, ScopedTypedAdapter — type exports for scope-aware storage adapters.
  • Plugin clientConfig is threaded through vite-plugin into the client bundle, so plugins can hand SDK-side config to their React surface without a separate config endpoint.
  • Schema compile perf: a new lint rule + hoisted Schema compilers keep parse-paths fast.

Fixes

  • executeWithPause now settles correctly when the running fiber fails — previously a fiber failure could leave the execution hanging instead of surfacing the error. (#523)
  • isDevMode correctly identifies the compiled bun binary, so installed CLI builds no longer misdetect themselves as running from source. Thanks @grfwings (#699)
  • Drizzle migration handling parses migration metadata with a typed schema and reports outdated-client failures cleanly. Thanks @grfwings (#741)
  • Frontend errors and API-client decode failures are now reported through the existing error-reporting path instead of being swallowed silently.
  • Source forms keep local error messages on screen instead of clearing them on the next render.
  • "Remove in-use source" surfaces a toast instead of a silent failure. (#530)

Breaking changes

SDK: makeTestConfig import path moved

The deep import path moved from @executor-js/core/sdk/testing to @executor-js/core/sdk/test-config. The package-root re-export is unchanged:

// still works
import { makeTestConfig } from "@executor-js/core/sdk";

SDK: per-plugin credential shapes replaced by credential bindings

If you authored a plugin that stored OAuth tokens or other credentials directly under a plugin-specific column, migrate to the unified CredentialBinding* surface. The in-tree plugins (OpenAPI, MCP, GraphQL, google-discovery) have all been ported — see them for reference. End users of the CLI / web UI are unaffected; existing rows migrate automatically.