LiveController
The panel's live wire: `POST {route}/live` — one endpoint over the ONE registry the page compiled with, so a component of the panel's own and a component a guest declared take their actions through the same door (greenhouse decisions/0211). The registry is rebuilt from the SAME reading the page used ({@see BootedPlugins}, then {@see ComponentBook::forSections()}): the sections are discovered per request on both surfaces, so an envelope minted while painting a page RESOLVES here, and a `RenderEffect` from a host component can repaint a guest's. **Resolving is not verifying, and the key is the app's.** This endpoint verifies with the PANEL's codec ({@see AdminSettings::signingSecret()} — `admin.secret`, else `live.secret`, else one derived from this install), while a guest's renderer signed with the guest package's own key. An app that declares neither gives the two different derived keys, and a guest's envelope is refused `400 invalid_signature` — loud, per call, never silent. Declaring one house key (`live.secret`) is what makes host and guest sign alike; measured both ways on a fresh app. The residue is named in the README: {@see \Milpa\Admin\Section\DeclaredView} does not receive the panel's codec, so a guest cannot borrow the host's key without the app saying so. **Behind the same door.** The route carries the panel's effective middleware stack — the gate of greenhouse decisions/0204 and 0206, whatever the app declared — because a wire outside the door would be a hole: an unauthenticated caller could act on any mounted component of any section. The endpoint adds no second policy of its own; it names WHO acted (the actor the gate authenticated, with the component scopes) so a component whose state is bound to a principal recognises its owner. Nobody signed in is `null` — the panel invents no identity, exactly as the topbar does not. The page session the CSRF token is bound to comes from the REQUEST BODY: `LiveBoot::issue()` minted it when the page was rendered and the runtime echoes it as `sessionId` on every action. No cookie carries it — a cookie another page set is not this page's session.
LiveController::__construct()
public function __construct(Milpa\Interfaces\Di\DIContainerInterface $container, object $self, Milpa\Live\Contracts\Transport\StateTransferCodecInterface $codec, Milpa\Live\Contracts\Security\CsrfGuardInterface $csrf, Milpa\Admin\AdminSettings $settings, ?Milpa\Interfaces\Event\MilpaEventDispatcherInterface $events = null):Parameters
| Name | Type | Description |
|---|---|---|
| $container | Milpa\Interfaces\Di\DIContainerInterface | |
| $self | object | the admin plugin instance — the one section provider the panel can count on without a kernel |
| $codec | Milpa\Live\Contracts\Transport\StateTransferCodecInterface | |
| $csrf | Milpa\Live\Contracts\Security\CsrfGuardInterface | |
| $settings | Milpa\Admin\AdminSettings | |
| $events | ?Milpa\Interfaces\Event\MilpaEventDispatcherInterface |
LiveController::live()
public function live(Psr\Http\Message\ServerRequestInterface $request): Psr\Http\Message\ResponseInterfaceHandle one component interaction: `{action, state, payload, sessionId, csrfToken}` in, re-rendered HTML + a fresh envelope out.
Parameters
| Name | Type | Description |
|---|---|---|
| $request | Psr\Http\Message\ServerRequestInterface |