Skip to content

fix(runtime): resolve session identity for action body ctx.user (#2701)#2725

Merged
os-zhuang merged 3 commits into
mainfrom
fix/action-ctx-user-2701
Jul 10, 2026
Merged

fix(runtime): resolve session identity for action body ctx.user (#2701)#2725
os-zhuang merged 3 commits into
mainfrom
fix/action-ctx-user-2701

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Problem

The POST /actions/:object/:action route registered its handler on the raw HTTP
server and called handleActions directly, bypassing dispatcher.dispatch().
Since resolveExecutionContext only runs inside dispatch(), the request's
executionContext was never populated, and handleActions additionally built
ctx.user from _context.user / _context.userId — fields HttpProtocolContext
never carries — hard-falling to { id: 'system' }.

Net effect: the action body sandbox's ctx.user was always system (no id,
no roles), so handlers could not branch on the operator's identity/business roles
or enforce server-side ownership. Every other entrypoint (MCP runAction,
record-change trigger) already resolved the session correctly — the action route
was the single miss. (Closes #2701)

Fix

Route action requests through dispatch() like the automation/AI routes, so the
per-request pipeline resolves identity (and swaps to the per-project kernel)
before the action body runs — this eliminates the "bypass dispatch" workaround
rather than papering over it with a fallback.

  • dispatcher-plugin.tsregisterActionRoutes now calls
    dispatch('POST', '/actions/…'). The scoped-URL :environmentId rides on
    req.params and is picked up by prepareResolverHints, exactly as automation does.
  • http-dispatcher.tshandleActions builds ctx.user from the resolved
    ExecutionContext (id, email, roles/positions = ADR-0090 business roles,
    permissions, tenantId), matching the MCP/record-change paths. Falls back to a
    system principal only for a genuinely anonymous / self-invoked call. The stale
    kernel-swap comment is updated (the block is now an idempotent fallback for direct
    handleActions callers).

No authoring change is required — handlers that always saw ctx.user.id === 'system'
now see the real caller.

Verification

  • 4 regression tests in http-dispatcher.test.ts, including an end-to-end
    case: mint an api key → dispatch('/actions/…')resolveExecutionContext
    action, asserting the principal reaches ctx.user (id user_9, not system).
  • Red-test check: temporarily restoring the pre-fix code turns all 4 red
    (expected 'system' to be 'user_42', 'system' to be 'user_9', …), confirming the
    tests actually guard the bug.
  • Typecheck (tsup DTS) passes; dispatcher-plugin.routes + ready.integration
    tests green (9/9); full http-dispatcher.test.ts green (156/156).

🤖 Generated with Claude Code

os-zhuang and others added 2 commits July 10, 2026 10:30
chore: release packages (#2304)

objectui@7a68d78f2a0c3c1f99dafd39b75b4f117a24917b
The POST /actions/:object/:action route called handleActions directly,
bypassing dispatch() → resolveExecutionContext. The action body sandbox's
ctx.user was therefore hard-coded to { id: 'system' }, so handlers could not
branch on the operator's identity/roles or enforce server-side ownership.

- dispatcher-plugin: action routes now dispatch through dispatch() (like the
  automation/AI routes), resolving the session identity + per-project kernel
  per request before the action body runs.
- http-dispatcher: handleActions builds ctx.user from the request's
  ExecutionContext (id, email, positions/roles, permissions, tenantId),
  matching the MCP runAction and record-change trigger paths; falls back to a
  system principal only for a genuinely anonymous / self-invoked call.
- Tests: 4 regression cases incl. an end-to-end api-key → dispatch → action
  pipeline asserting the principal reaches ctx.user (verified red without the fix).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 10, 2026 5:04am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/runtime.

15 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/api/index.mdx (via @objectstack/runtime)
  • content/docs/api/wire-format.mdx (via @objectstack/runtime)
  • content/docs/automation/hook-bodies.mdx (via @objectstack/runtime)
  • content/docs/concepts/north-star.mdx (via packages/runtime)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/runtime)
  • content/docs/deployment/index.mdx (via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/deployment/vercel.mdx (via @objectstack/runtime)
  • content/docs/permissions/authentication.mdx (via @objectstack/runtime)
  • content/docs/plugins/packages.mdx (via @objectstack/runtime)
  • content/docs/protocol/objectos/http-protocol.mdx (via @objectstack/runtime)
  • content/docs/protocol/objectos/index.mdx (via @objectstack/runtime)
  • content/docs/protocol/objectos/lifecycle.mdx (via @objectstack/runtime)
  • content/docs/releases/implementation-status.mdx (via @objectstack/runtime)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit 57b8fe0 into main Jul 10, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the fix/action-ctx-user-2701 branch July 10, 2026 08:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[runtime] 动作 body 沙箱 ctx.user 恒为 system:REST 动作路由独漏 ec?.userId 回退

1 participant