How to Create a JSON Seed File for Roles and Permissions in QAuth
What is QAUTH?
QAuth is a centralized authentication and authorization service designed by Quollnet to simplify how applications manage users, units, roles, and permissions. Instead of each app handling access control on its own, QAuth acts as a secure hub where rules are defined once and applied consistently across the ecosystem. This makes it easier for organizations to onboard users, delegate access, and enforce permission boundaries without duplicating logic in every project.
At its core, QAuth is built around role-based access control (RBAC). Users belong to units, and each unit has roles that define what actions its members can take. Permissions follow a clear naming convention, making access rules both human-readable and machine-enforceable. By separating authentication (who you are) from authorization (what you can do), QAuth provides a scalable, flexible, and transparent way to secure multi-app environments.
What is Seeding Roles and Permissions
Seeding roles and permissions is a crucial part of setting up role-based access control (RBAC) in QAuth. By defining roles and permissions in a JSON file, you make your access control structure declarative, portable, and easy to maintain across different environments.
This guide explains how to create a JSON seed file, what naming conventions to follow, how wildcards work, and how to validate and apply your file.
1. Why use a JSON seed file?
Instead adding roles and permissions manually in the application. This gives you:
-
Consistency across all environments.
-
Transparency – simple diffs show changes to access rules.
-
Portability – re-seed the same roles/permissions into new units/apps.
- Safety – seeding is idempotent (safe to re-run).
2. File location
You can select the file saved on your device or you can do the following.
-
Save as:
main_storage/common_roles.json
-
In
config.py
, set:
COMMON_ROLES_PATH = "path/to/main_storage/common_roles.json"
3. JSON structure
A seed file contains two top-level arrays:
-
roles
: each role has a name, description, and agrants
list. -
permissions
: each permission has a unique name and description.
Example:
{
"roles": [
{
"name": "creator",
"description": "Unit owner with full access",
"grants": ["*"]
},
{
"name": "admin",
"description": "Manage unit and members",
"grants": ["*:unit", "add:*", "assign:permission"]
},
{
"name": "viewer",
"description": "Read-only access",
"grants": ["view:unit", "view:member"]
}
],
"permissions": [
{ "name": "edit:unit", "description": "Edit unit settings" },
{ "name": "view:unit", "description": "View unit details" },
{ "name": "invite:member", "description": "Invite user to unit" },
{ "name": "add:role", "description": "Create role" },
{ "name": "assign:permission", "description": "Assign permissions" }
]
}
4. Naming conventions
-
Format:
verb:subject
(e.g.,edit:unit
,add:role
) -
Verbs:
view
,add
,edit
,delete
,activate
,deactivate
,assign
,invite
-
Subjects: nouns like
unit
,role
,member
-
Allowed characters: lowercase letters, numbers,
-
,_
,:
-
Example:
-
✅
view:unit
-
✅
add:member
-
❌
can_edit_unit
(old style, avoid underscores)
-
5. Using wildcards in grants
Wildcards make it easy to grant groups of permissions without listing each one:
-
*
→ all permissions -
*:unit
→ all permissions ending with:unit
-
add:*
→ all permissions starting withadd:
-
Literal names → attach exactly the given permission
Example:
{ "name" : "admin" , "grants" : [ "*:unit" , "add:*" , "assign:permission" ] }
Expands to:
-
All unit-related permissions (
view:unit
,edit:unit
,deactivate:unit
, …) -
All permissions starting with
add:
(add:role
,add:member
,add:unit
, …) -
The explicit permission
assign:permission
6. Seeding behavior
-
Permissions: created if new, skipped if they already exist.
-
Roles: if a role exists, its permissions are synced to match the
grants
list. - Unattached permissions: valid; they are created and left unused until assigned later.