Skip to content
docsv0.31.1

LiveEndpoint

The HTTP live loop terminus: verifies a request, dispatches it to a mounted component's `handle()`, re-renders, and returns a response the client can apply. This is the controller the 2026-07-08 lab audit found missing — Sync/Transport/Security were all individually proven but never wired to a real entrypoint. Trust model: the client cannot hold the HMAC signing secret, so it never builds a signed envelope itself. Instead it echoes back — byte for byte — the last `<milpa-state>` envelope the server signed and handed it (first embedded in the SSR'd page, then refreshed on every response). Verifying that envelope (`StateTransferCodecInterface::decodeState()`) is what proves the state hasn't been tampered with since this server last saw it; `action`/`payload` are ordinary untrusted input, constrained instead by the CSRF guard and the contract-based action allowlist. One endpoint per page (greenhouse decisions/0211): `$components` may be a {@see \Milpa\Live\Runtime\CompositeComponentRegistry} over the host's and every plugin's components (only `has`/`get` are needed), and `$renderers` may be a {@see ComponentRendererRegistry} instead of a hand-wired name => renderer array — it answers per name (`registerFor()`), exactly what the array did — then one endpoint re-renders every plugin's components and a {@see RenderEffect} resolves across layers. The session id the CSRF token is checked against is {@see LiveHttpRequest::$sessionId}, and the contract is that the host's adapter fills it from the request body's `sessionId` — the runtime echoes the boot the host issued with {@see LiveBoot::issue()} — not from a cookie. This endpoint cannot see where the adapter took it from; keeping that contract is the adapter's job.

LiveEndpoint::__construct()

public function __construct(Milpa\Live\Contracts\Component\ComponentRegistryInterface $components, Milpa\Live\Contracts\Transport\StateTransferCodecInterface $codec, Milpa\Live\Contracts\Security\InteractionAuthorizerInterface $authorizer, Milpa\Live\Contracts\Security\CsrfGuardInterface $csrf, string $route, Milpa\Live\Rendering\ComponentRendererRegistry|array $renderers = [], array $renderProps = [], ?Milpa\Interfaces\Event\MilpaEventDispatcherInterface $dispatcher = null, Milpa\Live\Assets\ComponentAssetOrchestrator $assetOrchestrator = new ComponentAssetOrchestrator(), string $locale = Milpa\Live\Assets\ComponentMessages::DEFAULT_LOCALE):

Parameters

Parameters of __construct()
NameTypeDescription
$componentsMilpa\Live\Contracts\Component\ComponentRegistryInterface
$codecMilpa\Live\Contracts\Transport\StateTransferCodecInterface
$authorizerMilpa\Live\Contracts\Security\InteractionAuthorizerInterface
$csrfMilpa\Live\Contracts\Security\CsrfGuardInterface
$routestring
$renderers(array<string, ComponentRendererInterface> | ComponentRendererRegistry)component name => renderer used to re-render after handle(), or a registry answering {@see ComponentRendererRegistry::resolveFor()} per name (its `registerFor()`ed renderers only — like the array, no fallback)
$renderPropsarray<string, array<string, mixed>>component name => base render props needed to re-render faithfully (e.g. the live endpoint URL)
$dispatcher?Milpa\Interfaces\Event\MilpaEventDispatcherInterface
$assetOrchestratorMilpa\Live\Assets\ComponentAssetOrchestrator
$localestring

LiveEndpoint::handle()

public function handle(Milpa\Live\Http\LiveHttpRequest $request, ?Milpa\Live\ValueObjects\SecurityPrincipal $principal = null): Milpa\Live\Http\LiveHttpResponse

Processes one interaction request end to end: method/CSRF/state- signature checks, authorization, dispatch to {@see \Milpa\Live\Contracts\Component\ComponentDefinitionInterface::handle()}, and (when a renderer is registered for the component) re-rendering to HTML. Every failure path returns an {@see LiveHttpResponse} error rather than throwing — this method MUST NOT throw for ordinary bad input (wrong method, missing fields, invalid/expired state signature, failed CSRF/authorization); it is the single point that turns those into the appropriate HTTP status code. `$principal` MUST already be resolved by the caller (e.g. via a {@see \Milpa\Live\Contracts\Security\TokenVerifierInterface}) — this method only consumes it for authorization, it does not perform authentication itself. When the guard implements {@see CsrfTokenLifetimeInterface} and the presented token has less than a tenth of its TTL left, the OK response carries a fresh `csrfToken` for the same session and route; the remote runtime stores it in the boot for the next action.

Parameters

Parameters of handle()
NameTypeDescription
$requestMilpa\Live\Http\LiveHttpRequest
$principal?Milpa\Live\ValueObjects\SecurityPrincipal