Skip to content

Keep workspace-write access on cross-session MCP resume - #2099

Merged
RhysSullivan merged 1 commit into
mainfrom
fix/cross-session-resume-org-write
Sep 24, 2026
Merged

RhysSullivan merged 1 commit into
mainfrom
fix/cross-session-resume-org-write

Conversation

@RhysSullivan

Copy link
Copy Markdown
Collaborator

When a model calls resume from a different MCP session than the one that started the execution (for example after an mcp-remote reconnect), the requester's session forwards the resume to the owning session via resumeExecutionForModel. That RPC ran engine.resume with no CurrentOrgWriteAccess bound, so the engine rebound the paused execution to the fail-closed "denied" default. An admin's pending addServer / addSpec / updateSpec then failed with org_write_denied.

  • The forwarded identity (McpModelResumeCaller) now carries the requester's orgWriteAccess, read from its own request context.
  • The owning session binds that value around engine.resume. A caller from the previous deploy that omits it is treated as denied.

Prod telemetry over the last 14 days: every always-gated admin write resumed through the cross-session path was denied. Same-session resumes were almost never denied.

Tests: new cases in agent-session-model-resume.test.ts cover allowed, denied, and a legacy caller. The allowed case fails without the fix. Typecheck is clean for @executor-js/cloudflare, apps/cloud, and apps/host-cloudflare.

@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Cloudflare preview

Torn down — the PR is closed.

@pkg-pr-new

pkg-pr-new Bot commented Sep 24, 2026

Copy link
Copy Markdown

Open in StackBlitz

@executor-js/cli

npm i https://pkg.pr.new/@executor-js/cli@2099

@executor-js/config

npm i https://pkg.pr.new/@executor-js/config@2099

@executor-js/execution

npm i https://pkg.pr.new/@executor-js/execution@2099

@executor-js/sdk

npm i https://pkg.pr.new/@executor-js/sdk@2099

@executor-js/codemode-core

npm i https://pkg.pr.new/@executor-js/codemode-core@2099

@executor-js/runtime-quickjs

npm i https://pkg.pr.new/@executor-js/runtime-quickjs@2099

@executor-js/plugin-file-secrets

npm i https://pkg.pr.new/@executor-js/plugin-file-secrets@2099

@executor-js/plugin-graphql

npm i https://pkg.pr.new/@executor-js/plugin-graphql@2099

@executor-js/plugin-keychain

npm i https://pkg.pr.new/@executor-js/plugin-keychain@2099

@executor-js/plugin-mcp

npm i https://pkg.pr.new/@executor-js/plugin-mcp@2099

@executor-js/plugin-onepassword

npm i https://pkg.pr.new/@executor-js/plugin-onepassword@2099

@executor-js/plugin-openapi

npm i https://pkg.pr.new/@executor-js/plugin-openapi@2099

executor

npm i https://pkg.pr.new/executor@2099

commit: 273b78d

