
February 17, 2026
Modern Rails applications rarely fail because of authentication — they fail because of authorization complexity. As products grow, roles multiply, exceptions accumulate, and permission checks scatter across controllers, models, views, and frontend code. What begins as a simple current_user.admin? quickly becomes an unmaintainable web of implicit rules.
At Kaigi on Rails 2025, Yusuke Ishimi presented a practical architecture for permission management designed to remain correct as systems evolve. The talk, titled “Designing and Implementing Authorization Without Technical Debt,” focuses on building authorization that is explicit, testable, and resilient to business change. 権限管理の設計と実装
This article distills the key ideas and shows why they matter for real-world Rails systems.
Why Authorization Fails in Growing SaaS Systems
Permission bugs are not minor defects — they are business risks.
In enterprise SaaS products, authorization determines who can see salaries, contracts, customer data, or internal metrics. A single mistake can expose sensitive information and damage trust.
The presentation highlights typical scenarios:
- Only administrators can invite members
- External contractors can access only assigned projects
- Premium plans unlock additional features
- Financial data is visible only to specific roles
When implemented poorly, these rules lead to incidents such as accidentally exposing salaries or client information — errors with serious consequences. 権限管理の設計と実装
The Root Problem: Role-Based Checks
Most Rails codebases start with role checks:
redirect_to root_path unless current_user.admin?
This seems reasonable — until reality intrudes.
Businesses evolve:
- New customer segments appear
- Organization sizes vary
- Responsibilities differ by industry
- Features expand
- Temporary exceptions accumulate
Eventually, “admin” no longer means a single thing.
The talk argues that role-dependent logic becomes fragile and opaque. Developers reviewing code must mentally reconstruct what each role implies, and changes require touching many scattered checks. 権限管理の設計と実装
RBAC vs ABAC — And Why You Need Both

Authorization models are often described as:
RBAC — Role-Based Access Control Permissions depend on user roles.
Examples:
- Admin account
- Manager account
- External account
ABAC — Attribute-Based Access Control Permissions depend on contextual attributes.
Examples:
- Record creator
- Assigned user
- Ownership
- Project membership
Real systems require both. A project might be editable by:
“An administrator or the assigned user.”
This rule mixes role and context. The presentation emphasizes that authorization logic should explicitly represent these dimensions rather than hiding them inside roles. 権限管理の設計と実装
The Key Design Insight: Depend on Permissions, Not Roles
Instead of asking:
“Is the user an admin?”
Ask:
“Can this user perform this action on this object under these conditions?”
The proposed model decomposes authorization into four elements:

1. Target (Object)
What resource is being accessed?
- Project
- Invoice
- User account
- Report
2. Operation (Action)
What is the user trying to do?
- read
- update
- delete
- invite
- approve
3. Role
Who is the user within the organization?
- Admin
- Manager
- External contractor
4. Conditions (Attributes)
Contextual requirements:
- Is the user the creator?
- Are they assigned?
- Does the record belong to their organization?
This structure makes authorization rules explicit and understandable.
Example Rule in Explicit Form
Instead of implicit logic scattered across the app:
“Project updates are allowed for administrators or responsible users.”
Express it as:
Target: ProjectOperation: updateAllowed when: role == admin OR condition == assigned_user
Now anyone can understand the rule without reverse-engineering roles.
A Modular Policy Architecture
The implementation presented goes beyond typical policy libraries by structuring authorization as composable modules.
Key ideas include:
Separate Roles from Conditions
Roles determine baseline authority. Conditions refine it using record-specific context.
Define Policies per Target
Each model has dedicated authorization logic rather than global role rules.
Use Explicit Operations
CRUD operations are defaults, but custom actions can be added cleanly.
Leverage Metaprogramming to Locate Policy Classes
The system determines the correct policy class based on the target and role, reducing manual wiring and simplifying changes.
Three Authorization Modes
The architecture supports three common authorization needs.
1. Record Mode — Can the user perform an action on this object?
Example:
can_update?(project)
2. Scope Mode — Which records can the user access?
Example:
visible_projects = policy_scope(Project)
This is critical for index pages and API endpoints.
3. List Mode — What permissions does this user have?
This produces a permission set that can be sent to clients (e.g., a Next.js frontend) to control UI behavior declaratively.
Why This Matters for Frontend Architecture
A particularly interesting insight is how this design affects the client side.
By sending explicit permission data to the frontend:
- UI logic depends on permissions, not roles
- Components render conditionally in a declarative way
- Frontend technical debt decreases
- Authorization remains consistent across layers
For example, the edit button simply checks whether the user has update permission for a project. If not, it never renders.
Reliability Gains in Practice
According to the presentation, adopting this modular authorization system led to tangible improvements:
- Increased service reliability
- Elimination of internal support questions about permissions
- Higher development productivity
- Reduced bugs related to authorization
- Prevention of frontend authorization debt
These outcomes suggest that authorization architecture is not just a security concern but a productivity multiplier.
Why Role-Dependent Logic Becomes Technical Debt
The core argument is simple but powerful:
Roles change as businesses grow — permissions should not.
When authorization depends on roles alone:
- Meaning becomes implicit
- Changes ripple unpredictably
- Reviewers struggle to understand behavior
- Bugs become likely
- Security risks increase
Explicit permission modeling avoids these pitfalls.

Lessons for Rails Engineers
This talk highlights several best practices for production systems:
- Treat authorization as domain logic, not plumbing
- Avoid scattering permission checks across layers
- Make rules explicit and composable
- Combine role-based and attribute-based approaches
- Provide machine-readable permission data to clients
- Optimize for clarity and change resilience
Final Thoughts
Rails has excellent tools for authentication, but authorization remains one of the most difficult aspects of application design. As systems scale, simplistic role checks inevitably break down.
The architecture presented at Kaigi on Rails 2025 offers a compelling alternative: a permission-centric model that separates concerns, embraces context, and remains understandable over time.
If your codebase still relies heavily on admin? checks, it may be time to rethink authorization before it becomes your next major source of technical debt.
