Skip to content

fix: keep executor.jsonc in sync with source add/remove#408

Merged
RhysSullivan merged 1 commit into
RhysSullivan:mainfrom
RyanNg1403:fix/sync-config-on-engine-source-remove
May 11, 2026
Merged

fix: keep executor.jsonc in sync with source add/remove#408
RhysSullivan merged 1 commit into
RhysSullivan:mainfrom
RyanNg1403:fix/sync-config-on-engine-source-remove

Conversation

@RyanNg1403
Copy link
Copy Markdown
Contributor

Summary

Two related bugs caused executor.jsonc and the runtime DB to drift out of sync, so sources resurrected after a UI delete and OAuth auth blocks vanished after a restart. Both are reproducible against executor@1.4.9.

  • Engine-level removeSource hook in the openapi, mcp, and graphql plugins now mirrors the SDK-level removeSpec / removeSource and writes back to configFile.
  • apps/local config-sync now translates McpAuthConfigMcpConnectionAuth and forwards it to executor.mcp.addSource, so remote MCP auth survives boot.

Why

Bug 1 — engine-level remove never updates executor.jsonc

The SDK methods (openapi.removeSpec, mcp.removeSource, graphql.removeSource) correctly call ctx.storage.removeSource(...) and configFile.removeSource(...). The plugin lifecycle hook also named removeSource — used by the engine's executor.sources.remove and therefore by the HTTP sources.remove handler and the web UI delete button — only deleted plugin storage rows. The DB was cleaned, but the file wasn't.

On the next boot, apps/local boot-sync read executor.jsonc, saw the still-present source entry, and re-upserted it into the DB. From the user's perspective, deleted sources resurrected after every restart.

Bug 2 — boot-sync silently strips MCP auth

apps/local/src/server/config-sync.ts rebuilt the executor.mcp.addSource(...) call for remote MCP sources without passing source.auth. addSource then wrote back to executor.jsonc via configFile.upsertSource(...) with auth: undefined — so { kind: "oauth2", connectionId: ... } blocks silently disappeared from the file on the very first restart. The next restart saw a source with no auth, hit a 401 on connect, and registered zero tools.

The OAuth connection row and keychain tokens themselves remained intact in the DB; the file just lost the pointer.

Validation

  • bunx --bun vitest run in packages/plugins/openapi — 64/64 (incl. new regression test asserting executor.sources.remove triggers configFile.removeSource)
  • bunx --bun vitest run in packages/plugins/mcp — 30/30
  • bunx --bun vitest run in packages/plugins/graphql — 14/14
  • bunx --bun vitest run in packages/core/sdk — 90/90
  • bunx --bun vitest run in apps/local — 23/23 (incl. new config-sync.test.ts covering all McpAuthConfig variants)
  • bun run typecheck clean across apps/local, packages/plugins/{openapi,mcp,graphql}
  • End-to-end repro on a local executor web:
    • Bug 1: added the GitHub OpenAPI spec via UI, deleted via UI, restarted — executor.jsonc correctly omits the source and the DB stays clean (was reappearing pre-fix)
    • Bug 2: configured Linear MCP via UI OAuth, restarted — auth: { kind: "oauth2", connectionId: ... } block is preserved in executor.jsonc and 33 Linear tools load (was silently 401'ing pre-fix)

Two related bugs caused executor.jsonc and the runtime DB to drift out of
sync, so sources resurrected after a UI delete and OAuth `auth` blocks
vanished after a restart.

- Engine-level `removeSource` hook in the openapi, mcp, and graphql plugins
  now mirrors the SDK-level `removeSpec` / `removeSource` and writes back
  to `configFile` after the storage transaction.
- `apps/local` config-sync now translates `McpAuthConfig` →
  `McpConnectionAuthInput` and forwards it to `executor.mcp.addSource`, so
  remote MCP `auth` survives boot.
@RhysSullivan RhysSullivan force-pushed the fix/sync-config-on-engine-source-remove branch from 437a06b to 6ba30f0 Compare May 11, 2026 15:57
@RhysSullivan RhysSullivan merged commit 061dd16 into RhysSullivan:main May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants