Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
Agents
jacyimp/api-platform-rate-limiter
claude-code
cursor
symfony
throttling
laravel
api-platform
rate-limit
rate-limiter

This package prioritizes:

Install
php artisan boost:add-skill jacyimp/api-platform-rate-limiter

Save this content to: AGENTS.md

## Project Principles

This package prioritizes:

1. Clarity
2. Simplicity
3. Developer experience
4. Correctness
5. Extensibility only when justified

Do not add abstractions for hypothetical future needs. Prefer fewer concepts, fewer public types, fewer configuration steps, and conventional Symfony/API Platform or Laravel/API Platform behavior.

## Compatibility

Support:

- PHP 8.2+
- API Platform 3.4 / 4.x
- Symfony 6.4 / 7.x / 8.x
- Laravel 11.x / 12.x / 13.x through `api-platform/laravel`

Always consider lowest-supported dependencies and framework combinations, not only the locally installed versions.

## Public API

Keep the public API intentionally small.

Expected consumer-facing types include:

- `Metadata\RateLimit`
- `Metadata\BypassRateLimit`
- `Metadata\RateLimitPolicy`
- identity and condition metadata expressions
- dynamic value metadata
- resolver/provider/bypass contracts
- `Symfony\ApiPlatformRateLimiterBundle`
- Laravel package auto-discovery through `Laravel\LaravelServiceProvider`

Treat `Core`, API Platform adapters, framework listeners/middleware, DI/service-provider classes, storage adapters, resolvers, and orchestration classes as implementation details. Mark them `@internal` where appropriate.

Do not leak internal types through public extension interfaces.

## Design Rules

Prefer obvious APIs:

    new RateLimit(
        limit: 100,
        interval: '1 minute',
    );

Human-readable interval strings are the primary API. `DateInterval` is the programmatic alternative.

Inline rate limiting should work with no additional configuration after framework registration/package discovery.

Configured buckets may require central configuration.

Do not introduce builders, factories, interfaces, configuration objects, or framework abstractions unless they solve a real current problem.

Crawler detection and crawler verification do not belong in this package. Consumers can implement them through bypass rules.

## Architecture

Keep boundaries clear:

    API Platform metadata
        → extraction
        → resolution
        → enforcement
        → limiter/storage

Identity resolution and bypass checks are enforcement collaborators.

Do not pass API Platform `Operation` objects deep into the core.

Keep framework HTTP/container concerns in the Symfony and Laravel integration layers.

Multiple limits are consumed sequentially. Consumption from an earlier successful limit is not rolled back if a later limit rejects.

## Symfony

Default identity:

1. authenticated user identifier;
2. otherwise client IP.

Use Symfony trusted-proxy handling. Never manually parse `X-Forwarded-For`.

Security integration must remain optional.

Use `cache.app` for Symfony RateLimiter storage by default and keep package storage isolated from Symfony's generic storage aliases.

Avoid requiring users to manually configure internal services.

## Laravel

Default identity:

1. authenticated user identifier;
2. otherwise request IP.

Use Laravel's request/proxy handling. Never manually parse forwarded IP headers.

`api-platform/laravel` is the host integration. Keep Illuminate packages out of production requirements so Symfony consumers do not inherit Laravel's Symfony component constraints.

Register package middleware through API Platform's default operation middleware and rely on API Platform to populate `_api_operation`; do not reconstruct operation metadata from Laravel routes.

Keep package cache storage isolated from Laravel's global cache bindings.

## PHP Style

Every PHP file must contain:

    <?php

    declare(strict_types=1);

Follow PSR-12 and configured Slevomat rules.

Use:

- strict type hints;
- sorted imports;
- no unused imports;
- early returns;
- static closures where possible.

PHPStan runs at `level: max` with PHP 8.2 as baseline.

Prefer concrete intermediate variables over fragile long fluent chains when Symfony 6.4 typing requires it.

Avoid PHPStan suppressions unless narrowly justified.

## Tests

Use PHPUnit attributes.

Test methods:

- use `#[Test]`;
- start with `it...`.

Use `#[CoversClass(...)]` for unit tests with a clear SUT.

Prefer:

    self::createStub(...)
    self::createMock(...)

Use precise generic types for data providers, preferably `Generator`.

Test observable behavior rather than internal implementation details.

Kernel integration tests should exercise real Symfony wiring.

Laravel integration tests should use Testbench, and at least one CI path should exercise the real `api-platform/laravel` middleware contract.

Do not weaken tests or disable risky/deprecation detection to make CI pass.

## Commands

Before completing work:

    composer check
    composer audit

For dependency-sensitive changes:

    composer update --prefer-lowest --prefer-stable --no-interaction
    composer check

Then verify current dependencies:

    composer update
    composer check

Do not commit `composer.lock`.

CI covers PHP 8.2, 8.3, 8.4, 8.5, lowest dependencies, supported Symfony/API Platform consumer combinations, and Laravel/API Platform integration combinations.

## Documentation

Keep README onboarding minimal.

Show the simplest working example first, then advanced features.

Examples must reflect real implemented APIs.

Update README and CHANGELOG when public behavior changes.

## Scope Control

Solve the requested task and directly affected tests/docs only.

Do not prematurely add:

- atomic multi-limit consumption;
- distributed locking;
- crawler verification;
- remote IP-list fetching;
- speculative storage abstractions;
- unnecessary factories/interfaces.

## Commits

Use Conventional Commits:

    feat: ...
    fix(symfony): ...
    refactor(api): ...
    test: ...
    docs: ...
    chore: ...

Keep commits focused.

## Decision Rule

When several designs work, choose the one with:

