Skip to content

refactor(appkit): own asUser OBO wrapping in Plugin proxy#385

Open
MarioCadenas wants to merge 1 commit into
mainfrom
mario/refactor-asuser-proxy
Open

refactor(appkit): own asUser OBO wrapping in Plugin proxy#385
MarioCadenas wants to merge 1 commit into
mainfrom
mario/refactor-asuser-proxy

Conversation

@MarioCadenas
Copy link
Copy Markdown
Collaborator

Move the OBO-side exports() wrapping out of AppKit#wrapWithAsUser and into Plugin.asUser's proxy. The proxy now intercepts reads of exports and returns the underlying exports() result with every function pre-wrapped in the user-context scope. The cross-file USER_CONTEXT_SYMBOL bridge between plugin.ts and appkit.ts is removed, and wrapExportsInUserContext is deleted from appkit.ts.

The two inline Proxy literals in Plugin.asUser (real OBO and dev-mode fallback) collapse into a single _createAsUserProxy(wrapCall) factory that takes a per-call wrap strategy. The real OBO branch uses runInUserContext(userContext, ...); the dev fallback uses otelContext.with(DEV_OBO_FALLBACK_KEY=true, ...).

Behavior preserving: full appkit test suite passes and typecheck is clean. Adds a focused 26-test file covering proxy mechanics: real OBO method calls, exports() interception (class methods, arrows, nested plain objects, class-instance values not recursed, callable exports, null/undefined), AsyncLocalStorage propagation across Promise.all, concurrent user isolation, error cleanup, dev-fallback exports(), and escape-the-proxy boundaries (returned functions not auto-wrapped, return this returns the unwrapped target).

Also drop the now-unused UserContext type re-export from the internal context barrel (not part of the public package entry).

Move the OBO-side exports() wrapping out of AppKit#wrapWithAsUser
and into Plugin.asUser's proxy. The proxy now intercepts reads of
`exports` and returns the underlying exports() result with every
function pre-wrapped in the user-context scope. The cross-file
USER_CONTEXT_SYMBOL bridge between plugin.ts and appkit.ts is
removed, and wrapExportsInUserContext is deleted from appkit.ts.

The two inline Proxy literals in Plugin.asUser (real OBO and
dev-mode fallback) collapse into a single _createAsUserProxy(wrapCall)
factory that takes a per-call wrap strategy. The real OBO branch
uses runInUserContext(userContext, ...); the dev fallback uses
otelContext.with(DEV_OBO_FALLBACK_KEY=true, ...).

Behavior preserving: full appkit test suite passes and typecheck is
clean. Adds a focused 26-test file covering proxy mechanics: real
OBO method calls, exports() interception (class methods, arrows,
nested plain objects, class-instance values not recursed, callable
exports, null/undefined), AsyncLocalStorage propagation across
Promise.all, concurrent user isolation, error cleanup, dev-fallback
exports(), and escape-the-proxy boundaries (returned functions not
auto-wrapped, `return this` returns the unwrapped target).

Also drop the now-unused UserContext type re-export from the
internal context barrel (not part of the public package entry).

Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
@MarioCadenas MarioCadenas requested a review from a team as a code owner May 14, 2026 14:36
@MarioCadenas MarioCadenas requested a review from pkosiec May 14, 2026 14:36
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