|
1 | 1 | ## Highlights |
2 | 2 |
|
3 | | -### Install paths fixed |
| 3 | +### Unified credential bindings |
4 | 4 |
|
5 | | -`npm i -g executor` and `bun i -g executor` both work cleanly on a fresh machine. For machines without node, `curl … install.sh | bash` does the same thing. |
| 5 | +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: |
6 | 6 |
|
7 | | -> 1.4.13 and 1.4.14 were partial releases that didn't make it to npm cleanly. If you tried `npm i -g executor@latest` and got an older version, that's why. 1.4.15 is the first complete release of the new packaging. |
| 7 | +- 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`). |
| 8 | +- 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. |
8 | 9 |
|
9 | | -### MCP sources honor upstream `destructiveHint` |
| 10 | +### See where a secret or connection is used |
10 | 11 |
|
11 | | -MCP sources now read `destructiveHint` from upstream tool annotations. Tools marked destructive will require approval before running, surfaced via MCP elicitation. Refresh existing sources (or remove + re-add) to pick up annotations on tools added before this change. |
| 12 | +A new `executor.usages` surface lets plugins declare every place they reference a secret or connection. The local UI uses it to: |
12 | 13 |
|
13 | | -### Set tool policies from the Tools page |
| 14 | +- Show a "used in N sources / M bindings" summary on the secret detail page. |
| 15 | +- 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. |
14 | 16 |
|
15 | | -The local UI gains a **Policies** tab for managing approval rules, plus a per-row action menu on the Tools tree. Hover any tool or category and pick **Always run / Require approval / Block / Clear** — leaf rows save a rule for the exact tool id, group rows save a `prefix.*` wildcard. New rules are auto-placed by specificity so a freshly-added group rule never silently shadows an existing leaf rule. The same menu is available from the tool detail header and from any source-detail page. |
| 17 | +Plugin authors implement `usagesForSecret` / `usagesForConnection`; the executor fans out and concatenates. |
16 | 18 |
|
17 | | -### Per-user OAuth for OpenAPI and MCP sources |
| 19 | +### MCP source detection works on more servers |
18 | 20 |
|
19 | | -OpenAPI and MCP sources now carry first-class **Connections** — a per-user sign-in state decoupled from the source definition itself. |
| 21 | +Adding an MCP source now succeeds against servers that previously failed to probe. |
20 | 22 |
|
21 | | -- Save an OAuth2 OpenAPI or MCP source **before** signing in; users sign in later from the source page. |
22 | | -- Each connection refreshes independently, with concurrent refreshes deduped across the SDK. When a refresh can't recover, the SDK surfaces an explicit `reauth-required` signal instead of silently failing. |
23 | | -- The Edit OpenAPI Source page has a new **Connections** pane showing every user who has signed in and their status. Each source in the sidebar now shows a live connection badge. |
24 | | -- Existing OpenAPI + MCP + google-discovery OAuth rows migrate into Connections automatically on first launch — no user action required. |
| 23 | +- 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. |
| 24 | +- 401 challenges that advertise `resource_metadata=` are recognized as MCP-spec OAuth signals. |
| 25 | +- 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. |
| 26 | +- A live-snapshot regression suite covers 29 real public MCP servers; new probes are checked against those snapshots before shipping. |
| 27 | +- 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. |
25 | 28 |
|
26 | | -### OpenAPI: client-credentials, non-JSON bodies, source refresh |
| 29 | +### TypeScript code runs in dynamic-worker and QuickJS runtimes |
27 | 30 |
|
28 | | -- Full **OAuth2 client-credentials** flow end-to-end. |
29 | | -- **Non-JSON request bodies** dispatch correctly by content type; Executor honors OAS3 `encoding` and multi-content operations, and lets the caller pick which content type to send. |
30 | | -- Relative OAuth2 URLs resolve against the source's `baseUrl`. |
31 | | -- Refresh a source by re-fetching its origin URL from the edit page. |
| 31 | +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. |
32 | 32 |
|
33 | | -### Layered scope isolation |
| 33 | +### OpenAPI source UX |
34 | 34 |
|
35 | | -Multi-tenant deployments get a proper security primitive. Every read and write now passes through a layered `ScopeStack`, with the write scope declared explicitly. Plugins have adopted the API; the UI exposes it via `CreatableSecretPicker`; and WorkOS sources enforce tenant-ownership on every access. Per-scope blob and secret lookups are batched into single `IN` queries, so the extra check doesn't cost a round-trip. |
| 35 | +- Source-add screens reworked: cleaner flow, the freeform combobox lists the URL you typed first, scoped credential UI clarified. |
| 36 | +- OpenAPI import size limit removed — large specs (Stripe, GitHub, etc.) import without truncation. |
| 37 | +- The OpenAPI source edit page lets you change the OAuth2 token / authorization endpoint URLs without removing and re-adding the source. |
| 38 | +- Source favicons render again on the sources list (regression from the source-credential cutover). |
| 39 | +- `listSourceBindings` no longer 500s when called after a source has been removed. |
36 | 40 |
|
37 | | -### Natural CLI for tool discovery and invocation |
| 41 | +### OAuth reliability |
38 | 42 |
|
39 | | -Call tools by path instead of writing TypeScript: |
| 43 | +A pile of small fixes to the OAuth flow, individually unspectacular, collectively meaning fewer mysterious "Sign in" failures: |
40 | 44 |
|
41 | | -```bash |
42 | | -executor call github issues create '{"owner":"octocat","repo":"Hello-World","title":"Hi"}' |
43 | | -executor tools search "send email" |
44 | | -executor tools sources |
45 | | -executor tools describe github.issues.create |
46 | | -``` |
47 | | - |
48 | | -`executor call <path> --help` browses namespaces → resources → methods, with `--match <text> --limit <n>` to narrow huge namespaces. Errors are normalized for agent consumption, and the resume / help UX is cleaner for non-interactive flows. |
49 | | - |
50 | | -### Daemon lifecycle |
51 | | - |
52 | | -```bash |
53 | | -executor daemon run |
54 | | -executor daemon status |
55 | | -executor daemon stop |
56 | | -executor daemon restart |
57 | | -``` |
58 | | - |
59 | | -`executor call`, `executor resume`, and `executor tools …` auto-start a local daemon if one isn't running. The daemon pointer is scope-aware, and if the default port is busy the CLI transparently picks an open one — so two projects can run side-by-side without collisions. |
| 45 | +- 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. |
| 46 | +- Refresh requests use the exact scopes from the original token grant; servers that reject scope upgrades on refresh stop returning `invalid_scope`. |
| 47 | +- `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). |
| 48 | +- The `scope` parameter is omitted entirely when empty, instead of being sent as `scope=`. |
| 49 | +- 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. |
| 50 | +- Token-endpoint failures now include the upstream HTTP status + body summary in the surfaced error. |
| 51 | +- 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. |
60 | 52 |
|
61 | | -`executor daemon run` now backgrounds by default. Pass `--foreground` to keep it attached for log inspection. |
| 53 | +### Source-registration tools require approval |
62 | 54 |
|
63 | | -### OpenTelemetry everywhere |
| 55 | +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. |
64 | 56 |
|
65 | | -Tool dispatch, plugins, storage, schema, and transport are now fully instrumented with OTEL spans, and the runtime is threaded through dispatch so spans actually export in all runtimes. |
| 57 | +### Migration safety for older CLI builds |
66 | 58 |
|
67 | | -## New presets |
| 59 | +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. |
68 | 60 |
|
69 | | -- **Notion** is now a featured MCP preset. |
| 61 | +### SDK additions |
70 | 62 |
|
71 | | -## Performance |
| 63 | +For plugin authors and embedders: |
72 | 64 |
|
73 | | -- `buildExecuteDescription` no longer calls `executor.tools.list`, making tool-description generation measurably faster on large workspaces. |
74 | | -- Per-scope blob and secret lookups now use a single `IN` query instead of N per-scope round-trips. |
| 65 | +- `Usage`, `UsagesForSecretInput`, `UsagesForConnectionInput` — the usages contract. |
| 66 | +- `CredentialBindingKind`, `CredentialBindingValue`, `ConfiguredCredentialBinding`, `ConfiguredCredentialValue`, `ScopedSecretCredentialInput`, `CredentialBindingRef`, `SetCredentialBindingInput`, `RemoveCredentialBindingInput`, `ReplaceCredentialBindingsInput`, `ResolvedCredentialSlot`, `CredentialBindingId` — the new credential bindings surface. |
| 67 | +- `SecretInUseError`, `ConnectionInUseError` — typed errors for blocked deletes. |
| 68 | +- `RefreshSourceInput`, `RemoveSourceInput`, `RemoveSecretInput`, `RemoveToolPolicyInput`, `CredentialBindingRow` — new typed inputs / row types. |
| 69 | +- `ScopedDBAdapter`, `ScopedTypedAdapter` — type exports for scope-aware storage adapters. |
| 70 | +- 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. |
| 71 | +- Schema compile perf: a new lint rule + hoisted `Schema` compilers keep parse-paths fast. |
75 | 72 |
|
76 | 73 | ## Fixes |
77 | 74 |
|
78 | | -- Upgrade: preserve legacy OAuth connection backfills after the `connection.kind` column is removed. |
79 | | -- OpenAPI: refreshing or editing sources with legacy inline secret/OAuth config now materializes the new source binding rows instead of dropping credentials. |
80 | | -- Keychain: skip provider registration when the OS backend is unreachable (no more startup failure when running headless on Linux without a keyring). |
81 | | -- Local database: fail early with guidance when an older Executor build opens a data directory migrated by a newer build, instead of surfacing a low-level SQLite schema error. |
82 | | -- Local server: return 404 for missing static assets instead of serving HTML. |
83 | | -- Tests: Windows compatibility across the suite. |
| 75 | +- `executeWithPause` now settles correctly when the running fiber fails — previously a fiber failure could leave the execution hanging instead of surfacing the error. (#523) |
| 76 | +- `isDevMode` correctly identifies the compiled bun binary, so installed CLI builds no longer misdetect themselves as running from source. Thanks @grfwings (#699) |
| 77 | +- Drizzle migration handling parses migration metadata with a typed schema and reports outdated-client failures cleanly. Thanks @grfwings (#741) |
| 78 | +- Frontend errors and API-client decode failures are now reported through the existing error-reporting path instead of being swallowed silently. |
| 79 | +- Source forms keep local error messages on screen instead of clearing them on the next render. |
| 80 | +- "Remove in-use source" surfaces a toast instead of a silent failure. (#530) |
84 | 81 |
|
85 | 82 | ## Breaking changes |
86 | 83 |
|
87 | | -### `executor call` no longer accepts inline code |
| 84 | +### SDK: `makeTestConfig` import path moved |
88 | 85 |
|
89 | | -The old TypeScript-as-argument forms are gone: |
| 86 | +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: |
90 | 87 |
|
91 | | -```bash |
92 | | -executor call '<code>' |
93 | | -executor call --file script.ts |
94 | | -executor call --stdin |
| 88 | +```ts |
| 89 | +// still works |
| 90 | +import { makeTestConfig } from "@executor-js/core/sdk"; |
95 | 91 | ``` |
96 | 92 |
|
97 | | -Migrate to explicit tool paths: |
98 | | - |
99 | | -```bash |
100 | | -# before |
101 | | -executor call 'return await tools.github.issues.list({ owner, repo })' |
102 | | -# after |
103 | | -executor call github issues list '{"owner":"octocat","repo":"Hello-World"}' |
104 | | -``` |
105 | | - |
106 | | -`tools.discover(...)` becomes `executor tools search "<query>"`. |
107 | | - |
108 | | -### `sources.add` CLI form simplified |
109 | | - |
110 | | -Use the dedicated tool: |
111 | | - |
112 | | -```bash |
113 | | -executor call openapi addSource '{ |
114 | | - "spec": "https://petstore3.swagger.io/api/v3/openapi.json", |
115 | | - "namespace": "petstore", |
116 | | - "baseUrl": "https://petstore3.swagger.io/api/v3" |
117 | | -}' |
118 | | -``` |
119 | | - |
120 | | -Pass `baseUrl` when the OpenAPI document has relative `servers` entries. |
121 | | - |
122 | | -### SDK: layered scope |
| 93 | +### SDK: per-plugin credential shapes replaced by credential bindings |
123 | 94 |
|
124 | | -Every SDK write now takes an explicit scope. If you have plugins or host code calling the SDK directly, they'll need to adopt the new layered-scope API (see the in-tree plugins for reference — they've all been migrated). This does not affect users of the CLI or web UI. |
| 95 | +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. |
0 commit comments