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

ActiveLibrary[Framework](/categories/framework)

waffle-commons/contracts
========================

Contracts component for Waffle framework.

0.1.0-beta4(2w ago)15.8k16MITPHPPHP ^8.5CI passing

Since Nov 26Pushed 2w agoCompare

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

READMEChangelog (10)Dependencies (66)Versions (29)Used By (16)

[![demo](https://camo.githubusercontent.com/b30f41baece56d71f7f496f7e39fd33a2a096221c66c648b350dd4fe14276c2e/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f3735353238383030313539323033333339313f6c6f676f3d646973636f7264)](https://discord.gg/eKgywnfXr2)[![PHP Version Require](https://camo.githubusercontent.com/e85b98c53629965f7bbc35302434f8340df15706c1527620de5ee14e7e21d4e9/687474703a2f2f706f7365722e707567782e6f72672f776166666c652d636f6d6d6f6e732f636f6e7472616374732f726571756972652f706870)](https://packagist.org/packages/waffle-commons/contracts)[![PHP CI](https://github.com/waffle-commons/contracts/actions/workflows/main.yml/badge.svg)](https://github.com/waffle-commons/contracts/actions/workflows/main.yml)[![codecov](https://camo.githubusercontent.com/e5cc5a5cf2dee93f8e185515b6b1ddfec4fcebe2b65d55be55e2932e2b9364d0/68747470733a2f2f636f6465636f762e696f2f67682f776166666c652d636f6d6d6f6e732f636f6e7472616374732f67726170682f62616467652e7376673f746f6b656e3d64373461633632612d373837322d343033352d386238622d626363336166313939316530)](https://codecov.io/gh/waffle-commons/contracts)[![Latest Stable Version](https://camo.githubusercontent.com/dba7b1ddb95815d5f16d87658fb7d5a7eac576a52ef174d869ff895b2a0d55e5/687474703a2f2f706f7365722e707567782e6f72672f776166666c652d636f6d6d6f6e732f636f6e7472616374732f76)](https://packagist.org/packages/waffle-commons/contracts)[![Latest Unstable Version](https://camo.githubusercontent.com/aeaf4600d0e00f03277c92ed1db2a465fffe8529b75eb3de5cce00a06b33f9aa/687474703a2f2f706f7365722e707567782e6f72672f776166666c652d636f6d6d6f6e732f636f6e7472616374732f762f756e737461626c65)](https://packagist.org/packages/waffle-commons/contracts)[![Total Downloads](https://camo.githubusercontent.com/b40b51c95ec0421879cf922048dc995d2ff714a68d38ce06fc7256235e0c8ecb/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f776166666c652d636f6d6d6f6e732f636f6e7472616374732e737667)](https://packagist.org/packages/waffle-commons/contracts)[![Packagist License](https://camo.githubusercontent.com/413e466fe0f1772c94938e3ab77234c390b14203222e9ceff42c7ef3a0b923ea/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f776166666c652d636f6d6d6f6e732f636f6e747261637473)](https://github.com/waffle-commons/contracts/blob/main/LICENSE.md)

Waffle Contracts Component
==========================

[](#waffle-contracts-component)

> **Release:** `0.1.0-beta4` | [`CHANGELOG.md`](./CHANGELOG.md)

The Waffle Framework's central contract package. Every other `waffle-commons/*` component depends **only** on this package and on its declared PSR interfaces. No component may depend on a sibling's concrete implementation — `contracts` is the line that keeps the ecosystem decoupled.

This package contains interfaces, attributes, enums, exception interfaces, typed constants, and the small set of concrete routing exceptions (`RouteNotFoundException`, `MethodNotAllowedException`) shared across components. No business logic ever ships from here.

🆕 Beta-2 highlights — HTTP method correctness
---------------------------------------------

[](#-beta-2-highlights--http-method-correctness)

- **NEW** — `Waffle\Commons\Contracts\Routing\Exception\MethodNotAllowedException` (concrete `final` class) and its `MethodNotAllowedExceptionInterface` marker. Carries the allowed-methods list so downstream renderers can emit the RFC 7231 `Allow` header on `405` responses.
- **NEW** — `Waffle\Commons\Contracts\Routing\Constant`: HTTP-method string constants (`METHOD_GET`, `METHOD_POST`, `METHOD_PUT`, `METHOD_PATCH`, `METHOD_DELETE`, `METHOD_HEAD`, `METHOD_OPTIONS`).
- **CHANGED** — `Waffle\Commons\Contracts\Routing\Attribute\Route` (relocated from `waffle-commons/routing` in Beta-2): gained the `array $methods = ['GET']` parameter for method filtering and route overloading. Constructor argument order normalised so `$path` precedes `$methods`. Empty `methods` array means "any method".
- **NEW** — `Waffle\Commons\Contracts\Exception\WaffleExceptionInterface`: explicit base interface for the framework's exception hierarchy.

Beta-1 inheritance
------------------

[](#beta-1-inheritance)

The Beta-1 line introduced the security and HTTP-correctness foundations this package still carries:

- **BREAKING (Beta-1)** — `CsrfTokenManagerInterface::issue()`, `validate()`, `refresh()` take a `$sessionId` argument. The HMAC binds tokens to the per-browser `WAFFLE_SID` cookie issued by `AnonymousSessionMiddleware`.
- **NEW (Beta-1)** — `Waffle\Commons\Contracts\Security\Attribute\PublicAccess` — explicit opt-out for the fail-closed ABAC default. Without `#[Voter]` and without `#[PublicAccess]`, `SecureContainer::analyze()` denies with HTTP `403`.
- **NEW (Beta-1)** — `Waffle\Commons\Contracts\Routing\Exception\RouteNotFoundException` — concrete `final` class implementing `RouteNotFoundExceptionInterface`. Thrown by `CoreRoutingMiddleware` so missing routes render as `404` instead of `500`.
- **NEW (Beta-1)** — CSRF binding constants on `Waffle\Commons\Contracts\Security\Csrf\Constant`: `SESSION_COOKIE_NAME` (`WAFFLE_SID`), `SESSION_ID_BYTES` (`32`), `SESSION_REQUEST_ATTRIBUTE` (`_anon_sid`), `SESSION_COOKIE_MAX_AGE` (`2_592_000`), plus `MIN_SECRET_BYTES` (`32`) and `SECRET_ENV_KEY` (`WAFFLE_CSRF_SECRET`).

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

[](#-installation)

```
composer require waffle-commons/contracts
```

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

[](#-whats-inside)

NamespacePurpose`Waffle\Commons\Contracts\Attribute`Marker attributes (`#[Dto]`) consumed by the framework's argument resolver.`Waffle\Commons\Contracts\Cache`PSR-6 + PSR-16 extension interfaces (`CacheInterface`, `CacheItemPoolInterface`, `StampedeProtectionInterface`).`Waffle\Commons\Contracts\Config``ConfigInterface` typed getters (`getInt`, `getString`, `getArray`, `getBool`).`Waffle\Commons\Contracts\Console``ConsoleApplicationInterface`, `CommandInterface`, `InputInterface`, `OutputInterface`.`Waffle\Commons\Contracts\Constant\Constant`Ecosystem-wide typed constants (env names, security levels, attribute keys).`Waffle\Commons\Contracts\Container``ContainerInterface` extending PSR-11 + `ResettableInterface` for worker-mode resets.`Waffle\Commons\Contracts\Controller``BaseControllerInterface`.`Waffle\Commons\Contracts\Core``KernelInterface` — the heart of the request lifecycle.`Waffle\Commons\Contracts\Enum`Framework-wide enums (e.g. `Failsafe`).`Waffle\Commons\Contracts\ErrorHandler``ErrorRendererInterface` for content-negotiated error rendering.`Waffle\Commons\Contracts\EventDispatcher``EventDispatcherInterface`, `ListenerProviderInterface` (PSR-14 extension).`Waffle\Commons\Contracts\Exception`Root exception interfaces (`ValidationExceptionInterface`, etc.).`Waffle\Commons\Contracts\Handler``ArgumentResolverInterface`, `ResponseConverterInterface`.`Waffle\Commons\Contracts\Http`Framework-specific HTTP factories on top of PSR-7/17 (`GlobalsFactoryInterface`, `ResponseEmitterInterface`, `ServerRequestFactoryInterface`).`Waffle\Commons\Contracts\Parser``YamlParserInterface`.`Waffle\Commons\Contracts\Pipeline``MiddlewareStackInterface` (PSR-15 stack).`Waffle\Commons\Contracts\Routing``RouterInterface` + routing exception interfaces.`Waffle\Commons\Contracts\Runtime``RuntimeInterface` for FrankenPHP / classic SAPI bootstrap.`Waffle\Commons\Contracts\Security``SecurityInterface`, `SecurityRuleInterface`, `VoterInterface` + `#[Voter]` / `#[Rule]` attributes + CSRF attributes.`Waffle\Commons\Contracts\Service``ResettableInterface` — implemented by any service that needs reset between FrankenPHP worker requests.`Waffle\Commons\Contracts\System``SystemInterface`.`Waffle\Commons\Contracts\Validation``ValidatorInterface`, `ValidationResultInterface`, `ViolationInterface`.🐘 PHP 8.5 surface
-----------------

[](#-php-85-surface)

The contracts package is the canonical reference for the framework's PHP 8.5 contract style:

- **Typed constants** everywhere — `public const string EVENT_NAME = '...';`, `public const int SECURITY_LEVEL10 = 10;`.
- **Marker attributes** with `Attribute::TARGET_*` declarations (`#[Dto]`, `#[Voter]`, `#[Rule]`).
- **`final readonly class`** for value-object attributes.
- All return types and parameter types are explicit; no `mixed` in the public surface except where PSR-11 mandates it (`ContainerInterface::get(): mixed`).

📐 Sample interfaces
-------------------

[](#-sample-interfaces)

`KernelInterface` — the heart of the framework:

```
namespace Waffle\Commons\Contracts\Core;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

interface KernelInterface
{
    public function boot(): static;
    public function configure(): void;
    public function handle(ServerRequestInterface $request): ResponseInterface;
    public function reset(): void;
}
```

`ConfigInterface` — typed config access:

```
namespace Waffle\Commons\Contracts\Config;

interface ConfigInterface
{
    public function getInt(string $key, ?int $default = null): ?int;
    public function getString(string $key, ?string $default = null): ?string;
    public function getArray(string $key, ?array $default = null): ?array;
    public function getBool(string $key, ?bool $default = null): ?bool;
}
```

`#[Dto]` — marker attribute for auto-hydrated DTOs:

```
namespace Waffle\Commons\Contracts\Attribute;

use Attribute;

#[Attribute(Attribute::TARGET_CLASS)]
final readonly class Dto {}
```

A DTO consumer in your controller:

```
use Waffle\Commons\Contracts\Attribute\Dto;
use Waffle\Commons\Contracts\Exception\Validation\ValidationExceptionInterface;

#[Dto]
final readonly class UserLoginDto
{
    public string $email {
        set(string $value) {
            if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
                throw new \DomainException('Invalid email');
            }
            $this->email = $value;
        }
    }
}
```

🤝 Decoupling rule
-----------------

[](#-decoupling-rule)

Every concrete waffle-commons component **must** depend on `waffle-commons/contracts` and on nothing else from the `waffle-commons/*` namespace, unless explicitly declared in its own `composer.json require`. This rule is enforced at build time by `mago guard` perimeters in every component.

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

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

`contracts` is the **root** of the ecosystem, so its own perimeter (enforced by `vendor/bin/mago guard`, bundled into `composer mago`, zero baselines — see [`mago.toml`](./mago.toml) `[guard.perimeter]`) is the strictest of all: production code under `Waffle\Commons\Contracts` may depend **only** on:

- `Waffle\Commons\Contracts\**` — itself
- `Psr\**` — PSR interfaces
- `@global` + `Psl\**` — PHP core and the PHP Standard Library

It depends on **no other `waffle-commons/*` package** — that is what lets every other component depend on it without creating a cycle. Test code under `WaffleTests\Commons\Contracts` 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 (see the [Decoupling rule](#-decoupling-rule) above for the ecosystem-wide counterpart).

🧪 Testing
---------

[](#-testing)

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

📄 License
---------

[](#-license)

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

###  Health Score

50

—

FairBetter than 95% of packages

Maintenance96

Actively maintained with recent releases

Popularity26

Limited adoption so far

Community20

Small or concentrated contributor base

Maturity49

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 ~7 days

Total

10

Last Release

19d ago

PHP version history (2 changes)0.1.0-alpha1PHP ^8.4

0.1.0-alpha4PHP ^8.5

### 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 (88 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[symfony/symfony

The Symfony PHP framework

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

The PHP framework that gets out of your way.

2.2k34.4k15](/packages/tempest-framework)[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)[typo3/cms-core

TYPO3 CMS Core

3713.2M5.1k](/packages/typo3-cms-core)[windwalker/framework

The next generation PHP framework.

25740.3k1](/packages/windwalker-framework)

PHPackages © 2026

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