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

Doorman Laravel Package

clarkeash/doorman

Doorman adds secure passwordless magic-link authentication to Laravel. Generate signed login links by email, set expiry and usage limits, invalidate links, and integrate with Laravel's auth guard for simple, low-friction sign-in.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • Doorman remains an access-gate package, not an auth system: it layers a redeemable access-code check in front of routes via middleware, plus a Doorman facade (generate, redeem, check) and Eloquent-backed storage. This is an additive, non-invasive architectural fit for a standard Laravel monolith — it does not touch guards, providers, or session drivers.
  • Correct mental model is "invite-only / private-beta allowlist," not "authentication." It coexists cleanly with Breeze/Jetstream/Fortify and should be sequenced alongside them rather than instead of them.
  • It fits two distinct product patterns: (a) gate the entire app behind a code, or (b) gate only registration (invite-code signup). Pattern (b) is the lighter-touch, lower-risk integration and the one I would default to.
  • It does not naturally fit a stateless/API-first architecture. Session-based gating has no meaningful analogue for token-authenticated requests; an API deployment requires a custom redemption endpoint and a persistence decision (bind code to user record vs. token metadata).

Integration feasibility

  • Friction is low: composer require, publish config and migrations, migrate, register the middleware alias, attach to a route group, and build a redemption controller/view. There are no service dependencies (no Redis, no queue, no external API).
  • The package ships the engine, not the product surface: no admin CRUD, no onboarding emails, no reporting. Budget real effort for the code-lifecycle tooling around it.
  • Front-end work is non-trivial relative to package size — a redemption form, error states (invalid/expired/exhausted), and post-redemption redirect behavior all belong to us.

Technical risk

  • Unassessable v11.0.0 release (new). The release is published as a major version bump with no changelog or release notes content supplied. A major semver bump is presumptively breaking by convention, and the version number aligns with the wider Laravel ecosystem habit of version-matching the framework — which typically signals a moved framework/PHP support floor. Neither the breaking changes nor the new support matrix can be confirmed from the release as published. Treat this as a verification gate, not an adoption decision: until we have diffed composer.json and the published config/migration between our pinned version and v11, we do not know what we are upgrading into.
  • Framework support floor may have moved. The assessment previously characterised fit as "Laravel 9–12 era, PHP 8.x." A v11-aligned release plausibly narrows that window (and could drop older Laravel/PHP combinations). If our target app is on an older major, v11 may be unusable; if it is on the newest, older pinned versions may already be out of the maintainer's test matrix. This must be read off the package's own constraints, not inferred.
  • Concurrency on use-count decrement. Per-code and per-user usage limits imply a read-modify-write on a counter. Under concurrent redemptions this can over-issue. Validate whether the implementation uses a transaction with row locking; if not, wrap redemption in our own transactional boundary and add a unique constraint as a backstop. Re-verify on v11 — this is exactly the class of behaviour a major bump may have rewritten.
  • No first-class rate limiting. Short alphanumeric codes are enumerable. The redeem endpoint must sit behind Laravel's throttle middleware, and code length/entropy config must be reviewed rather than left at defaults.
  • Plaintext code storage. Access codes are effectively credentials. If codes grant anything beyond a landing page, consider hashing at rest or accepting the risk explicitly with a documented rationale.
  • No user binding by default. A code is a bearer token; sharing is the expected failure mode. If per-seat or per-org control matters, we need to add the association ourselves.
  • Middleware placement is a silent-failure surface. A route registered outside the protected group is simply open. This must be covered by an explicit route-coverage test, not by review.
  • Bus factor. Single-maintainer package, dependents: 0. The zero-dependents figure is expected for an application-level package and is not an adoption signal; the ~1k stars are the better indicator. Still, there is no vendor SLA — and a major release shipped without notes is a concrete illustration of the communication risk rather than a hypothetical one.

Key questions

  1. What is actually in v11.0.0, and which Laravel/PHP versions does it support? Answer by diffing the repo against our pinned tag — not from the release page, which is empty.
  2. Do we adopt v11 or pin to the prior major? Default to pinning the version we have validated unless v11 delivers something we need. A major bump with no notes is not a reason to move.
  3. Is the gate on the whole app or on registration only? This decision drives most of the integration cost.
  4. Do redemptions need to be bound to a user/org, and does a code need to be revocable per-user after the fact?
  5. What is the failure posture if the database or session store is unavailable — fail open (open the app) or fail closed (lock everyone out)? Default must be explicit, not inherited.
  6. Is there an audit requirement (who redeemed what, when)? The package's timestamps are unlikely to satisfy compliance review on their own.
  7. Do we need stateless API access in the next 12 months? If yes, plan a custom layer now rather than retrofitting.
  8. What is the expected redemption QPS at launch? This determines whether counter contention is a real concern or theoretical.

Integration Approach

Stack fit

  • Laravel 9–12 era on the prior major; v11.0.0's supported matrix is unconfirmed and must be established before it is used as the baseline. Standard Composer install either way. Ideal target is a modular monolith or a single Laravel app with server-rendered (Blade/Livewire/Inertia) surfaces.
  • Poor fit for headless backends serving mobile/SPA clients over tokens without a custom persistence layer. Flag this before committing.
  • No infrastructure footprint: one table, one config file, one middleware. Deployable to any environment that already runs the app.

