BaryoDev / BaryoDev/barakoCMS

Roles: tenant-owned roles, with a small set of platform roles

Open
#913 0 comments 0 reactions 0 assignees View on GitHub
core design migration security
Dominant language
C#
Stars
6
Forks
7
Avg merge
4h 42m
Merged PRs (30d)
307

Description

Roles are one global list. `Role` is `SingleTenanted` (`barakoCMS/Extensions/ServiceCollectionExtensions.cs:626`), `GET /api/roles` queries every role with no tenant filter (`barakoCMS/Features/Roles/List/Endpoint.cs:32`), and `PUT /api/roles/{id}` loads and saves any role by id (`Features/Roles/Update/Endpoint.cs:47`). `docs/multi-tenancy.md` states this is by design. A role's `Permissions` name content types (`barakoCMS/Models/Role.cs:26`), but content types live in each tenant's partition, so the same entry means a different type in each tenant. `User.RoleIds` is unioned into the caller's roles in every tenant (`Infrastructure/Multitenancy/MembershipRoles.cs`).

### What was checked for a cross-tenant bug

A seeded tenant administrator cannot reach this today. Creating a tenant gives its first member the seeded Admin role (`Features/Tenants/Endpoints.cs:188`), Admin's defaults do not include `manage_roles` (`Models/SystemCapabilities.cs:289`), and all five roles routes require `manage_roles` (`Features/Roles/List/Endpoint.cs:25` and siblings), so `GET /api/roles` with that tenant admin's token answers 403. No bug for the 4.2.0 train.

The exposure is configuration. `manage_roles` is only meaningful platform-wide, but nothing says so. A tenant member endpoint accepts any existing role except SuperAdmin (`Features/Tenants/Members/Endpoints.cs:41`), so if an operator ever creates a role holding `manage_roles` for a client, that client's administrator can assign it within their tenant, and the holder then lists and edits the role definitions every other tenant uses, including the shared Admin role.

### Why it is too specific

One list assumes one organisation. An agency running a clinic and a bakery wants a Nurse role in one and a Baker role in the other, and neither client should see or change the other's. Editing Admin for one client changes Admin for all of them.

### The general concept

Tenant-owned roles: a role belongs to a tenant, and its permissions refer to that tenant's content types. A small set of platform roles (SuperAdmin, and the seeded defaults a tenant copies from) stays global and is editable only with a platform capability. `manage_roles` becomes tenant scoped; a separate platform capability covers platform roles.

### Where it lives

Core: roles, capabilities and multi-tenancy.

### Compatibility

Released, stored data changes. A migration assigns each existing custom role to the tenants whose memberships hold it (copying a role held in several), leaves the seeded ids global, and keeps role ids stable. `/api/roles` keeps its shape and answers with the caller's tenant roles plus platform roles; a platform caller keeps seeing everything. Default single-tenant deployments see no difference.

Part of the decision on what a principal is, linked from the umbrella issue. Relates #883, #886.

### Done when

- A caller holding tenant `manage_roles` in tenant A gets 404 on `PUT /api/roles/{id}` for a role owned by tenant B, with a test that fails before the change.
- Tenant A's role list does not contain tenant B's roles.
- The seeded Admin role cannot be edited without the platform capability.
- The migration keeps every existing membership's effective permissions unchanged.

Found in the architecture sweep of 15 September 2026.

Contributor guide

Open the contributing guide

Research direction

Start with the role registration and access paths in barakoCMS/Extensions/ServiceCollectionExtensions.cs, Features/Roles/List/Endpoint.cs, Features/Roles/Update/Endpoint.cs, and Features/Tenants/Members/Endpoints.cs. Then read Models/Role.cs, Infrastructure/Multitenancy/MembershipRoles.cs, Features/Tenants/Endpoints.cs, and docs/multi-tenancy.md to understand seeded roles and effective permissions. Done means tenant isolation, protected platform roles, and unchanged effective permissions after migration, covered by failing-before tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
authorization, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.