PHPackages                             milpa/live-web - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. milpa/live-web

ActiveLibrary[Framework](/categories/framework)

milpa/live-web
==============

HTTP/HTML transport layer for Milpa Live: CSRF/HMAC/nonce security, the signed XHTML state-transfer codec, the wire-protocol LiveEndpoint controller, and the HTML/Alpine/Latte-subset renderers for the Milpa PHP framework.

v0.2.2(3w ago)0258↑100%1Apache-2.0PHPPHP &gt;=8.3CI passing

Since Jul 8Pushed 1mo agoCompare

[ Source](https://github.com/getmilpa/live-web)[ Packagist](https://packagist.org/packages/milpa/live-web)[ RSS](/packages/milpa-live-web/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (3)Dependencies (21)Versions (7)Used By (1)

 [   ![Milpa](https://raw.githubusercontent.com/getmilpa/core/main/art/lockup/milpa-lockup-v-color-light.svg)  ](https://github.com/getmilpa)

Milpa Live Web
==============

[](#milpa-live-web)

> The **web surface** for `milpa/live` — HTML renderers over the design system, XHTML state/interaction codecs, and a security-hardened `LiveEndpoint` (HMAC-signed state, CSRF, single-use nonce/replay protection).

[![CI](https://github.com/getmilpa/live-web/actions/workflows/ci.yml/badge.svg)](https://github.com/getmilpa/live-web/actions/workflows/ci.yml)[![Packagist](https://camo.githubusercontent.com/3be57d4563da2320d70619b6a88fd62b5a3e69750520f84849a1b1da046ae2e0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d696c70612f6c6976652d7765622e737667)](https://packagist.org/packages/milpa/live-web)[![PHP](https://camo.githubusercontent.com/ca03f11ea27dac4dedc8ad56a7bdfc4a9ff5feb825055f9d2983616115076607/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d254532253839254135253230382e332d3737376262342e737667)](https://www.php.net/)[![License](https://camo.githubusercontent.com/798509b4df525f56802b56f8096862487f08023e3d7561c68656f8dab10d0d6e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4170616368652d2d322e302d626c75652e737667)](LICENSE)[![Docs](https://camo.githubusercontent.com/c6dc6a3411e15b0ac7cc4583e8e6a8144181caedb82f5d98753353decda06d77/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f646f63732d4150492532307265666572656e63652d626c75652e737667)](https://getmilpa.github.io/live-web/)

`milpa/live` defines the render-target-agnostic component lifecycle (mount / handle / render, contracts, data sources). `milpa/live-web` is what makes that lifecycle reachable over HTTP and renderable to a browser: HTML renderers for the form, dashboard, and autocomplete component families, a dependency-free XHTML state/interaction transport codec, and the security package — HMAC state signing, CSRF, and single-use nonce/replay protection — that `LiveEndpoint` composes into one hardened HTTP entrypoint.

Install
-------

[](#install)

```
composer require milpa/live-web
```

What it is
----------

[](#what-it-is)

- **`LiveEndpoint`** — the HTTP live-loop terminus. Verifies the request method, the CSRF token, and the signed state envelope; authorizes the requested action against the component's own contract; dispatches to the component's `handle()`; and returns freshly rendered HTML plus a freshly signed state envelope for the client to hold onto. Every ordinary failure (bad method, missing fields, invalid signature, replay, unauthorized action) returns a typed error response — it never throws for expected bad input.
- **HTML renderers** — `AutocompleteHtmlRenderer`, `FormPrimitiveHtmlRenderer` (`input`, `textarea`, `select`, `checkbox`), and `DashboardHtmlRenderer` (shell, sidebar, topbar, grid, panel, metric card, data table, …) each turn a component's state into Alpine-bound HTML over the `@milpa/design` system. `XhtmlComponentCompiler` lets you author `` component trees directly in markup and compiles them through the same renderer pipeline.
- **Transport** — `XhtmlStateTransferCodec` encodes a component's state/interaction as a single `` / `` XHTML element with a base64 JSON payload. It carries no security guarantees on its own — it is the `$inner` codec `SignedXhtmlStateTransferCodec` wraps.
- **Security** — `HmacStateSigner`, `HmacCsrfGuard`, `FileNonceStore`, `SignedXhtmlStateTransferCodec`, `ContractInteractionAuthorizer`, and `AllowListCorsPolicy` are the concrete, production classes `LiveEndpoint` is built to trust — see [Security](#security) below.
- **`AlpineRuntimeAdapter`** — the `Milpa\Live\Contracts\Client\ClientRuntimeAdapterInterface`implementation the shipped renderers target; it marks root elements with `data-milpa-*`attributes and describes the boot payload/asset the Alpine runtime script consumes.

Quick example
-------------

[](#quick-example)

Wiring the real security classes and issuing one interaction through `LiveEndpoint` — this is a trimmed version of what `tests/Http/LiveEndpointTest.php` exercises, and runs as-is against this package's own `vendor/`:

```
use Milpa\Live\Adapters\Alpine\AlpineRuntimeAdapter;
use Milpa\Live\Components\Autocomplete\AutocompleteComponent;
use Milpa\Live\DataSource\ArrayDataSource;
use Milpa\Live\DataSource\InMemoryDataSourceRegistry;
use Milpa\Live\Http\LiveEndpoint;
use Milpa\Live\Http\LiveHttpRequest;
use Milpa\Live\Rendering\AutocompleteHtmlRenderer;
use Milpa\Live\Runtime\InMemoryComponentRegistry;
use Milpa\Live\Security\ContractInteractionAuthorizer;
use Milpa\Live\Security\FileNonceStore;
use Milpa\Live\Security\HmacCsrfGuard;
use Milpa\Live\Security\HmacStateSigner;
use Milpa\Live\Security\SignedXhtmlStateTransferCodec;
use Milpa\Live\Transport\XhtmlStateTransferCodec;
use Milpa\Live\ValueObjects\ComponentContext;

// A real component (milpa/live) over a real data source.
$sources = new InMemoryDataSourceRegistry();
$sources->register(new ArrayDataSource('customers.search', [
    ['value' => 'acme', 'label' => 'Acme Studio', 'search' => 'agency design'],
    ['value' => 'milpa', 'label' => 'Milpa Labs', 'search' => 'framework components'],
]));
$components = new InMemoryComponentRegistry();
$components->register('autocomplete', new AutocompleteComponent($sources));

// The real security wiring: HMAC-signed state + single-use replay nonce + CSRF.
$codec = new SignedXhtmlStateTransferCodec(
    new XhtmlStateTransferCodec(),
    new HmacStateSigner($_ENV['LIVE_STATE_SECRET']),
    new FileNonceStore(sys_get_temp_dir() . '/milpa-live-nonces.json'),
);
$csrf = new HmacCsrfGuard($_ENV['LIVE_CSRF_SECRET']);

$endpoint = new LiveEndpoint(
    components: $components,
    codec: $codec,
    authorizer: new ContractInteractionAuthorizer($components),
    csrf: $csrf,
    route: '/live/autocomplete',
    renderers: ['autocomplete' => new AutocompleteHtmlRenderer(new AlpineRuntimeAdapter(), $codec)],
);

// Mount the initial state (server-rendered on the page) and issue a CSRF token for the session.
$context = new ComponentContext('customer-picker', route: '/autocomplete-demo');
$state = $components->get('autocomplete')->mount(['name' => 'customer', 'source' => 'customers.search'], $context);
$sessionId = 'demo-session'; // however your app tracks sessions (e.g. the PHP session id)
$csrfToken = $csrf->issueToken($sessionId, '/live/autocomplete');
$envelope = $codec->encodeState($state); // embed both in the SSR'd page

// The client echoes $envelope + $csrfToken back on every interaction.
$response = $endpoint->handle(new LiveHttpRequest(
    method: 'POST',
    action: 'search',
    stateEnvelope: $envelope,
    payload: ['query' => 'mil'],
    sessionId: $sessionId,
    csrfToken: $csrfToken,
));

$response->status;             // 200
$response->body['data'];       // ['items' => [['value' => 'milpa', ...]]]
$response->body['html'];       // freshly rendered …
$response->body['state'];      // a freshly signed  envelope for the next round-trip
```

Security
--------

[](#security)

`LiveEndpoint`'s trust model, in one line: **the client cannot hold the signing secret, so it never builds a state envelope itself** — it only ever echoes back, byte for byte, the last `` envelope this server signed and handed it (first embedded in the SSR'd page, then refreshed on every response). Verifying that envelope is what proves it hasn't been tampered with:

- **Tamper → reject.** Any change to the signed envelope — the component id, the state payload, a claim — fails HMAC-SHA256 verification and `LiveEndpoint` returns `400 invalid_signature`before the request ever reaches a component's `handle()`.
- **Replay → 409, not silently reused.** When a `FileNonceStore` (or another `NonceStoreInterface`) is wired into `SignedXhtmlStateTransferCodec`, every signature carries a single-use nonce; decoding the exact same signed envelope a second time throws `ReplayedNonceException` and `LiveEndpoint` answers `409 replay_detected` — a conflict with the server's current state, not a permissions failure, because the request was genuinely authentic the first time.
- **CSRF is a separate, independent gate.** `HmacCsrfGuard` binds a token to the exact `sessionId`/`route` pair it was issued for; a token issued for one session or route never verifies for another, and CSRF failure (`403 csrf`) is checked before the state envelope is even decoded.
- **Authorization is contract-based, not ambient.** `ContractInteractionAuthorizer` only allows an action that the component's own contract declares, checks that the state's owning principal (if any) matches the caller, and requires the derived `milpa:component:{name}:{action}` scope — an attacker who forges a plausible-looking action name still gets `403 action_not_allowed`.

None of this is optional wiring you have to remember: `LiveEndpoint::handle()` runs method → CSRF → signature/replay → authorization, in that order, and turns every failure into the matching HTTP status instead of throwing.

**The `@milpa/design` topology caveat.** The HTML renderers' CSS comes from `Milpa\Live\Support\MilpaDesign`, which resolves the `@milpa/design` npm package at `node_modules/@milpa/design` under your project root. If your layout differs (a monorepo, a lab checkout without `npm install`), set `MILPA_DESIGN_PATH` to the design package's directory — it takes priority over the npm-relative lookup and is checked first by every method on `MilpaDesign`.

What's inside
-------------

[](#whats-inside)

NamespaceWhat it provides`Milpa\Live\Http``LiveEndpoint` — the hardened HTTP live-loop entrypoint`Milpa\Live\Security``HmacStateSigner`, `HmacCsrfGuard`, `FileNonceStore`, `SignedXhtmlStateTransferCodec`, `ContractInteractionAuthorizer`, `AllowListCorsPolicy`, `StaticBearerTokenVerifier``Milpa\Live\Transport``XhtmlStateTransferCodec` — the unsigned inner transport codec`Milpa\Live\Rendering``AutocompleteHtmlRenderer`, `FormPrimitiveHtmlRenderer`, `DashboardHtmlRenderer`, `LatteTemplateRenderer`, `XhtmlComponentCompiler``Milpa\Live\Adapters\Alpine``AlpineRuntimeAdapter` — the shipped `ClientRuntimeAdapterInterface``Milpa\Live\Support``Html` (escaping helpers), `MilpaDesign` (design-system path resolution)`Milpa\Live\Contracts\*``Security`, `Rendering`, and `Transport` seams — `CsrfGuardInterface`, `StateSignerInterface`, `NonceStoreInterface`, `StateTransferCodecInterface`, `ComponentRendererInterface`, `MarkupCompilerInterface`, `TemplateRendererInterface`, `CorsPolicyInterface`, `InteractionAuthorizerInterface`, `TokenVerifierInterface``Milpa\Live\ValueObjects``StateSignature`, `AuthorizationResult`, `CorsDecision`Every public symbol carries a DocBlock.

Requirements
------------

[](#requirements)

- PHP **≥ 8.3** with the **`ext-dom`** extension
- [`milpa/core`](https://packagist.org/packages/milpa/core) **^0.6**
- [`milpa/live`](https://packagist.org/packages/milpa/live) **^0.1**

Documentation
-------------

[](#documentation)

**Full API reference: [getmilpa.github.io/live-web](https://getmilpa.github.io/live-web/)** — generated straight from the source DocBlocks and dressed with the Milpa design system.

Contributing
------------

[](#contributing)

Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). Please report security issues via [SECURITY.md](SECURITY.md), and note that this project follows a [Code of Conduct](CODE_OF_CONDUCT.md).

License
-------

[](#license)

[Apache-2.0](LICENSE) © Rodrigo Vicente - TeamX Agency.

---

Milpa is designed, built, and maintained by **[Rodrigo Vicente - TeamX Agency](https://teamx.agency/?utm_source=github&utm_medium=readme&utm_campaign=milpa&utm_content=live-web)**.

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance93

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 78.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

6

Last Release

24d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1993784?v=4)[rodrigomx](/maintainers/rodrigomx)[@rodrigomx](https://github.com/rodrigomx)

---

Top Contributors

[![rodrigoteamx](https://avatars.githubusercontent.com/u/269849276?v=4)](https://github.com/rodrigoteamx "rodrigoteamx (11 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (3 commits)")

---

Tags

frameworklive-componentsphpsecuritywebphpframeworkwebsecurityhtmlcsrflive-componentsmilpa

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/milpa-live-web/health.svg)

```
[![Health](https://phpackages.com/badges/milpa-live-web/health.svg)](https://phpackages.com/packages/milpa-live-web)
```

###  Alternatives

[laravel/framework

The Laravel Framework.

34.9k556.2M21.6k](/packages/laravel-framework)[symfony/symfony

The Symfony PHP framework

31.4k87.4M2.2k](/packages/symfony-symfony)[symfony/framework-bundle

Provides a tight integration between Symfony components and the Symfony full-stack framework

3.6k257.3M12.5k](/packages/symfony-framework-bundle)[shopware/platform

The Shopware e-commerce core

3.4k1.5M3](/packages/shopware-platform)[flow-php/flow

PHP ETL - Extract Transform Load - Data processing framework

86337.5k](/packages/flow-php-flow)[hypervel/framework

The Hypervel framework.

1119.1k13](/packages/hypervel-framework)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
