cloudflare self-host: browser approval + a Cloudflare e2e target - #1016
Conversation
a595fe9 to
69e930c
Compare
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-cloud | d4f3e6f | Jun 14 2026, 06:10 AM |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-marketing | d4f3e6f | Commit Preview URL Branch Preview URL |
Jun 14 2026, 06:09 AM |
Cloudflare previewTorn down — the PR is closed. |
Greptile SummaryThis PR wires browser-approval support into the Cloudflare self-host worker and adds a new
Confidence Score: 5/5Safe to merge — the new approval handler and e2e target are additive, self-contained, and mirror well-tested existing patterns in the codebase. The base-class resolveAndStoreSessionMeta correctly merges token.webOrigin after the host's resolveSessionMeta returns, so the approval URL origin is populated on cold restores even though the host subclass doesn't forward it. The globalSetup for the cloudflare project is auto-generated by the project() helper, so the wrangler boot is wired without any extra configuration. The only pre-existing concern (unhandled throw from idFromString) was already flagged in a prior review thread; no new unresolved defects were introduced here. apps/host-cloudflare/src/mcp/index.ts — the approval handler's async body has no top-level try/catch, which was called out in a previous review comment; the decodeURIComponent calls before the stubFor invocation share the same unguarded surface. Important Files Changed
Sequence DiagramsequenceDiagram
participant Browser as Console Browser
participant Worker as Cloudflare Worker
participant Access as Access Verifier
participant DO as McpSessionDO
Note over Worker: /api/mcp-sessions/* mounted via HttpRouter
Browser->>Worker: "GET /api/mcp-sessions/{sessionId}/executions/{execId}"
Worker->>Access: verify(request)
Access-->>Worker: "principal | null"
alt not authenticated
Worker-->>Browser: 401 Unauthorized
end
Worker->>DO: idFromString(sessionId) stub
Worker->>DO: getPausedExecutionForApproval(execId, owner)
DO-->>Worker: status text structured
Worker-->>Browser: 200 text structured
Browser->>Worker: "POST /api/mcp-sessions/{sessionId}/executions/{execId}/resume"
Worker->>Access: verify(request)
Access-->>Worker: principal
Worker->>Worker: decodeResumeResponse(body)
Worker->>DO: resumeExecutionForApproval(execId, owner, response)
DO->>DO: store response, signal waiter Deferred
DO-->>Worker: status ok executionStatus text structured
Worker-->>Browser: 200 status text structured isError
Reviews (4): Last reviewed commit: "cloudflare self-host: browser approval +..." | Re-trigger Greptile |
@executor-js/cli
@executor-js/config
@executor-js/execution
@executor-js/sdk
@executor-js/codemode-core
@executor-js/runtime-quickjs
@executor-js/plugin-file-secrets
@executor-js/plugin-graphql
@executor-js/plugin-keychain
@executor-js/plugin-mcp
@executor-js/plugin-onepassword
@executor-js/plugin-openapi
executor
commit: |
c34b4f5 to
8156239
Compare
69e930c to
14eb2c5
Compare
8156239 to
9763604
Compare
14eb2c5 to
11c1a17
Compare
9763604 to
8ff9ad6
Compare
11c1a17 to
e3c90bb
Compare
The host-cloudflare Durable Object base already owned the approval store and the paused/resume RPCs, but its buildMcpServer ignored the session's elicitation mode (model-mode only) and the worker served no approval endpoints — so a gated MCP action could never be approved in the browser. - host-cloudflare: buildMcpServer wires browser elicitation mode + approvalUrl (origin from the create request, captured by the DO base) + the base's browserApprovalStore, mirroring cloud. The worker mounts an Access-gated /api/mcp-sessions/* handler that routes the paused (GET) + resume (POST) calls to the owning session's DO RPCs. - e2e: a new 'cloudflare' target — the real worker on workerd via wrangler dev (Miniflare) with local D1 + R2 and dev-auth, the console SPA built and served as static assets. The cross-target browser-approval scenario (approve + decline) now runs green here too, driving the rendered resume page against the worker. Browser approval is now covered end-to-end on all three deployment shapes: cloud, self-host, and Cloudflare self-host.
8ff9ad6 to
d4f3e6f
Compare
|
Want your agent to iterate on Greptile's feedback? Try greploops. |
What
The Cloudflare self-host Durable Object base already owned the approval store and the paused/resume RPCs, but its
buildMcpServerignored the session's elicitation mode (model-mode only) and the worker served no approval endpoints — so a gated MCP action could never be approved in the browser.buildMcpServerwires browser elicitation mode + approval URL (origin from the create request, captured by the DO base) + the base's approval store, mirroring the hosted app. The worker mounts a gated/api/mcp-sessions/*handler that routes the paused (GET) + resume (POST) calls to the owning session's Durable Object RPCs.cloudflaretarget — the real worker on workerd viawrangler dev(Miniflare) with a local D1 + R2 and dev-auth, the console SPA built and served as static assets. The cross-target browser-approval scenario (approve + decline) now runs green here too, driving the rendered resume page against the worker.Browser approval is now covered end-to-end on all three deployment shapes.
Notes
cloudflaree2e project is scoped to the browser-approval scenario for now — the rest of the cross-target suite is not yet validated against the worker.Testing
typecheck/format:check/lintclean.wrangler devworker integration test.Third of a three-PR stack.
Stack