
Give each role the right responsibilities
Roles describe what a person or service may do. Wildo lets your application extend the built-in roles and inherit their responsibilities, so you can express your own team structure without rebuilding ordinary access checks.
The role travels with its scope: being an administrator of one organization does not make someone an administrator of another.
Example — A supervisor can do the work they oversee
A project supervisor inherits the manager role. Operations available to managers remain available to that supervisor, while ownership changes can require a higher role.
For engineers
Register custom roles in the application role configuration. inheritFrom supplies the existing responsibilities; relatedPrimaryScope selects the role table in which they are meaningful. Wonder Todos declares both an application manager and an organization supervisor:
This implementation excerpt from roles.ts shows the decision in context; explanatory source comments are omitted.
import { RolesConfiguration, ResourcePrimaryScope, CORE_APP_ROLES, CORE_ORG_ROLES } from "@wildo-ai/saas-models";
export const CUSTOM_ROLES_CONFIGURATION: RolesConfiguration = {
'CUSTOM_APP_MANAGER': {
role: 'CUSTOM_APP_MANAGER',
inheritFrom: CORE_APP_ROLES.APP_USER,
isSystemRole: false,
relatedPrimaryScope: ResourcePrimaryScope.APPLICATION
},
'CUSTOM_ORG_SUPERVISOR': {
role: 'CUSTOM_ORG_SUPERVISOR',
inheritFrom: CORE_ORG_ROLES.ORG_MANAGER,
isSystemRole: false,
relatedPrimaryScope: ResourcePrimaryScope.ORGANIZATIONS
}
};
Register the role map with the shared application module
A role map must reach startup before operations can use its hierarchy. Wonder Todos’ shared-lib/src/engine/index.ts contributes it through the existing engine module:
import type { SharedSaaSModule } from '@wildo-ai/saas-models';
import { CUSTOM_ROLES_CONFIGURATION } from './roles';
const engineSharedModule: SharedSaaSModule = {
moduleId: 'engine',
kind: 'engine',
customRoles: CUSTOM_ROLES_CONFIGURATION,
// Keep the module's existing feature, milestone and product contributions.
};
export default engineSharedModule;
This selected module excerpt is the contribution point. In Wonder Todos, shared-lib/src/modules-registry.shared.ts includes engineSharedModule in sharedModules and passes that list to buildSharedSaaSModulesRegistry. Retain that existing assembly. Declaring the constant in an unreferenced file does not register roles. Membership assignment and an operation’s required roles are separate choices: registration makes the hierarchy available, it does not grant it to every account.
Follow the declaration into authorization
Application startup registers this configuration with initializeRolesWithCustom. The authorizer expands the caller’s role through the configured inheritance chain before comparing it with an operation’s roles. This means an inherited manager responsibility remains available without copying the entire role list onto every member.
| Decision | Declaration or runtime input |
|---|---|
| What responsibilities a role includes | inheritFrom in the role configuration |
| Where the role applies | relatedPrimaryScope and the caller’s membership |
| Which role an action requires | The operation’s roles |
| Which records the caller can reach | Scope, membership and resource authorization |
A matching role is one part of admission. Tenant confinement and reference eligibility still apply. APP_PUBLIC is an operation declaration that removes a role requirement; it is not a role to grant to an account. Use role grants to control who may assign the roles you define.