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

Laravel Nemesis Laravel Package

andydefer/laravel-nemesis

Laravel Nemesis is a lightweight Laravel package by andydefer that installs via Composer and registers through a service provider, adding configurable functionality to your app. Early-stage project with limited adoption—check the source and docs before production use.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and publish:
    composer require <vendor>/nemesis   # confirm vendor from Packagist
    php artisan vendor:publish --tag=nemesis-config
    php artisan migrate
    
  2. Create your first token for a consumer (e.g. a mobile app or partner domain):
    php artisan nemesis:create --domain=partner.example.com --name="Partner API"
    
    Capture the plaintext token once — it is typically not recoverable afterwards.
  3. Protect a route group with the auto-registered nemesis middleware alias:
    Route::middleware('nemesis')->prefix('api/v1')->group(function () {
        Route::get('/orders', [OrderController::class, 'index']);
    });
    
  4. Where to look first:
    • config/nemesis.php — token extraction sources, quota defaults, CORS behaviour, header names.
    • The package's NemesisServiceProvider — confirms the middleware alias and whether the alias can be overridden.
    • The token model/migration — the authoritative list of per-token columns (domain, quota, used count, blocked flag, CORS origins).
    • php artisan nemesis:list — fastest way to verify the package is wired up and see live quota state.

First use case: drop the middleware on an existing internal API, create one token per consuming domain, and watch nemesis:list for a week before enabling blocking behaviour in production. That gives you real traffic shape before quotas start returning errors.

Implementation Patterns

One token per domain, not per user. The package's unit of control is the domain. Model your issuance around consumers: web-app, mobile-ios, partner-acme. This makes nemesis:block a clean kill switch for a single integration without touching the others.

Route group layering. Place nemesis on the API group, then layer authorisation on top:

Route::middleware(['nemesis', 'auth:sanctum'])->group(...);

Nemesis answers "is this caller allowed to call at all and within quota"; auth answers "who are they". Keeping those separate avoids conflating rate-limits with user identity.

Quota lifecycle. The package blocks automatically when the counter is exhausted. Plan the reset explicitly:

// routes/console.php (Laravel 11+) or app/Console/Kernel.php
Schedule::command('nemesis:reset')->dailyAt('00:00');

Pick a reset cadence that matches your quota window semantics, and confirm whether nemesis:reset clears all tokens or accepts a --domain/--token filter.

Decommissioning vs. blocking. Prefer nemesis:block over deleting a token when a client misbehaves — it preserves the row for audit and is reversible with nemesis:unblock. Reserve deletion for genuinely retired integrations.

Issuance in code. Rather than shelling out to Artisan from a controller, wrap issuance in a small service that calls the package's model/repository directly. Your admin UI then has one seam to swap if the package's API shifts, and you can attach your own metadata alongside.

Query-param extraction as a compatibility path. Use the ?token=-style fallback only for callers that cannot set headers (legacy webhooks, some embeddable clients). For everything else enforce Authorization: Bearer.

Testing. Create tokens in setUp() (or a factory if one ships), then assert the three distinct failure shapes your clients will see: missing/invalid token, blocked token, quota exceeded. Catching these in tests is the cheapest way to pin down the exact status codes you are committing to.

Gotchas and Tips

  • Query-param tokens leak. Tokens in URLs land in access logs, proxy logs, Referer headers, and browser history. If you enable that extraction path, scrub the parameter in your logging middleware and never enable it on routes reachable from a browser.
  • CORS double-handling. The package manages CORS per token, but Laravel's HandleCors and config/cors.php (or fruitcake/laravel-cors on older apps) also emit headers. Two sources means duplicated or contradictory Access-Control-Allow-Origin headers, which browsers reject outright. Pick one owner per route group and verify with curl -I -H "Origin: ...".
  • Middleware ordering. nemesis runs before or after HandleCors depending on registration; a 401/403 from Nemesis that lacks CORS headers shows up in the browser as an opaque CORS error, not the real failure. Order Nemesis after CORS so error responses stay readable to browser clients.
  • Alias collisions. "Automatically registered" is convenient but means a pre-existing nemesis alias (or one you add later) will conflict silently. Check bootstrap/app.php / Kernel::$middlewareAliases after install.
  • Counter increment under load. v1.0.0 calls out an optimised increment. Confirm it is an atomic DB increment (increment() / UPDATE ... SET used = used + 1) rather than read-modify-write; the latter overshoots quotas under concurrency. Worth a quick parallel-request test before you trust the blocking.
  • Domain matching edge cases. Whether example.com matches www.example.com, non-default ports, http vs https, and Origin vs Host header are all decisions the package makes for you. Test each case your real clients use — subdomain mismatches are the most common false 403.
  • Reset must be scheduled, or quotas never recover. A blocked token with no scheduled reset is blocked forever. Add the schedule entry in the same PR that enables quotas, and alert if nemesis:list shows tokens pinned at 100%.
  • Distinguish your error codes. Make sure clients can tell 401 (bad token) from 403 (blocked) from 429 (quota). If the package returns one code for all three, normalise it in your exception handler so client retry logic isn't guessing.
  • Config caching. After editing config/nemesis.php in a deployed environment, run php artisan config:cache — long-lived config caches are a classic "my change did nothing" source.
  • Read the cleanup/uninstall path before you need it. The release notes mention an optimised cleanup and uninstall process. Know exactly which tables/columns and config keys get removed so a future package swap doesn't strand data — and take a backup before running it in production.
  • v1.0.0 is a stability signal. The public surface (command signatures, config keys, middleware name) is now semver-committed; pin ^1.0 and read the changelog on minor bumps for new config defaults.

Extension points worth checking on day one: custom middleware subclassing for bespoke error responses, model swapping (if the package binds an interface), and any events fired on block/quota-exceeded — those events are the natural hook for alerting (Slack/PagerDuty) and for audit logging, and they're cheaper than polling nemesis:list.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib