PHPackages                             waffle-commons/pipeline - 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. waffle-commons/pipeline

ActiveLibrary[Framework](/categories/framework)

waffle-commons/pipeline
=======================

Pipeline component for Waffle framework.

0.1.0-beta4(3w ago)1341MITPHPPHP ^8.5CI passing

Since Jan 5Pushed 3w agoCompare

[ Source](https://github.com/waffle-commons/pipeline)[ Packagist](https://packagist.org/packages/waffle-commons/pipeline)[ RSS](/packages/waffle-commons-pipeline/feed)WikiDiscussions main Synced today

READMEChangelog (8)Dependencies (48)Versions (26)Used By (1)

[![Discord](https://camo.githubusercontent.com/b30f41baece56d71f7f496f7e39fd33a2a096221c66c648b350dd4fe14276c2e/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f3735353238383030313539323033333339313f6c6f676f3d646973636f7264)](https://discord.gg/eKgywnfXr2)[![PHP Version Require](https://camo.githubusercontent.com/639fce377ca84bea153ad3bb793713a6179d13ae0eea37dcd076cc81c8d53d8f/687474703a2f2f706f7365722e707567782e6f72672f776166666c652d636f6d6d6f6e732f706970656c696e652f726571756972652f706870)](https://packagist.org/packages/waffle-commons/pipeline)[![PHP CI](https://github.com/waffle-commons/pipeline/actions/workflows/main.yml/badge.svg)](https://github.com/waffle-commons/pipeline/actions/workflows/main.yml)[![codecov](https://camo.githubusercontent.com/c201b6df2853a375e8cb6666e152029b2b240ad367536c7177f98e4cfec9b8c4/68747470733a2f2f636f6465636f762e696f2f67682f776166666c652d636f6d6d6f6e732f706970656c696e652f67726170682f62616467652e7376673f746f6b656e3d64373461633632612d373837322d343033352d386238622d626363336166313939316530)](https://codecov.io/gh/waffle-commons/pipeline)[![Latest Stable Version](https://camo.githubusercontent.com/077fc648e26931ad2568294a97eb9855fe2b3885d378c63bf3020ff4119c543a/687474703a2f2f706f7365722e707567782e6f72672f776166666c652d636f6d6d6f6e732f706970656c696e652f76)](https://packagist.org/packages/waffle-commons/pipeline)[![Latest Unstable Version](https://camo.githubusercontent.com/47aa5051ed65db344cbf95d51ca30515f539bde209b19199d1035e5ac131b537/687474703a2f2f706f7365722e707567782e6f72672f776166666c652d636f6d6d6f6e732f706970656c696e652f762f756e737461626c65)](https://packagist.org/packages/waffle-commons/pipeline)[![Total Downloads](https://camo.githubusercontent.com/46aaac797f8c6397f2aa90b7960cdcc573983c7ae388449cf0e14b943713c986/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f776166666c652d636f6d6d6f6e732f706970656c696e652e737667)](https://packagist.org/packages/waffle-commons/pipeline)[![Packagist License](https://camo.githubusercontent.com/84ac65ec097135115b4ac593dea4ee43d07a152fca48f3b0d618599ca1c70442/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f776166666c652d636f6d6d6f6e732f706970656c696e65)](https://github.com/waffle-commons/pipeline/blob/main/LICENSE.md)

Waffle Pipeline Component
=========================

[](#waffle-pipeline-component)

> **Release:** `0.1.0-beta4` | [`CHANGELOG.md`](./CHANGELOG.md)**PSR Compliance:** PSR-15 (`Psr\Http\Server\MiddlewareInterface`, `RequestHandlerInterface`), PSR-17 (response factory, optional for `OPTIONS` auto-answer)

The PSR-15 middleware stack that runs every request through the kernel. The stack locks itself the moment a request enters it, so middleware order cannot be tampered with mid-request.

📦 Installation
--------------

[](#-installation)

```
composer require waffle-commons/pipeline
```

🧱 Surface
---------

[](#-surface)

ClassRole`Waffle\Commons\Pipeline\MiddlewareStack``final` registry of middleware (`add`, `prepend`, `getMiddlewares`, `createHandler`). Implements `MiddlewareStackInterface`.`Waffle\Commons\Pipeline\RequestHandler`The PSR-15 handler that walks the stack and falls through to a terminal handler.`Waffle\Commons\Pipeline\CoreRoutingMiddleware`Routes the request and exposes the resolved controller / route params on the request attributes. **Beta-1:** raises the contracts-side `RouteNotFoundException` (instead of a generic `RuntimeException`) when no route matches, so missing routes render as `404` rather than `500`. Accepts an optional PSR-17 `ResponseFactoryInterface` — when supplied, an `OPTIONS` request to a known path is auto-answered `204` + `Allow`.`Waffle\Commons\Pipeline\Middleware\TrustedHostMiddleware``final readonly` PSR-15 middleware enforcing the configured trusted-host allowlist (RFC-003 §3.2).`Waffle\Commons\Pipeline\Middleware\SecureHeadersMiddleware`Adds baseline security response headers (`X-Content-Type-Options`, etc.).🚀 Building a stack (Beta-1 canonical order)
-------------------------------------------

[](#-building-a-stack-beta-1-canonical-order)

```
use Waffle\Commons\Pipeline\MiddlewareStack;
use Waffle\Commons\Pipeline\CoreRoutingMiddleware;
use Waffle\Commons\Pipeline\Middleware\SecureHeadersMiddleware;
use Waffle\Commons\Pipeline\Middleware\TrustedHostMiddleware;
use Waffle\Commons\Security\Middleware\AnonymousSessionMiddleware;
use Waffle\Commons\Security\Middleware\CsrfMiddleware;
use Waffle\Commons\Security\Middleware\SecurityMiddleware;

$stack = new MiddlewareStack();

$stack
    ->add(new ErrorHandlerMiddleware($renderer, $logger))            // 1. outermost (catches everything)
    ->add(new TrustedHostMiddleware(['example.com', 'api.example.com']))
    ->add(new AnonymousSessionMiddleware())                          // 3. issues WAFFLE_SID + _anon_sid attr
    ->add(new CoreRoutingMiddleware($router, $responseFactory))      // 4. resolves _classname / _method; auto-answers OPTIONS
    ->add(new CsrfMiddleware($csrfTokenManager))                     // 5. validates #[RequiresCsrfToken] using _anon_sid
    ->add(new SecurityMiddleware($secureContainer, $logger))         // 6. fail-closed ABAC analysis
    ->add(new SecureHeadersMiddleware())                             // 7. innermost — defensive response headers
;

$handler = $stack->createHandler($controllerDispatcher);
$response = $handler->handle($serverRequest);
```

`AnonymousSessionMiddleware` must run before `CsrfMiddleware` — the CSRF HMAC binds to the SID it publishes. `CoreRoutingMiddleware` must run before both Csrf and Security — both read `_classname`/`_method` from its request attributes.

After `createHandler()`, the stack is locked. Further `add()` / `prepend()` calls raise `RuntimeException('MiddlewareStack is locked and cannot be modified during request processing.')`.

🔒 Locking semantics
-------------------

[](#-locking-semantics)

```
final class MiddlewareStack implements MiddlewareStackInterface
{
    public private(set) array $middlewares = [];   // PHP 8.5 asymmetric visibility

    public function add(MiddlewareInterface $middleware): static;       // fluent
    public function prepend(MiddlewareInterface $middleware): static;   // fluent
    public function getMiddlewares(): array;
    public function createHandler(RequestHandlerInterface $fallback): RequestHandlerInterface;
}
```

`public private(set)` on `$middlewares` exposes the array for read-only inspection (tests, debug pages) while keeping mutation strictly through `add()` / `prepend()`.

🛡️ Trusted-host middleware
--------------------------

[](#️-trusted-host-middleware)

`TrustedHostMiddleware` is `final readonly` and takes a list of trusted hosts; matching is case-insensitive against `UriInterface::getHost()`. An empty list disables the check (DEV-only convenience). The middleware throws `\InvalidArgumentException` on missing or untrusted Host, which `ErrorHandlerMiddleware` converts to RFC 7807 `HTTP 400`.

🐘 PHP 8.5 features used
-----------------------

[](#-php-85-features-used)

- **Asymmetric visibility** (`public private(set) array $middlewares`).
- **`final readonly` middleware classes** so mounting them is side-effect-free.
- **`#[\Override]`** on every PSR-15 implementation method.

🧭 Architectural boundary (`mago guard`)
---------------------------------------

[](#-architectural-boundary-mago-guard)

An active dependency **perimeter** is enforced on every CI run by `vendor/bin/mago guard` (bundled into `composer mago`; zero baselines). The rules live in [`mago.toml`](./mago.toml) under `[guard.perimeter]` — a forbidden `use` statement fails the build, not a reviewer.

Production code under `Waffle\Commons\Pipeline` may depend **only** on:

- `Waffle\Commons\Pipeline\**` — itself
- `Waffle\Commons\Contracts\**` — the shared contracts package, the **only** Waffle dependency permitted
- `Psr\**` — PSR interfaces (PSR-7 / PSR-15 / PSR-17)
- `@global` + `Psl\**` — PHP core and the PHP Standard Library

Test code under `WaffleTests\Commons\Pipeline` is unrestricted (`@all`). Structural rules are guarded too: interfaces must be named `*Interface`, `Exception\**` classes must end in `*Exception`, and any `Enum\**` namespace may hold only `enum` declarations.

Contract-first, component-agnostic by construction: components compose through `waffle-commons/contracts`, never directly through one another.

🧪 Testing
---------

[](#-testing)

```
docker exec -w /waffle-commons/pipeline waffle-dev composer tests
```

📄 License
---------

[](#-license)

MIT — see [LICENSE.md](./LICENSE.md).

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance96

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~22 days

Recently: every ~5 days

Total

8

Last Release

21d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/34a7557a3fb23aaf788ca3892b9b7efdf96e753264bafd0599153c9e8a921316?d=identicon)[LesliePetrimaux](/maintainers/LesliePetrimaux)

---

Top Contributors

[![supa-chayajin](https://avatars.githubusercontent.com/u/695448?v=4)](https://github.com/supa-chayajin "supa-chayajin (66 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/waffle-commons-pipeline/health.svg)

```
[![Health](https://phpackages.com/badges/waffle-commons-pipeline/health.svg)](https://phpackages.com/packages/waffle-commons-pipeline)
```

###  Alternatives

[cakephp/cakephp

The CakePHP framework

8.9k19.5M1.8k](/packages/cakephp-cakephp)[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)[cakephp/authentication

Authentication plugin for CakePHP

1214.1M106](/packages/cakephp-authentication)[typo3/cms-core

TYPO3 CMS Core

3713.2M5.1k](/packages/typo3-cms-core)[cakephp/authorization

Authorization abstraction layer plugin for CakePHP

762.5M51](/packages/cakephp-authorization)[windwalker/framework

The next generation PHP framework.

25740.3k1](/packages/windwalker-framework)

PHPackages © 2026

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