Migration path

  1. Pin explicitly and immediately. Use a tight constraint for whichever major we validate (^10.x or ^11.0, not ^10|^11). Do not let a floating constraint silently pull a major we have not tested.
  2. Resolve the v11 delta before any install: read the tag's composer.json for Laravel/PHP constraints, diff config/ and the migration against the pinned version, and skim the diff for changes to redemption, limits, or middleware registration. Record the finding in the ticket — the release notes will not supply it.
  3. composer require clarkeash/doorman, publish config and migrations, review the published migration for indexes on the code column. Re-review if upgrading rather than greenfield, since published assets are not automatically republished.
  4. php artisan migrate in staging only; confirm rollback works before production. For an upgrade, confirm the migration is additive.
  5. Register the middleware alias and attach it to the narrowest route group that satisfies the requirement — prefer the registration route over the whole app for the first pass.
  6. Build the redemption controller and view; wire post-redemption redirect into the existing onboarding flow.
  7. Seed a small batch of codes and run an end-to-end pass in staging, including invalid, expired, and exhausted paths — plus the concurrency test, which must be re-run on v11 rather than inherited from prior results.
  8. Ship behind a config/env feature flag so the gate can be disabled without a redeploy.

Compatibility

  • Coexists with all standard auth scaffolding. Ordering matters: if gating registration, the code check must run before the user is created; if gating the app, it should run after auth so codes can be attributed to a user.
  • Session driver compatibility should be confirmed against whatever we run in production (cookie, Redis, database). Multi-node deployments require a shared session store or the gate will behave inconsistently across instances.
  • No conflict expected with Laravel's built-in auth, verified, or throttle middleware; stack throttle outside Doorman on the redeem route.
  • Upgrade-specific: if we are already running the package, the constraint conflict will surface at composer update, not at runtime. Run the upgrade on a branch and let the full test suite plus the route-coverage test arbitrate.

Sequencing

  • Phase 0 (new, ~half a day): resolve the v11 delta — constraints, config/migration diff, changelog archaeology. This gates everything else and is cheap.
  • Phase 1 (PoC, ~1–2 days): install, protect one route in staging, prove redeem/check/limit behavior including a concurrency test.
  • Phase 2 (decision gate): choose app-wide vs. invite-only registration, session-gate vs. user-bound, and v11 vs. pinned prior major. These choices are cheap now and expensive later.
  • Phase 3 (~3–5 days): ops tooling — generate/revoke/list codes, usage reporting — plus rate limiting, tests, and error-state UI.
  • Phase 4: integrate with transactional email for code delivery and with whatever onboarding analytics we run.
  • Phase 5: production rollout behind the flag, staged by traffic percentage or by cohort.

Operational Impact

Maintenance

  • Very low ongoing cost: small dependency surface, no runtime services, stable public API. Pin the version in composer.json and review releases on a quarterly cadence rather than continuously — but note that "review releases" now requires reading the repository, since the release channel carried no information for v11.0.0.
  • Changelog hygiene is a standing operational task, not a one-off. If the maintainer does not publish notes for majors, our upgrade process must assume we are the ones producing the diff. Budget a recurring half-day per major release and keep a short internal upgrade note so the next engineer is not starting cold.
  • Single-maintainer project. Treat the effective maintenance plan as "we own it": MIT plus roughly a few hundred lines of logic means vendoring or forking is a viable escape hatch if maintenance lapses. This remains the main reason the package's low opportunity score is not a blocker — we are consuming a commodity, not betting the roadmap on it.
  • A major release is evidence the project is alive; silence on its contents is evidence the bus factor is real. Both are consistent with the prior assessment and neither changes the recommendation.

Support

  • No commercial support, no SLA. Internal ownership is required from day one: a named owner, a runbook covering code generation, revocation, and "everyone is locked out" recovery.
  • Support burden concentrates in one place — the redemption funnel. Instrument it (attempts, failures by reason) so support tickets can be diagnosed without database access.

Scaling

  • Load is negligible: one indexed read per gated request plus one write per redemption. This will not be a bottleneck at any plausible scale for an invite gate.
  • The one scaling caveat is a hot row: a single high-traffic code with a usage counter will serialize writes under row locking. Use many codes, not one shared code, and cap per-code usage to keep contention bounded.
  • Session store scaling matters more than Doorman itself — multi-region or multi-node deployments need a shared session backend or redemption state will appear to "forget" users on some requests.

Failure modes

  • Database unavailable → gate behavior is determined by exception handling; decide fail-open vs. fail-closed deliberately and test both. For a private beta, fail-closed is usually correct.
  • Session loss or eviction → users are re-prompted for a code they already redeemed. Mitigate by binding redemption to the user record once authenticated, not only to the session.
  • Middleware misordering or route misregistration → silently unprotected routes. Cover with an automated test that asserts unauthenticated access to protected paths is blocked.
  • Undocumented major upgrade → silent behaviour change in limit enforcement or route protection. The empty v11.0.0 notes make this the most likely failure mode of the upgrade itself; mitigated by the Phase 0 diff and by re-running the concurrency and route-coverage tests against the new version rather than trusting prior results.
  • Code exhaustion / accidental mass revocation → lockout. Require a bulk-generate path and a tested break-glass procedure (env flag to disable the gate).
  • Redeem endpoint abuse → code enumeration. Mandatory throttle plus alerting on failure-rate spikes.
  • Counter race → over-redemption beyond configured limits. Mitigated by transaction + unique constraint, verified by a concurrency test rather than by inspection.

Ramp-up

  • For a Laravel-fluent engineer: roughly half a day to a working gate in staging, 1–2 days to something defensible in production with tests and rate limiting. Add half a day for the v11 delta investigation if we adopt the new major.
  • Add 3–5 days for the surrounding product surface (admin tooling, email delivery, error-state UX, audit logging) — this, not the package, is the real cost line.
  • Conceptually shallow: no new mental model beyond "middleware + one table." Onboarding cost is close to zero, and the knowledge is transferable because the implementation is thin enough to read end to end in an hour — which is also the mitigation for the missing release notes.
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.
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
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core