edgrosvenor/tupleauth
TupleAuth adds tuple-based, relationship-driven authorization to Laravel. Define access as subject-relation-object tuples, then check permissions through familiar Gates and Blade directives without building complex role hierarchies.
Basis of this assessment. Package metadata, the description, the single 0.1.3 release note, and the repository state (archived, last release October 2019, one star, MIT). No composer.json, source, README, or CI configuration was supplied. Conclusions are conditional and should be re-validated against the actual manifest before any decision that costs money.
What this package actually is. edgrosvenor/tupleauth is an authorization library that models access as subject–relation–object tuples (the Zanzibar/ReBAC pattern) and surfaces the result through Laravel's native Gate and route middleware APIs. The commercial proposition is not "new auth features" — Laravel already has Gates and policies — it is expressiveness: replacing scattered if ($user->hasRole('admin')) checks with a declared relationship graph that supports hierarchies and relationship traversal. The relevant comparison set is therefore Spatie Permission (role-centric), Laravel Gates/policies (verb-centric), Casbin/OPA (external policy engines), and build-your-own.
Architecture fit. Two things dominate. First, it plugs into the Laravel abstractions a team already uses — Gate, policies, middleware, a service provider, publishable config. That is a genuinely low-ceremony shape and, importantly, it is reversible: if the library is replaced, the call sites (Gate::allows, ->can() in Blade, can: middleware) survive. Second, it is pre-1.0 and now archived, which means the public API is frozen rather than stabilized, and there is no upgrade path forward. Fit is best where the authorization model genuinely needs graph traversal (hierarchical orgs, document/folder inheritance, delegated access) and where the app is on a Laravel version the 2019 code actually runs on. Fit is worst for anything on a current Laravel major, and worse for anything where authorization is a security boundary rather than a UX convenience.
Integration feasibility. Mechanically trivial: composer require, provider auto-discovery or manual registration, publish config, define tuples, call Gate. That is a spike measured in hours, not weeks — which is the main argument for evaluating it at all despite the signals. The friction is not installation, it is verification. A 2019 package against a 2025 framework will hit removed helpers (str_*/array_* to Str::/Arr::), changed service-provider and container semantics, facade and event signature drift, and possibly PHP 8 typed-property and nullability incompatibilities. Whether those are one-line fixes or a rewrite is unknown without reading the source — and reading the source is a task you are assigning to an engineer, not something you can infer from a release note.
Technical risk, ranked by business consequence.
Key questions to put to engineering before any commitment.
Gate/Gate::before/policy contracts, or does it monkey-patch the auth internals? Standard contracts mean cheap replacement; internals mean lock-in.Stack fit and the abstraction rule. The package's value to a TPM is contingent on one engineering discipline: do not call it directly from controllers, Blade templates, jobs, or API resources. Wrap it behind an application-owned interface — an AuthorizationService contract, or a small set of policies that delegate internally. If that discipline holds, the library is an implementation detail and its archived status is a moderate risk rather than a strategic one. If it does not hold, it becomes a dependency you cannot remove without a cross-cutting refactor, which is precisely the state a TPM exists to avoid.
Decision framing: three viable postures.
path repository, pin it, add it to your own test suite, and accept ownership. Justified only if the source is small, the target Laravel is old (5.x–8.x, PHP 7.x), and the graph semantics are non-trivial enough to be costly to rebuild. MIT makes this clean. Budget for a security review and a written maintenance owner.If the team is already on a current Laravel major, posture one is the only one that makes sense — the package cannot be made to run without work you would rather spend on the reimplementation.
Migration path and sequencing.
0.1.3 tag if supported; otherwise reimplement the tuple evaluator natively. Exercise one real authorization scenario end to end, including a denied case. Commit the lock file and diff the dependency graph.AuthorizationService interface and the tuple/config schema regardless of which implementation wins. This is the artifact that outlives the library.Compatibility discipline. Pin the exact version, never a caret range — 0.x permits breaking changes on any bump, and a published bump here will never come anyway. Verify the PHP floor independently of the Laravel floor; an old Laravel major implies an old PHP minor, and that may conflict with the rest of your estate.
Maintenance and ownership. Archived means the maintenance burden transfers to you in full, and it does so immediately, not on some future date. Someone must own the code, review it against Laravel upgrade notes each time the framework moves, and hold a fork or patch layer if you vendored. Budget this as a standing line item, not a one-off integration cost — an unowned authorization dependency is how a team ends up unable to upgrade Laravel for two years because one package blocks the path. That outcome is the exact inverse of the benefit advertised in the 0.1.3 release note, and it is the most likely long-run consequence of adopting this as a live dependency.
Support. There is none, and there will be none. No maintainer triage, no security advisories, no issue responses, no documentation beyond a short description and a one-line changelog per release. For a normal utility package that is survivable; for an authorization package it means the integrating team is the de facto security team for that code path. Plan for the team's own tests to be the only safety net, and for the source to be the only documentation.
Scaling. The package is described as having "no external services," which is operationally attractive — no new datastore, no sidecar, no network hop on the request path. Assuming in-process evaluation against config-defined tuples, per-request cost is likely a function of tuple count and hierarchy depth, which means scaling risk is really model risk: tuple sets that grow with tenants, resources, or users can make evaluation slower and, worse, harder to reason about. The engineering task during the spike is to bound the tuple set for the largest tenant and confirm evaluation stays flat per request. If the alternative considered is OPA or another external engine, note this package trades that operational surface for zero infrastructure — a real, if modest, advantage.
Failure modes, ranked.
true where it should return false. Highest cost because it is quiet and it is a security event. Mitigate with explicit deny-case tests on every supported version pair, not just the happy path.Ramp-up. Low technical ramp — a Laravel-fluent engineer is productive against Gate and middleware in half a day, because the API surface is familiar by design. The real ramp is conceptual and organizational: understanding the tuple/relationship model well enough to design a correct schema (which is where authorization systems actually fail), and absorbing the governance overhead of an unmaintained dependency on a security boundary. Assign the evaluation to an engineer, treat their written comparison as the gate on the decision, and do not let the appeal of the tuple model substitute for answering the question of whether the business needs it.
Bottom line for the roadmap. This is not a package to adopt; it is a package to read. The tuple-based authorization pattern is worth an afternoon of an engineer's time as a design input, and the MIT license makes lifting the approach straightforward. The code itself is archived, pre-1.0, single-author, adopted by essentially nobody, and sits on the authorization path — which is the one place where "unmaintained" is not an acceptable risk posture. If relationship-based access control is a genuine roadmap requirement, budget for a native implementation behind an owned interface, or evaluate a maintained alternative; treat this repository as a reference implementation and a source of vocabulary, not a dependency, and make that decision explicit in the ADR so the reasoning survives staff turnover.
How can I help you explore Laravel packages today?