//! `SdkCallCx` — per-call context every stateful SDK service receives. //! //! Service trait methods (added by subsequent v1.1.x PRs starting with //! KV) all take `&SdkCallCx` so they can: //! * scope by `app_id` for cross-app isolation, //! * audit `principal` when authenticated, //! * carry `execution_id` / `request_id` into emitted events, //! * bound trigger chains via `trigger_depth` / `root_execution_id`. //! //! The struct lives in `picloud-shared` (not `executor-core`) because //! future service impls live in `manager-core` and the trait that hands //! the cx in is shared by both sides. Pure value type — no handles, no //! DB pool references, no allocations beyond what's in `Principal`. use crate::{AppId, ExecutionId, Principal, RequestId, TriggerEvent}; /// Per-invocation context for every stateful SDK service call. /// /// Constructed once at the start of an invocation by `executor-core` /// from the incoming `ExecRequest`, then handed (by reference) to every /// service trait method the script triggers during execution. Services /// MUST derive `app_id` from this struct — never from script-passed /// arguments — to preserve cross-app isolation. #[derive(Debug, Clone)] pub struct SdkCallCx { /// Owning application for this invocation. Source of truth for /// every `(app_id, …)` storage lookup the script makes. pub app_id: AppId, /// Caller identity, when authenticated. `None` for unauthenticated /// data-plane HTTP requests (the common case for public endpoints); /// `Some` when the call came in via the dashboard, an API key, or a /// future authed surface. pub principal: Option, /// Unique id for THIS execution. Matches `ExecRequest.execution_id`. pub execution_id: ExecutionId, /// Unique id for the ingress request that started the chain. The /// same `request_id` is shared across every execution triggered by /// the same request (direct + trigger fan-out). pub request_id: RequestId, /// `0` for direct invocations (HTTP request, manual run). Each /// indirect invocation through the triggers framework (v1.1.1) /// increments this; the dispatcher rejects beyond a configured /// ceiling to prevent runaway feedback loops. pub trigger_depth: u32, /// `== execution_id` when `trigger_depth == 0`; otherwise the /// `execution_id` of the original ingress execution. Lets the audit /// log group every fan-out execution under the originating event. pub root_execution_id: ExecutionId, /// `true` only when this invocation is a `dead_letter` trigger /// handler. Set by the dispatcher when it picks an outbox row /// whose trigger has `kind = 'dead_letter'`. The retry / dead- /// letter machinery short-circuits when this is set: handlers /// execute once, with no retry, and a failed run can NEVER be /// dead-lettered itself (design notes §4 recursion-stop rule). /// `false` for every other invocation, including the script /// being used as a non-DL trigger handler. pub is_dead_letter_handler: bool, /// The event that fired this script, when it's a triggered /// invocation. `None` for direct ingress (HTTP request, manual /// run). Surfaced to scripts as `ctx.event`. pub event: Option, }