feat(executor): thread the defining node into ExecRequest (Phase 4b C2)

Carry the resolved script's owner (its defining node) from dispatch into
the executor so `import` resolution can be lexical (§5.5). The executing
app (`app_id`) stays the SDK isolation boundary; `script_owner` is a
separate axis — the lexical origin for imports.

- `ExecRequest.script_owner: Option<ScriptOwner>` (serde default; `None`
  falls back to `App(app_id)` in the engine for old payloads / cluster wire).
- `ScriptOwner` gains `Serialize`/`Deserialize` for the wire.
- The engine computes `default_origin` and hands it to the resolver
  (used fully in C3; the resolve() lookup already uses it).
- Every dispatch site sets it from the resolved `Script.owner()`:
  the 4 dispatcher arms (queue/trigger/http/invoke_async, via a new
  `ResolvedTrigger.script_owner`), the orchestrator id-bypass, and the
  `invoke()` SDK path (new `ResolvedScript.owner`, so a group script
  invoked by an app resolves imports from the group).

Behaviour-preserving: app scripts still resolve `App(app_id)`; group
scripts can't yet carry imports (lifted in C4).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-26 07:17:33 +02:00
parent 7fef098b48
commit 1844bef132
25 changed files with 86 additions and 17 deletions

View File

@@ -18,7 +18,7 @@ use async_trait::async_trait;
use chrono::{DateTime, Utc};
use thiserror::Error;
use crate::{AppId, ExecutionId, ScriptId, SdkCallCx};
use crate::{AppId, ExecutionId, ScriptId, ScriptOwner, SdkCallCx};
/// Identifies the script to invoke. Accepted by `invoke()` and
/// `invoke_async()` script-side.
@@ -52,6 +52,12 @@ impl InvokeTarget {
pub struct ResolvedScript {
pub script_id: ScriptId,
pub app_id: AppId,
/// The resolved script's **defining node** (Phase 4b) — the lexical
/// origin its `import`s resolve against (§5.5). For an inherited group
/// script this is the **group**, even though `app_id` (the execution
/// boundary) is the caller's app. `None` only for a corrupt owner row;
/// the executor falls back to `App(app_id)`.
pub owner: Option<ScriptOwner>,
pub source: String,
pub updated_at: DateTime<Utc>,
/// Script.name — surfaced to the callee as `ctx.script_name`.