@RhysSullivan
RhysSullivan marked this pull request as ready for review September 24, 2026 00:14
@RhysSullivan
RhysSullivan merged commit 9e143d9 into main Sep 24, 2026
79 of 80 checks passed
mhodgson pushed a commit to airbooksio/executor that referenced this pull request Sep 25, 2026
* Self-host Geist fonts (UsefulSoftwareCo#1963)

* Self-host Geist fonts instead of loading them from Google Fonts

* Move console font test to root tests so it typechecks

* Scope tool preview compile to referenced definitions (UsefulSoftwareCo#1977)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Report executions lost to a session reset (UsefulSoftwareCo#1978)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Point agent setup CTA to the setup docs (UsefulSoftwareCo#1944)

* docs(sdk): invoke tools by address, not id (UsefulSoftwareCo#1916)

* Document connections.list result shape in skills.ts (UsefulSoftwareCo#1808)

* Fix long connection names overflowing the removal dialog (UsefulSoftwareCo#1975)

* Fit the empty Toolkits grid to the viewport (UsefulSoftwareCo#1897)

* fix(openapi): preserve vendor +json Content-Type on object bodies (UsefulSoftwareCo#1937)

* fix(oauth): retry a refresh grant without scope when the AS refuses it (UsefulSoftwareCo#1982)

Railway answers every scope-bearing refresh with `invalid_scope: refresh
token missing requested scope` when its stored grant is narrower than the
authorization it echoed back, so a connection whose refresh token was
still live failed every call as `oauth_refresh_failed` and only a hand
re-authorization recovered it.

RFC 6749 §6 defines omitting `scope` as "the scope originally granted",
so retry the grant once without it. Only `invalid_scope` qualifies:
`invalid_grant` means the token is dead, and retrying that spends a
rotating refresh token to learn nothing.

* Honor OAuth resource metadata challenges (UsefulSoftwareCo#1981)

* Cascade integration removal to every member and stop serving orphaned rows (UsefulSoftwareCo#1991)

* Cascade integration removal to every member and stop serving orphaned rows

* Register the MCP server before starting OAuth in the local app test

* fix(openapi): fetch analyticsdata Discovery from the service host (UsefulSoftwareCo#1955)

* fix(openapi): fetch analyticsdata Discovery from the service host

The central Discovery directory does not list the GA4 Data API, so
https://www.googleapis.com/discovery/v1/apis/analyticsdata/v1beta/rest
answers 404 and importing the source fails. Route analyticsdata to its
own host the way forms, keep and photospicker already are.

* Test queue timeout with a controlled clock

* Verify Analytics Data discovery import end to end

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Advertise refresh-token grant in OAuth client metadata (UsefulSoftwareCo#1974)

* Advertise refresh-token grant in OAuth client metadata

* Test OAuth metadata through connection and tool use

* Test queue timeout with a controlled clock

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix(mcp): shut down scoped executor on session eviction (UsefulSoftwareCo#1917) (UsefulSoftwareCo#1971)

* fix(mcp): shut down scoped executor on session eviction (UsefulSoftwareCo#1917)

Retain the scoped Executor created for each MCP session and shut it down when an in-memory MCP session is evicted, closed, or fails eager initialization. This ensures child tool subprocesses and connection pools owned by the session are properly cleaned up.

* test(cloud): fix flaky timer precision assertion in session build semaphore test

* Verify MCP session disposal closes upstream resources

* Test queue timeout with a controlled clock

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix(mcp): bound discovery connection teardown (UsefulSoftwareCo#1878)

* fix(mcp): bound discovery connection teardown

Discovery cleanup runs in an interruption-masked finalizer. Bound an unresponsive transport close so a completed tool listing cannot strand health checks or other callers indefinitely.

* test(mcp): match current discovery client contract

* test(mcp): avoid wall-clock teardown assertion

* Exercise discovery teardown with real MCP connections

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix(react): honor prefers-reduced-motion in the shared stylesheet (UsefulSoftwareCo#1892)

* fix(react): honor prefers-reduced-motion in the shared stylesheet

* Test queue timeout with a controlled clock

* Cover reduced motion changes in the browser

---------

Co-authored-by: pt-act <211776491+pt-act@users.noreply.github.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Keep artifact deletion optimistic across navigation (UsefulSoftwareCo#1901)

* Keep artifact deletion optimistic across navigation

* Restore gallery-card delete coverage and bound the Saved artifacts wait in the artifacts e2e

* Test queue timeout with a controlled clock

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Surface unreachable OpenAPI upstreams as network errors (UsefulSoftwareCo#1960)

* Surface unreachable upstreams as network error

* Test queue timeout with a controlled clock

* Classify transport failures without hiding invocation defects

* Name the integration and origin in the unreachable-upstream message

Executor sends the request, not the user's browser, so "check your
network" pointed at the wrong place. Name the integration and the origin
that could not be reached and tell the user to verify the base URL and
that the service is online. Only the host is lifted off the transport
failure; the path, query, and headers stay out of the message.

* Record the cause of unreachable upstreams without the request

Classifying transport failures as a typed tool result took them off the
hosts' defect path, which was the only place the cause was logged. Lift
the errno-style code (ECONNREFUSED, ENOTFOUND, UND_ERR_SOCKET, ...) off
the fetch cause chain, log a warning and annotate the span with the
integration, host, and code, and return the same sanitized pair in the
tool result details. The raw TransportError stays out of details on
purpose: it carries the whole request, including resolved auth headers.

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix(mcp): report completed connected tool (UsefulSoftwareCo#1964)

* fix(mcp): report completed connected tool

* Test queue timeout with a controlled clock

* Verify connected tool provenance over MCP

* Exclude upstream tool failures from completion metadata

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Return tool annotations from describe.tool (UsefulSoftwareCo#1980)

* Return tool annotations from describe.tool

`ToolSchemaView` carried everything about a tool except the annotations a
plugin declares on it, so code written inside `execute` could not tell an
approval-gated tool from a plain one except by reading its prose description.
The data was already persisted on the tool row and already used by the
executor's own approval copy.

`tools.schema` now projects the three fields declared in `ToolAnnotations`
(`requiresApproval`, `approvalDescription`, `mayElicit`), and `describe.tool`
passes them through. The fields are picked explicitly rather than spread,
because plugins keep private bookkeeping alongside the contract: the mcp
plugin stores its upstream tool name and `_meta` map in the same column, and
none of that should reach a caller.

The key is omitted when a tool declares no annotations, so the describe
payload does not grow for the tools that have nothing to say.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Test queue timeout with a controlled clock

* Verify annotation projections and expose resume failure context

* Model private annotation metadata through the test adapter

* Use the static tool address for schema discovery

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix(oauth): request offline_access for Vercel MCP (UsefulSoftwareCo#1951)

* fix(oauth): request offline_access for Vercel MCP

* Test queue timeout with a controlled clock

* Verify Vercel lifecycle scopes through an OAuth connection

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix(cloud): require CSRF state in the WorkOS login callback (UsefulSoftwareCo#1886)

* fix(cloud): require CSRF state in the WorkOS login callback

* Test queue timeout with a controlled clock

* Exercise browser binding and replay protection for login state

* Capture provider redirect before testing callback state

* Wait for key revocation before checking authentication

---------

Co-authored-by: pt-act <211776491+pt-act@users.noreply.github.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Fix HubSpot optional scopes for workspace OAuth (UsefulSoftwareCo#1898)

* Fix HubSpot optional scopes for workspace OAuth

* chore: rerun flaky cloud E2E

* Honor integration-declared HubSpot optional scopes

* Test queue timeout with a controlled clock

* Verify optional OAuth scopes through consent and tool execution

---------

Co-authored-by: Lloyd Vickery <lvickery@Lloyds-MacBook-Pro.local>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Support POST health checks for HTTP RPC APIs (UsefulSoftwareCo#1952)

* Support POST health checks for HTTP RPC APIs

* Preserve existing health-check method behavior

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix(e2e): honor the 503 restart envelope in the cap-eviction helper (UsefulSoftwareCo#1895)

* trim to the openSession restart-retry backstop

Per review: the concurrency half is superseded by UsefulSoftwareCo#1907 (already on
main, stricter). Rebased onto current main and kept only the retry
loop on the documented 503 restart envelope.

* Match the exact MCP restart envelope before retrying

* Test queue timeout with a controlled clock

---------

Co-authored-by: pt-act <pt-act@users.noreply.github.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix: use public origin for browser approval URLs (UsefulSoftwareCo#1967)

* fix: use public origin for approval URLs

CLI browser approval links ignored EXECUTOR_WEB_BASE_URL and inherited the
internal HTTP listener scheme, so TLS-proxied deployments got unreachable
http:// URLs.

* fix: skip port-0 web base URL for approval links

CLI --port 0 installs EXECUTOR_WEB_BASE_URL as http://127.0.0.1:0 before
the OS assigns a listen port. Chrome rejects that origin as ERR_UNSAFE_PORT,
so approval URLs fall back to the request origin in that case.

* Exercise browser approvals through a TLS proxy

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix(oauth): complete browser callbacks before tool sync (UsefulSoftwareCo#1880)

* fix(oauth): complete browser callbacks before tool sync

Persist the refreshed OAuth grant and connection before returning the popup callback, then keep remote catalog synchronization alive through the host lifecycle. Preserve synchronous completion for programmatic callers and cover slow MCP discovery with unit and browser E2E tests.

* Verify OAuth callbacks with blocked and failing catalogs

* Release catalog gate before the separate health probe

* Verify OAuth discovery recovery through explicit refresh

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Fix hyphenated tool paths in artifacts (UsefulSoftwareCo#1884)

* test: cover hyphenated paths in browser

* refactor: narrow hyphenated artifact path fix

* Test queue timeout with a controlled clock

* Handle single-quoted artifact integration paths

* Use the catalog path for the artifact schema query

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Bridge generated-UI target=_blank links through the host openLink capability (UsefulSoftwareCo#1915)

* Bridge generated-UI `target=_blank` links through the host openLink capability

The sandbox iframe omits allow-popups, so artifact links silently failed. The
trusted renderer now relays a user click across the frame boundary, guarded by
a per-render closure nonce, and the host opens only http(s) URLs.

* Test queue timeout with a controlled clock

* Prevent generated artifacts from replacing link authorization

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix(mcp): pause active timeout during elicitation (UsefulSoftwareCo#1956)

* fix(mcp): pause active timeout during elicitation

* Test approval waits beyond the MCP active-work deadline

* Test queue timeout with a controlled clock

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Add search and invoke MCP mode (UsefulSoftwareCo#1942)

* Add search and invoke MCP mode

* Preserve full annotations in MCP scenario decoding

* Return artifact source from show-artifact (UsefulSoftwareCo#1943)

* Return artifact source from show-artifact

* Preserve artifact deletion regression coverage

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Carry an approval's persistence choice through elicitation (UsefulSoftwareCo#1976)

* fix(mcp): pause active timeout during elicitation

* Carry an approval's persistence choice through elicitation

Codex Computer Use offers `persist: ["session", "always"]` in the terms of
its "Allow Computer Use to use X?" prompt and remembers the app only when
the answer names one. Executor lost the offer on the way in — the terms
projection kept strings only — and the choice on the way out, because every
adapter rebuilt the reply from `action` and `content`. So each accept was a
one-time approval and the same app prompted on every call.

- `ElicitationResponse.meta.persist` carries the choice; the vocabulary is
  closed so no host can grant more than the prompt offered.
- `approvalTerms` keeps string lists, so the offered scopes reach the host.
- The MCP plugin, the app-server bridge, and the MCP host (native mode)
  pass `_meta` through in both directions.
- The model-mode `resume` tool takes `persist`; the pause output names the
  offered scopes and says a bare accept is one-time.
- The HTTP resume API takes `persist`, and the browser approval page offers
  the scopes in a select. Nothing is chosen automatically.

Fixes UsefulSoftwareCo#1962

* Preserve approval lifetime through browser and cloud resume paths

* Test approval waits beyond the MCP active-work deadline

* Test queue timeout with a controlled clock

* Test queue timeout with a controlled clock

---------

Co-authored-by: mikemikimike <13286568797@163.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* fix(host-cloudflare): route toolkit MCP endpoints (UsefulSoftwareCo#1926)

* test(host-cloudflare): classify toolkit MCP paths

* fix(cloudflare): bind MCP sessions to their resource

* fix(host-cloudflare): serve toolkit MCP routes

* style: format toolkit route changes

* fix(mcp): pause active timeout during elicitation

* Carry an approval's persistence choice through elicitation

Codex Computer Use offers `persist: ["session", "always"]` in the terms of
its "Allow Computer Use to use X?" prompt and remembers the app only when
the answer names one. Executor lost the offer on the way in — the terms
projection kept strings only — and the choice on the way out, because every
adapter rebuilt the reply from `action` and `content`. So each accept was a
one-time approval and the same app prompted on every call.

- `ElicitationResponse.meta.persist` carries the choice; the vocabulary is
  closed so no host can grant more than the prompt offered.
- `approvalTerms` keeps string lists, so the offered scopes reach the host.
- The MCP plugin, the app-server bridge, and the MCP host (native mode)
  pass `_meta` through in both directions.
- The model-mode `resume` tool takes `persist`; the pause output names the
  offered scopes and says a bare accept is one-time.
- The HTTP resume API takes `persist`, and the browser approval page offers
  the scopes in a select. Nothing is chosen automatically.

Fixes UsefulSoftwareCo#1962

* Preserve approval lifetime through browser and cloud resume paths

* Test approval waits beyond the MCP active-work deadline

* Test queue timeout with a controlled clock

* Test queue timeout with a controlled clock

* Verify toolkit session isolation across resources and methods

---------

Co-authored-by: Don Pansacola <1178461+donmasakayan@users.noreply.github.com>
Co-authored-by: mikemikimike <13286568797@163.com>
Co-authored-by: Dara Adedeji <shawnadedeji@gmail.com>
Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>

* Add account discovery and guides to search and invoke (UsefulSoftwareCo#1997)

* Billing: update the payment card (UsefulSoftwareCo#1992)

* Add payment method update to billing page

* Change an existing card through the billing portal

* Recover the card button when the payment form fails to open

* Bump @executor-js/emulate to 0.14.2

* Handle payment form failures with Effect

* Hide built-in Slack OAuth option (UsefulSoftwareCo#1998)

* fix(selfhost): restrict admin area to admins (UsefulSoftwareCo#1987)

* test(sdk): concurrent policy creates get distinct positions (UsefulSoftwareCo#1893)

Regression guard for the tool-policy position race: two equally
specific policies created concurrently must land distinct positions.
Upstream UsefulSoftwareCo#1919 wrapped policiesCreate/policiesUpdate in a transaction;
this pins that guarantee with a discriminating it.live test.

Verified load-bearing both directions: passes with the transaction
wrap (upstream/main), fails with the pre-UsefulSoftwareCo#1919 unwrapped executor
(duplicate positions: Set size 1 vs 2).

Co-authored-by: pt-act <211776491+pt-act@users.noreply.github.com>

* Keep artifacts available in search and invoke mode (UsefulSoftwareCo#1999)

* Harden OAuth sessions and patch vulnerable dependencies (UsefulSoftwareCo#2000)

* Update YAML, URI, and serialization dependencies

* Harden sessions, credential traces, and runtime dependencies

* Require HTTPS for cloud outbound requests

* Normalize dependency resolution for frozen installs

* Prebundle browser telemetry before cloud development starts

* Keep seat reconciliation alive after the response (UsefulSoftwareCo#2001)

* Keep seat reconciliation alive after the response

* Await callback background work in the test fixture

* Use Effect test helpers for background work fixtures

* Normalize login return destinations (UsefulSoftwareCo#2002)

* Normalize login return destinations

* Assert parsed redirect state unconditionally

* Use public Option helpers in auth checks

* Stop capping WorkOS access token age at 24 hours (UsefulSoftwareCo#2009)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Surface MCP JSON-RPC refusals as typed tool failures (UsefulSoftwareCo#2012)

An MCP server that rejects tools/call with a JSON-RPC error (Stripe's
-32602 invalid params, for one) fell through the dispatch catch as an
opaque "Internal tool error [id]", so the model read a bad argument as
an integration outage. Carry the server's code and message on
McpInvocationError and answer with an mcp_tool_error result instead.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Hide integration edit/delete controls for non-admin members (UsefulSoftwareCo#2013)

Co-authored-by: Rhys Sullivan <rhys@rhyssullivan.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* Name the SDK rejection in MCP invocation defects (UsefulSoftwareCo#2014)

* Name the SDK rejection in MCP invocation defects

An MCP tools/call rejection that is neither HTTP auth nor a JSON-RPC
error reaches the dispatch defect log as "MCP tool call failed for
<tool>" and nothing else, so an opaque correlation id cannot be traced
to a cause. Carry the SDK error class and stable code on
McpInvocationError and in its message. Structural only; the SDK message
is never copied, since a transport message can embed an upstream body.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Include the HTTP status in the MCP invocation defect message

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Surface 4xx JSON refusals from MCP tools/call as typed failures (UsefulSoftwareCo#2016)

Stripe's OAuth MCP server validates the account context at the HTTP
layer: a call without stripe_context gets a 422 whose JSON body names
the missing field. That reached the sandbox as an opaque
"Internal tool error [id]" because a non-auth HTTP status was treated
as a transport defect. Read a string message out of a 4xx JSON body
(structurally; never the raw text) and answer with mcp_tool_error so
the caller can fix the arguments. 401/403 keep their auth
classification; 5xx and bodyless 4xx stay opaque.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Marketing site redesign (UsefulSoftwareCo#2011)

* marketing: homepage variants for mission, proof, captions, and agent markdown

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: sidebar rail layout variants

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: default to paper rail, fallback variant switcher

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: document-style homepage body

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: centre the document column beside the rail

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: centre rail and content in one fixed-width frame

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: no graph-paper texture in rail mode

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: hero variants for cloud, local, and self-hosted paths; gridline rail default

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: beam figure sits under the hero

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: settle on gridline rail and document body

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: five more hero variants

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: byline and signature linking to Rhys on X

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: rail CTA stack with YC badge, tabs hero default

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: remove variant picker, keep tabs hero; docker-only self-host copy

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: desktop app, not native app

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: drop MIT call-outs

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: contact block in the sidebar, byline out of the hero

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: rail spy pins clicked section; contact rows are single links

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: rail spy tracks the section under a fixed reading line

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: slack connect wording; remove cloudflare self-host docs

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: what people say section from X posts

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: testimonials lead with strongest posts, drift starts on first view

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: slower testimonial drift

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: testimonial intro line

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: add yours card in testimonials

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: consistent rail buttons; safety, run-it, and about copy from user feedback

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: restore full-bleed YC badge in rail

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: steps headline with logo reveals, beam label backing, plainer copy

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: platform-specific download buttons; drop self-referencing links

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: tab panes share one cell so switching never shifts layout

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: subhead under the steps

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: tab description holds two lines so buttons never move

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: dedicated pricing page

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: harness logos in the agent reveal; trim pricing page

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: run-it section as a four-cell grid

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: buttons inside sections keep button colours

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: allow markdown routes at the edge; lint and copy fixes

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Marketing: step spacing fix and mobile layout (UsefulSoftwareCo#2017)

* marketing: keep spaces around hover words in production; mobile layout

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: centre the column when the rail is a top bar

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: centre the intro below the rail breakpoint

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Marketing: faster testimonial drift, Hermes logo (UsefulSoftwareCo#2018)

* marketing: faster testimonial drift

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: hermes agent mark in the agent reveal

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: blog on the rail layout; one shared shell for home, pricing, and blog (UsefulSoftwareCo#2019)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Marketing: port X articles to the blog, add a testimonial (UsefulSoftwareCo#2020)

* marketing: port three X articles to the blog

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: restore the three tweet links in the concepts post

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: add a testimonial

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* marketing: keep duplicated and hidden text out of find-in-page (UsefulSoftwareCo#2021)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Restart hosted invitation logins with fresh state (UsefulSoftwareCo#2023)

* Keep request resources alive for background OAuth sync (UsefulSoftwareCo#2028)

* Add MemberDirectory seam and cloud membership mirror tables (UsefulSoftwareCo#2003)

* Feed the cloud membership mirror from login and member writes (UsefulSoftwareCo#2004)

* Reconcile the membership mirror from WorkOS events (UsefulSoftwareCo#2024)

* Read members from the directory and add email search (UsefulSoftwareCo#2025)

* Authorize org membership from the local mirror (UsefulSoftwareCo#2026)

* Authorize from the mirror unconditionally; alert on a stale reconciler (UsefulSoftwareCo#2031)

* Add Hegar homepage testimonial (UsefulSoftwareCo#2038)

* marketing: one door on the homepage hero (UsefulSoftwareCo#2040)

Drop the Cloud / Desktop / Self-hosted tabs from the hero. One Start on
Cloud button, a ghost Copy setup prompt beside it, and a fine-print link to
the Run it section for the local options.

The rail stops selling: the Get started, star, and YC boxes become two quiet
text lines. Extract the intro steps and the copy button into components.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* fix(oauth): require exact explicit DCR redirect match (UsefulSoftwareCo#2032)

Treat a caller-supplied DCR redirectUri as authoritative: only a client registered with that exact callback is reused. A legacy client with no recorded redirect is kept for existing connections while a new uniquely named client is registered for the explicit callback. Callers that rely on the configured default redirect keep the previous reuse behavior.

* Fix pending changesets for a patch release (UsefulSoftwareCo#2042)

* Drop ignored host-mcp package from two changesets

* Release MCP passthrough mode as a patch

* Version Packages (UsefulSoftwareCo#2043)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Add a self-host opt-out for Better Auth rate limiting (UsefulSoftwareCo#2044)

* Fix macOS auto-update: preserve framework symlinks in the update zip (UsefulSoftwareCo#2049)

* Version Packages (UsefulSoftwareCo#2048)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Show disabled integration actions for members (UsefulSoftwareCo#2051)

* Align integration creation UI with admin permissions

* Show disabled integration actions for members

* fix(oauth): request all advertised scopes, keep sync verdicts visible (UsefulSoftwareCo#2056)

Scope discovery capped the request at 100 scopes. A resource that
advertises more (PostHog lists 150) got a token missing the scopes its
MCP server needs, so every new connection synced zero tools. Bound the
request by scope-string length (8 KiB) instead.

A credential-only health check then reported healthy over the
sync-stamped rejection, hiding the failure. Sync-supplied verdicts now
carry the tool_sync_failed reason and are served until a sync succeeds.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Protect deployment database connections (UsefulSoftwareCo#2057)

* Scope toolkit tool reads and stop gating reads on TTL-expired catalogs (UsefulSoftwareCo#2061)

* Scope tool policies to the account they are set under (UsefulSoftwareCo#2062)

* Accept Slack bot and user OAuth grants (UsefulSoftwareCo#2050)

* Accept Slack bot and user OAuth grants

* Preserve standard bearer response metadata

* Document the 20-connection application pool (UsefulSoftwareCo#2064)

* Prefer OAuth when a matching client is available (UsefulSoftwareCo#2066)

* Prefer OAuth when adding connections

* Verify authentication method selection stays usable

* Check client availability before preferring OAuth

* Pre-warm the app plane on requests that do not need it (UsefulSoftwareCo#2072)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Probe connection health through a per-connection atom (UsefulSoftwareCo#2071)

* e2e: reproduce health-probe churn on the integrations list

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Probe connection health through a per-connection atom

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* e2e: bound the churn scenario to its own connections

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

* Preload console route chunks on sidebar link hover. (UsefulSoftwareCo#2081)

Co-authored-by: Cursor <cursoragent@cursor.com>

* Revert "Preload console route chunks on sidebar link hover. (UsefulSoftwareCo#2081)" (UsefulSoftwareCo#2082)

This reverts commit 315ea3c.

* Collect tax IDs in Stripe checkout (UsefulSoftwareCo#2098)

* Keep workspace-write access on cross-session MCP resume (UsefulSoftwareCo#2099)

* Require MFA to unlock cloud administration (UsefulSoftwareCo#2109)

* Test cloud admin verification and ordinary access (UsefulSoftwareCo#2110)

* Revert admin MFA requirement (UsefulSoftwareCo#2109, UsefulSoftwareCo#2110) (UsefulSoftwareCo#2115)

* Revert "Test cloud admin verification and ordinary access (UsefulSoftwareCo#2110)"

This reverts commit fec546e.

* Revert "Require MFA to unlock cloud administration (UsefulSoftwareCo#2109)"

This reverts commit d0ca1b6.

* chore: reapply fork customizations on current upstream

* fix(cloudflare): register MCP discovery routes

---------

Co-authored-by: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Nidhi Singh <nidhi2894@gmail.com>
Co-authored-by: Aarushi Singh <175547726+The-AarushiSingh@users.noreply.github.com>
Co-authored-by: yingchao <yc@yingchao.dev>
Co-authored-by: mmarabel <166927047+mmarabel@users.noreply.github.com>
Co-authored-by: smrht <62819456+smrht@users.noreply.github.com>
Co-authored-by: Aditya kumar singh <143548997+Adityakk9031@users.noreply.github.com>
Co-authored-by: Saatvik Arya <aryasaatvik@gmail.com>
Co-authored-by: ra-co88 <racore88.ai@gmail.com>
Co-authored-by: pt-act <211776491+pt-act@users.noreply.github.com>
Co-authored-by: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com>
Co-authored-by: Davies Ayo <dadaviesayo@gmail.com>
Co-authored-by: Lloyd Vickery <115056532+LloydVickeryASI@users.noreply.github.com>
Co-authored-by: Lloyd Vickery <lvickery@Lloyds-MacBook-Pro.local>
Co-authored-by: Alp <karavil.alp@gmail.com>
Co-authored-by: pt-act <pt-act@users.noreply.github.com>
Co-authored-by: Utpal Singh <110197373+utpalsinghdev@users.noreply.github.com>
Co-authored-by: Tony(Gijung) Kim <44659712+GijungKim@users.noreply.github.com>
Co-authored-by: mikemikimike <13286568797@163.com>
Co-authored-by: Dara Adedeji <76637177+SunkenInTime@users.noreply.github.com>
Co-authored-by: Don Pansacola <don.masakayan@gmail.com>
Co-authored-by: Don Pansacola <1178461+donmasakayan@users.noreply.github.com>
Co-authored-by: Dara Adedeji <shawnadedeji@gmail.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Rhys Sullivan <rhys@rhyssullivan.com>
Co-authored-by: Swedish Chef <142688016+SwedishChef1@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: airbooks-alpha[bot] <285858461+airbooks-alpha[bot]@users.noreply.github.com>
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.

1 participant