Skip to content

Revert PR #54 "fix(executor): pass ownerId via per-call props"#55

Merged
jonnyparris merged 1 commit intomainfrom
revert/outbound-props
Apr 27, 2026
Merged

Revert PR #54 "fix(executor): pass ownerId via per-call props"#55
jonnyparris merged 1 commit intomainfrom
revert/outbound-props

Conversation

@jonnyparris
Copy link
Copy Markdown
Owner

Summary

Reverts #54. Third broken attempt at this fix.

What happened

Live test from a fresh codemode session after deploying `3f7e774`:

```

await fetch("https://...")
Error: outbound is not a function
```

Root cause

The `LoopbackServiceStub` type with the callable `({ props })` signature is only materialized via `ctx.exports[name]`. A regular service binding declared in `wrangler.jsonc` (even when targeting your own Worker's `AllowlistOutbound` entrypoint) gives you a plain `Fetcher` — `.fetch()` and `.connect()` only. No callable.

I had typed `env.OUTBOUND` as `LoopbackServiceStub` based on the type definitions, but the workerd runtime doesn't actually wire that callable through for env-bindings. TS lied; production told the truth.

Path forward

The proper fix needs to plumb `ctx.exports.AllowlistOutbound` from the top-level worker fetch handler (where `ExecutionContext` is available) down through CodingAgent (a DurableObject, where `ctx` is `DurableObjectState` — no `exports`) to `runSandboxedCode`. That's a more invasive architectural change than what shipped here.

Score so far on this fix

Adding "live test before merging Workers infra fixes" to the workflow checklist permanently. See `memory/learnings.md` on agent-hq.

🤖 generated by ruskin's agent

This reverts commit 3f7e774b... at runtime with:

  outbound is not a function

The LoopbackServiceStub callable signature (env.OUTBOUND({ props })) is
ONLY available via ctx.exports, not via wrangler service bindings. A
regular service binding to your own Worker still gives you a plain
Fetcher with only .fetch() and .connect() — no per-call props
callable.

The proper fix needs to plumb ctx.exports.AllowlistOutbound from the
top-level fetch handler (which has ExecutionContext) down through
CodingAgent (a DurableObject, no ctx.exports) to runSandboxedCode.
That's a bigger architectural change than what shipped here — back to
the drawing board.

(Third attempt at this same fix. Pattern: types pass, unit tests pass,
runtime fails. Live testing before merge would have caught all three —
adding it to the workflow checklist.)
@jonnyparris jonnyparris merged commit c787a73 into main Apr 27, 2026
2 checks passed
@jonnyparris jonnyparris deleted the revert/outbound-props branch April 27, 2026 11:51
jonnyparris added a commit that referenced this pull request Apr 27, 2026
The duck-typed wrapper in wrapOutboundWithOwner returned a plain JS
object cast 'as Fetcher', which workerd rejects at WorkerCode
validation with:

  Incorrect type for the 'globalOutbound' field on 'WorkerCode':
  the provided value is not of type 'Fetcher'.

This broke every codemode sandbox fetch (and clone via codemode) for
any session with an ownerId — i.e. all logged-in users. Three prior
fix attempts (#52 LOADER.get proxy, #54 ctx.exports per-call props,
#55 revert) hit different runtime/architectural walls.

This change removes the wrapper entirely and passes env.OUTBOUND
directly to DynamicWorkerExecutor. workerd accepts it because
OUTBOUND is a real service-binding ServiceStub.

Trade-off: per-user GitHub/GitLab token injection for raw sandbox
fetch() is no longer wired up. AllowlistOutbound continues to enforce
the hostname allowlist, so the perimeter is unchanged. Sandbox code
that needs auth must include its own headers — but the sandbox no
longer has direct access to user secrets, which is the safer default.
Git operations are unaffected because resolveRemoteToken() runs in
the parent DO and tokens are passed straight to isomorphic-git.

System prompts updated to reflect the new contract.
Old outbound.test.ts (17 tests for the deleted injectAuth helper)
replaced with 4 tests covering the constants and stripping behaviour
that survive.
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