pub struct RuntimeService { /* private fields */ }Expand description
Service-layer wrapper around arkhe_kernel::Kernel. Builds a
kernel with WAL configured and exposes a forge-shaped dispatch API.
Implementations§
Source§impl RuntimeService
impl RuntimeService
Sourcepub fn new(world_id: [u8; 32], manifest_digest: [u8; 32]) -> Self
pub fn new(world_id: [u8; 32], manifest_digest: [u8; 32]) -> Self
Construct a service backed by a chain-only WAL writer (L0
SignatureClass::None). world_id and manifest_digest are
pinned into the WAL header.
Sourcepub fn register_action<A: Action>(&mut self)
pub fn register_action<A: Action>(&mut self)
Register a forge ArkheAction so the kernel will execute it
when scheduled. Any forge action whose type bears
#[derive(ArkheAction)] automatically satisfies the kernel
Action bound through the derive’s emitted kernel-side
stack.
Sourcepub fn create_instance(&mut self, config: InstanceConfig) -> InstanceId
pub fn create_instance(&mut self, config: InstanceConfig) -> InstanceId
Create a fresh kernel instance and return its InstanceId.
Sourcepub fn dispatch<A>(
&mut self,
instance: InstanceId,
principal: Principal,
action: &A,
at: Tick,
caps: CapabilityMask,
authenticated_actor: Option<ActorId>,
) -> Result<StepReport, DispatchError>where
A: Action,
pub fn dispatch<A>(
&mut self,
instance: InstanceId,
principal: Principal,
action: &A,
at: Tick,
caps: CapabilityMask,
authenticated_actor: Option<ActorId>,
) -> Result<StepReport, DispatchError>where
A: Action,
Dispatch a forge action — inject the authenticated actor through the
kernel actor channel, run the L2 GDPR admission gate on it,
postcard-encode the action’s canonical bytes, submit at tick at,
then step the kernel once with caps. Returns the kernel’s
StepReport so the caller can inspect actions_executed /
effects_applied / effects_denied.
§Single source of truth for the acting actor
authenticated_actor is the caller identity the integrator’s
auth / session layer (which sits ABOVE forge) has already verified —
e.g. resolved from a login session, bearer token, or passkey
assertion. None denotes a system / anonymous caller with no
authenticated actor.
dispatch threads this actor into Kernel::submit’s actor channel
(as Option<EntityId> via ActorId::get). The kernel records it in
the WAL record and replays it into KernelActionContext::actor, which
the arkhe_forge_core::bridge injects as the forge
ActionContext::acting_actor. A user-scoped compute body reads its
acting identity from THAT channel and stamps it into the stored record
(SpaceConfig.creator, ActivityRecord.actor) — there is no
wire-controlled actor field to substitute, so the C3
actor-substitution attack is structurally impossible. A user-scoped
action submitted with authenticated_actor == None is rejected inside
compute (the bridge collapses the rejection to no Ops, so it never
reaches the WAL). A system action that does not read acting_actor
proceeds with None.
§GDPR ErasurePending admission gate (C3)
The kernel compute path drives a forge action through a viewless
ActionContext (see arkhe_forge_core::bridge), so the
in-compute ensure_actor_eligible check soft-passes — it cannot
read the actor’s UserBinding / UserGdprState without a bound
view. This method closes that gap at the L2 boundary: when
authenticated_actor is Some, the service binds a fresh
InstanceView, runs the existing ensure_actor_eligible logic on
that injected actor, and REJECTS the action before submit if the
backing user is ErasurePending. The gate is SOUND — the actor it
gates on is the authenticated caller, the same single source of truth
the compute records. It is also LIVE:
GdprEraseUser transitions
the user’s UserGdprState to ErasurePending with a blind write
(valid on the viewless compute path), so once erasure is requested
this gate rejects the user’s subsequent actions before submit (never
reaches the WAL), as this method’s tests demonstrate.
§Errors
DispatchError::ErasurePending— the L2 gate rejected the action (backing user inGdprStatus::ErasurePending).DispatchError::Kernel— kernel-side error fromsubmit(InstanceNotFoundifinstanceis not live). Capability denial happens insidestepand is reflected in the returned report’seffects_deniedcount rather than as anErr.
Sourcepub fn export_wal(self) -> Option<Wal>
pub fn export_wal(self) -> Option<Wal>
Drain the kernel’s internal WAL (consumes the service so the kernel cannot continue stepping after export).