vulkro rbac
Emit a role-based-access-control matrix from your discovered endpoints
METHOD PATHrows xAuthTiercolumns, where the endpoint requires that tier. Markdown for audit handoff, JSON for tooling.
Usage
vulkro rbac . # markdown matrix to stdout
vulkro rbac . --format json # structured JSON
vulkro rbac . --output rbac.md # write to a file
Arguments
| Argument | Description | Default |
|---|---|---|
PATH | Project root. | . |
Flags
| Flag | Description | Default |
|---|---|---|
--format <FMT> | md (Markdown table) or json. | md |
--output <FILE>, -o | Write to file instead of stdout. | stdout |
What the matrix shows
Vulkro's auth model has been extended beyond the original
Protected/Unprotected/Unknown flag: each endpoint now carries an
AuthRequirement with three fields the matrix surfaces.
- AuthTier - one of
Anonymous,User,Admin,Service,Machine,Unknown. Inferred from decorators and middleware (@UseGuards(AdminGuard),IsAdminUser,is_staff,[Authorize(Roles="Admin")],@PreAuthorize("hasRole('ADMIN')"),auth:sanctum, etc.). - Scopes - list of OAuth-style scope checks. Populated from
@Security(scopes=["users:read"]),@Scopes('foo'),RequiresScope(...), etc. - TenantScoping -
ScopedByTenant|GlobalNoTenant|Unknown. Flagged when the handler body referencescurrent_user.tenant_id,request.tenant,req.user.organisation_id, or similar.
The matrix presents the first dimension (tier) as columns and the endpoints as rows; scopes and tenant scoping appear as extra columns.
Markdown example
| Method | Path | Anonymous | User | Admin | Service | Machine | Scopes | Tenant |
|---|---|:--:|:--:|:--:|:--:|:--:|---|---|
| GET | /api/health | | | | | | | global |
| GET | /api/me | | | | | | | by tenant |
| POST | /api/users/:id/promote | | | | | | users:admin | by tenant |
| POST | /api/internal/sync | | | | | | | global |
JSON example
{
"endpoints": [
{
"method": "POST",
"path": "/api/users/:id/promote",
"tier": "Admin",
"scopes": ["users:admin"],
"tenant_scoping": "ScopedByTenant",
"file": "src/api/users.rs",
"line": 142
}
]
}
Why this is useful
- Audit handoff. Auditors asking "which endpoints can role X reach?" get a one-page answer instead of "let me grep the middleware."
- Sanity check on a release. A diff of the RBAC matrix before and after a release surfaces accidentally-exposed admin endpoints.
- Tenant-boundary review. The
TenantScopingcolumn reveals endpoints in a multi-tenant codebase that don't visibly scope by tenant - a common IDOR shape.
How tier inference works (per language)
The inference is best-effort and never invents a tier - it falls back
to Unknown when no clear evidence is visible. Examples:
| Language | Admin signal | Service signal |
|---|---|---|
| Python | IsAdminUser, is_staff, permission_classes=[IsAdmin*], @staff_member_required | X-Service-Token, verify_service_token, mTLS hints |
| Node/TS | @UseGuards(AdminGuard), requireAdmin, IsInRole("Admin") | @UseGuards(ServiceTokenGuard), X-Service-Token |
| Java | @PreAuthorize("hasRole('ADMIN')"), @RolesAllowed("ADMIN") | @RolesAllowed("SERVICE") |
| C# | [Authorize(Roles="Admin")] | [Authorize(Policy="ServiceToken")] |
| Go | route registered behind a RequireAdmin middleware | route behind a ServiceAuth middleware |
| Rails | before_action :require_admin, current_user.admin? | (less common in Rails) |
| Laravel | middleware('role:admin'), Gate::allows('admin') | middleware('auth:sanctum-service') |
Related
vulkro discover- produces the endpoint list the matrix is computed from.vulkro openapi- emits an OpenAPI 3.1 spec with the same auth-tier info asx-vulkro-tierextensions.