Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1a0e196
Restrict workspace writes to admins
RhysSullivan Sep 1, 2026
fca1d3b
Fix self-host MCP request forwarding
RhysSullivan Sep 2, 2026
c2c2b74
Update file secrets durability invariant
RhysSullivan Sep 2, 2026
0bd654a
Fix versioned cloud credentials
RhysSullivan Sep 2, 2026
ea31cbe
Fix self-host live-role scenario
RhysSullivan Sep 2, 2026
f38570d
Update cloud principal contract tests
RhysSullivan Sep 2, 2026
390aa48
Remove stray audit history assertions
RhysSullivan Sep 2, 2026
08a2f32
Fix no-auth credential classification
RhysSullivan Sep 2, 2026
9011ead
fix(mcp): project legacy stdio as no-auth
RhysSullivan Sep 2, 2026
e33c27b
fix(graphql): classify empty auth templates as no-auth
RhysSullivan Sep 2, 2026
d8ae8c3
fix(sdk): defer no-auth classification to engine
RhysSullivan Sep 2, 2026
d4bf88b
fix(sdk): ignore placements on no-auth methods
RhysSullivan Sep 2, 2026
68ff693
test(mcp): make reconcile cleanup infallible
RhysSullivan Sep 2, 2026
17ce156
test(graphql): use empty no-auth timeout input
RhysSullivan Sep 2, 2026
2e075f1
test(e2e): remove no-auth placeholder credentials
RhysSullivan Sep 2, 2026
2860568
test(e2e): use empty no-auth credential shapes
RhysSullivan Sep 2, 2026
33ec574
Project legacy stdio credentials truthfully
RhysSullivan Sep 2, 2026
70c5907
Reject invalid no-auth placements
RhysSullivan Sep 2, 2026
e8441ae
Reject MCP no-auth credential input
RhysSullivan Sep 2, 2026
5ddae31
Propagate MCP test cleanup failures
RhysSullivan Sep 2, 2026
6ab5835
Honor projected legacy stdio credentials
RhysSullivan Sep 2, 2026
322dc6b
Deduplicate invalid auth method warnings
RhysSullivan Sep 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/workspace-writes-admin-only.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
"@executor-js/sdk": minor
"@executor-js/api": minor
"@executor-js/plugin-graphql": minor
"@executor-js/plugin-mcp": minor
"@executor-js/plugin-openapi": minor
---

**Workspace writes now require an administrator**

Executor bindings accept `orgWrites: "allowed" | "denied" | "request"`.
Request-aware hosts use `"request"` and bind `CurrentOrgWriteAccess` from the
authenticated principal for each request. An approval, decline, cancellation,
or form response also rebinds the paused execution to the resumer's current
access. Browser approvals derive access from the authenticated browser user's
live organization membership when that user posts the decision, rather than
from the earlier MCP request waiting for it or the user's global role. Self-host
uses the same Better Auth membership lookup for ordinary requests and browser
decisions. A demotion before either kind of resume therefore takes effect
before the paused execution can reach a workspace-write sink.

`Principal` now declares its role model explicitly: organization-backed hosts
carry `orgRoleModel: "organization"` and an optional normalized admin/member
role, while hosts without roles carry `orgRoleModel: "none"` and cannot also
carry an organization role. Missing role data under the organization model
fails closed, including legacy persisted MCP session metadata. Cloud derives
roles from WorkOS memberships and self-host derives them from Better Auth.

Members may still read and execute shared workspace resources and perform
operational maintenance such as token refresh and tool-catalog synchronization.
User-requested workspace mutations now return `OrgWriteDeniedError` (HTTP 403):
workspace connections and reconnects, organization OAuth clients and connect
flows, tool policies, and integration add/update/replace/remove/health-check
operations. Personal connection management remains available.

Pasted connection credentials, OAuth client secrets, OAuth connection tokens,
and dependent tool discovery run only after the outermost transaction commits
their row, including when a plugin wraps creation in `ctx.transaction`. Each
committed row records unique provider item references owned by that write
attempt. Reads resolve only those recorded references, so the post-commit
window fails closed with a retryable incomplete-write error and can never
resolve a predecessor's credential. A process crash leaves detectable missing
references; a later executor incarnation can atomically replace and retry a
stranded pasted connection, while OAuth client and connection retries replace
their rows through their existing update paths.

If credential persistence fails while the process remains alive, row and
provider compensation restore the prior state where possible and surface
incomplete cleanup explicitly. Best-effort cleanup can leave inert orphaned
attempt items, but an attempt never shares an item reference with a successor,
eliminating the former successor-clobber interval without requiring provider
compare-and-set support.
2 changes: 2 additions & 0 deletions apps/cloud/drizzle/0017_lush_thunderbolts.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE "connection" ADD COLUMN "credential_write" json;--> statement-breakpoint
ALTER TABLE "oauth_client" ADD COLUMN "credential_write" json;
Loading
Loading