hasinhayder/tyro
Tyro is a lightweight Laravel package by Hasin Hayder for role and permission management. It lets you assign roles and permissions to users, protect routes with middleware, and use simple Blade directives—all through a clean, familiar Laravel API.
Architecture fit. Tyro targets a well-defined slot in the Laravel ecosystem: application-layer authorization on top of Sanctum. It is not an identity provider and not a replacement for Sanctum token issuance — it is a policy/privilege engine that consumes the authenticated user. That makes it a clean fit for teams already standardizing on Laravel 12/13 + Sanctum and looking to replace ad-hoc Gate/Policy sprawl or hand-rolled roles/permissions tables. The explicit separation between roles, permissions, and system-level privileges (plus suspensions, inheritance, and multi-tenancy) is a meaningful architectural statement: it means the package authors expect non-trivial enterprise RBAC, not just a HasRoles trait. The presence of a documented extension-point convention (configurable table names, model classes, drivers, resolvers, providers) is the strongest signal for TPM buy-in — it indicates the maintainers have designed for substitution rather than fork-on-first-friction.
Integration feasibility. High, with caveats. The package ships migrations, seeders, config, Artisan commands, middleware, Blade directives, and event contracts. A greenfield Laravel 12 app can integrate in a day. A mature app with existing roles/permissions tables faces a data migration and a permission-naming reconciliation problem: Tyro enforces its own naming conventions (tyro:user-{userId}:roles cache keys, {entity}.{action} audit events, tyro:{entity}-{action} commands, snake_case config), and the skill explicitly states "Consistency is more important than theoretical perfection." That is a healthy engineering stance but also a hard boundary — teams hoping to bend Tyro to their existing conventions will fight the framework. The Sanctum dependency is a strength (no parallel auth stack to defend) but also means the package inherits Sanctum's token lifecycle, revocation semantics, and SPA/CSRF posture.
Technical risk. Enumerate honestly:
hasinhayder) is the dominant risk. Laravel 12/13-only support means the package is ahead of the ecosystem — good for adopters who upgrade aggressively, risky for LTS-conscious enterprises.tyro:user-{id}:roles, :privileges) is a correctness-critical surface. Stale cache after a role change is a silent privilege-escalation or privilege-denial bug. The skill exposes invalidation, warming, and consistency rules, which is reassuring, but every integration must be audited for cache-flush-on-write completeness across its own mutation paths (admin UIs, support tooling, direct DB writes).privileges.md and security.md rule files exist specifically because this is the highest-severity failure mode: break-glass access, system privileges, inheritance chains. Any custom resolver or driver added on top must be reviewed against escalation invariants.backward-compatibility.md rule file and "public APIs consumed by Tyro Login and Tyro Dashboard" note confirm this is a platform, not a utility. That raises the cost of upgrading but also suggests coordinated releases.audit_logs table with an UPDATE grant is not an audit log.Key questions for the maintainer / spike team.
Policy allow/deny?Stack fit. Best fit is a Laravel 12/13 application with: Sanctum already in place (or willing to adopt it), a Postgres/MySQL primary, Redis for cache and queue, and an existing admin surface that can be rebuilt around Tyro's Artisan commands + REST endpoints. Worst fit is a Laravel 10/11 legacy app, a team with a deeply entrenched custom RBAC model, or an environment that disallows schema additions to the users table. The presence of Blade directives and middleware also implies the package expects to own the UI-layer authorization story — teams with a bespoke frontend permission model will need a translation layer.
Migration path. Sequence it as a strangler-fig, not a big bang:
Gate/Policy bridge so authorization calls resolve through Tyro but fall back to legacy on exception. Gate rollout by route group, starting with read-only admin surfaces, then write operations, then destructive operations last.security.md and inheritance.md contracts. This is not optional.Compatibility. Pin the composer constraint to a caret range on the minor version, not dev-main. Track Laravel 13 support explicitly in the dependency review — the package advertises 12 & 13, but "advertised" and "tested in our CI" are different claims. Confirm PHP version parity with your runtime. Validate Sanctum version compatibility (v4 vs v3 semantics differ on token abilities vs. permissions — do not conflate them). If the app already runs Sanctum, no auth-stack migration is needed; if it does not, budget a Sanctum adoption sprint before Tyro, not during.
Sequencing across the portfolio. If multiple product teams share the codebase, sequence the migration at the authorization boundary (the Gate facade and middleware registration), not per-team. Centralize the Tyro config in a shared internal package so config/tyro.php drift between teams is impossible. Publish an internal "Tyro conventions" doc that mirrors the skill's naming rules — new engineers should not learn from the upstream repo directly, they should learn from your internalized version.
Maintenance. The package is small enough to audit but large enough to own. Expect one engineer, part-time, to: monitor upstream releases and CVEs, run quarterly upgrade rehearsals against the next Laravel LTS, own the config/tyro.php and cache-key conventions, and review any custom resolvers/drivers/providers. The skill's "Consistency First" mandate is operationally valuable if your team codifies it — otherwise it becomes tribal knowledge and the first non-conforming PR starts the slow fork. Recommend: an internal CONTRIBUTING-style Tyro conventions page, a lint rule for Artisan command naming, and a code-owner rule on the HasinHayder\Tyro namespace imports.
Support. Two support surfaces: (1) upstream, which is a solo-maintainer OSS project — assume best-effort, no SLA, and no guaranteed CVE turnaround; (2) internal, which is your own admin tooling, runbooks, and incident playbooks. Build an internal runbook covering: how to grant break-glass access, how to revoke all sessions for a user, how to invalidate a specific user's privilege cache, how to replay a permission assignment from the audit log, and how to export the audit log for a compliance request. The CLI is a strong operational asset here — tyro:sys-* and tyro:auth-* commands reduce the need for ad-hoc SQL during incidents — but the team must be drilled on them before the incident, not during it.
Scaling. Authorization is on the hot path for every authenticated request. Two scaling axes matter:
Audit logging is append-only and will grow monotonically; budget partitioning, cold-storage archival, and retention policy from day one. Multi-tenant deployments must be benchmarked per-tenant on the scoped-permission path, not globally.
Failure modes. In rough severity order:
{entity}.{action} events is an invisible insider-threat surface. Mitigation: enforce event emission at the model observer layer, not the controller layer, and test that every mutating command emits exactly one event.Ramp-up. Plan for a 2–3 week productive ramp for a mid-level Laravel developer, contingent on three investments: (a) a 90-minute internal orientation covering Sanctum, the Tyro role/permission/privilege distinction, and the cache invalidation contract; (b) a sandbox app with seeders pre-populated so engineers can exercise the CLI without fear; (c) a "first PR" checklist drawn from the skill's Consistency First and naming-conventions rules. The Artisan CLI is the single biggest ramp-up accelerant — engineers who can see the model (tyro:role-list, tyro:user-privileges, etc.) understand it faster than engineers who only read schema. Budget one deliberate incident-free week where a pairing engineer drives the CLI against production-shaped data; that week purchases the next several months of confident operation. The Blade directives and middleware are the shallow end — most engineers will be productive there within days — but privilege inheritance, multi-tenant scoping, and the audit-log contract are the deep end and require the structured onboarding, not just reading the docs.
How can I help you explore Laravel packages today?