- fewer concepts;
- clearer names;
- smaller public API;
- less framework leakage;
- less required configuration;
- easier debugging.

Prefer a little duplication over an abstraction that makes the package harder to understand.

Project Principles

This package prioritizes:

  1. Clarity
  2. Simplicity
  3. Developer experience
  4. Correctness
  5. Extensibility only when justified

Do not add abstractions for hypothetical future needs. Prefer fewer concepts, fewer public types, fewer configuration steps, and conventional Symfony/API Platform or Laravel/API Platform behavior.

Compatibility

Support:

  • PHP 8.2+
  • API Platform 3.4 / 4.x
  • Symfony 6.4 / 7.x / 8.x
  • Laravel 11.x / 12.x / 13.x through api-platform/laravel

Always consider lowest-supported dependencies and framework combinations, not only the locally installed versions.

Public API

Keep the public API intentionally small.

Expected consumer-facing types include:

  • Metadata\RateLimit
  • Metadata\BypassRateLimit
  • Metadata\RateLimitPolicy
  • identity and condition metadata expressions
  • dynamic value metadata
  • resolver/provider/bypass contracts
  • Symfony\ApiPlatformRateLimiterBundle
  • Laravel package auto-discovery through Laravel\LaravelServiceProvider

Treat Core, API Platform adapters, framework listeners/middleware, DI/service-provider classes, storage adapters, resolvers, and orchestration classes as implementation details. Mark them @internal where appropriate.

Do not leak internal types through public extension interfaces.

Design Rules

Prefer obvious APIs:

new RateLimit(
    limit: 100,
    interval: '1 minute',
);

Human-readable interval strings are the primary API. DateInterval is the programmatic alternative.

Inline rate limiting should work with no additional configuration after framework registration/package discovery.

Configured buckets may require central configuration.

Do not introduce builders, factories, interfaces, configuration objects, or framework abstractions unless they solve a real current problem.

Crawler detection and crawler verification do not belong in this package. Consumers can implement them through bypass rules.

Architecture

Keep boundaries clear:

API Platform metadata
    → extraction
    → resolution
    → enforcement
    → limiter/storage

Identity resolution and bypass checks are enforcement collaborators.

Do not pass API Platform Operation objects deep into the core.

Keep framework HTTP/container concerns in the Symfony and Laravel integration layers.

Multiple limits are consumed sequentially. Consumption from an earlier successful limit is not rolled back if a later limit rejects.

Symfony

Default identity:

  1. authenticated user identifier;
  2. otherwise client IP.

Use Symfony trusted-proxy handling. Never manually parse X-Forwarded-For.

Security integration must remain optional.

Use cache.app for Symfony RateLimiter storage by default and keep package storage isolated from Symfony's generic storage aliases.

Avoid requiring users to manually configure internal services.

Laravel

Default identity:

  1. authenticated user identifier;
  2. otherwise request IP.

Use Laravel's request/proxy handling. Never manually parse forwarded IP headers.

api-platform/laravel is the host integration. Keep Illuminate packages out of production requirements so Symfony consumers do not inherit Laravel's Symfony component constraints.

Register package middleware through API Platform's default operation middleware and rely on API Platform to populate _api_operation; do not reconstruct operation metadata from Laravel routes.

Keep package cache storage isolated from Laravel's global cache bindings.

PHP Style

Every PHP file must contain:

<?php

declare(strict_types=1);

Follow PSR-12 and configured Slevomat rules.

Use:

  • strict type hints;
  • sorted imports;
  • no unused imports;
  • early returns;
  • static closures where possible.

PHPStan runs at level: max with PHP 8.2 as baseline.

Prefer concrete intermediate variables over fragile long fluent chains when Symfony 6.4 typing requires it.

Avoid PHPStan suppressions unless narrowly justified.

Tests

Use PHPUnit attributes.

Test methods:

  • use #[Test];
  • start with it....

Use #[CoversClass(...)] for unit tests with a clear SUT.

Prefer:

self::createStub(...)
self::createMock(...)

Use precise generic types for data providers, preferably Generator.

Test observable behavior rather than internal implementation details.

Kernel integration tests should exercise real Symfony wiring.

Laravel integration tests should use Testbench, and at least one CI path should exercise the real api-platform/laravel middleware contract.

Do not weaken tests or disable risky/deprecation detection to make CI pass.

Commands

Before completing work:

composer check
composer audit

For dependency-sensitive changes:

composer update --prefer-lowest --prefer-stable --no-interaction
composer check

Then verify current dependencies:

composer update
composer check

Do not commit composer.lock.

CI covers PHP 8.2, 8.3, 8.4, 8.5, lowest dependencies, supported Symfony/API Platform consumer combinations, and Laravel/API Platform integration combinations.

Documentation

Keep README onboarding minimal.

Show the simplest working example first, then advanced features.

Examples must reflect real implemented APIs.

Update README and CHANGELOG when public behavior changes.

Scope Control

Solve the requested task and directly affected tests/docs only.

Do not prematurely add:

  • atomic multi-limit consumption;
  • distributed locking;
  • crawler verification;
  • remote IP-list fetching;
  • speculative storage abstractions;
  • unnecessary factories/interfaces.

Commits

Use Conventional Commits:

feat: ...
fix(symfony): ...
refactor(api): ...
test: ...
docs: ...
chore: ...

Keep commits focused.

Decision Rule

When several designs work, choose the one with:

  • fewer concepts;
  • clearer names;
  • smaller public API;
  • less framework leakage;
  • less required configuration;
  • easier debugging.

Prefer a little duplication over an abstraction that makes the package harder to understand.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource