Stacklane's role and permission system is designed to strike a balance between power and real world use. The best permission system is the one you'll actually use.
default role is a specially named role that is
always defined and in effect for all users and visitors,
whether authenticated or not.
All other roles that may be in effect are built on top of any
permissions in effect for the
If there is no root
/👤.yaml file defined in the source,
default role is given full access to all resources.
This would be the case of a fully public site with
no sensitive or user specific data.
Once a root
/👤.yaml is added, then the
access level becomes
none if not otherwise redefined.
Take care with the default role since permissions may only be granted, never revoked. Although you may add to the default role's permissions in sub-directories, another custom role may not reduce the permissions already in effect for the default role.
Custom role names must start with an uppercase character and be valid identifiers.
We recommend using a singular form for role names — for example,
use the role name of
Owner instead of the plural
Once you've defined custom roles, they are most typical meaningful when associated with a specific user.
Profiles are a type of model which associates custom data with a specific user, and are the only location where role names may be associated with a user.
Learn more about Profiles, including role examples.
Changing role names may not be a safe operation if the role has been associated with a user.
All roles, including
default, may define permission rules.
Permission rules define what is allowed for a role,
and are always granted, never revoked.
Most permission rules map to model data operations.
The general layout of a role and its permission rules is the role name, resource rule (corresponding to a model or field), and one or more operations allowed (separated by commas).
[ROLE_NAME]: [RESOURCE_RULE]: [OPERATIONS_ALLOWED]
The following operations may be specified for any resource rule
all, no operation implies another operation.
none— Only applicable to root settings file roles.
all— All operations allowed.
access— May also refer to "select", "exists", "accessible", or "visible". Necessary for accessing linked/referenced models.
read— Read a value. May also refer to "get", "load" if the operation requires knowing an ID.
create— Create / new operation such as
update— Update / set a field value.
delete— Removing / deleting a model.
state— Special case of a field value
update, representing a significant "change in state". This occurs only by nomenclature, for any field named "state", "status", "stage", or "lifecycle".
list— List operations are "bulk" operations, and usually refer to queries that may return multiple results.
Resource rules for models follow the data structure, from general to specific. The rule most specific to the requested resource will be used.
📦— Package/module level rule.
📦.Product— Model type specific rule.
📦.Product.title— Field specific rule.
📦.Product.Description— Embedded model specific rule.
MyRole: 📦: read # read all models and fields 📦.Product: update # read (from package/module) + update (added)
In addition to models, Connectors
also support permission rules. The resource of the connector rule
follows the file-based definition of the Connector's various endpoints.
GET's are a
read operation, unless the endpoint is
list.yaml and then it's a
delete operations. Endpoints ending with
Everything else is an
default: stripe.com: read # read everything by default stripe.com.charges.list: list # allow for specific endpoint
A similar and more robust approach is possible with nested sites.
User settings files may be placed in sub-directories. This allows roles and permissions to be scoped to a directory and its descendants.
Sub-directory settings files may not define new role names.
They may only use role names already specified in the root
In this way the root file is a "master list" of role names.
If a role name is only relevant to a sub-directory, simply
define it with
[ROLE_NAME]: none in the root file, and then
redefine it with actual permissions in the sub-directory settings file.
Role permissions defined in a sub-directory file are additive to any earlier definitions of the same role name in ancestor directories. Permissions are never revoked. In this way deeper sub-directories are usually going from less permissive to more permissive (accumulating new role permissions as needed).
It's also not necessary to specify every role — only those roles which are being granted additional permissions in the sub-directory file.
auth: none MyRole: none
auth: required MyRole: 📦: read 📦.Post: access,read,update
MyRole: 📦.Post: create,delete
This is for special cases only and will not be needed for most endpoints.
This configuration file supports user related settings.
Assuming a POST endpoint named
👤: as: SomeRoleName only: OtherRoleName
The role names must already be defined, and typically only one setting would be used at a time.
regardless of whether the current user is actually assigned to that role.
from users associated with the given role. If the user is not associated
with the role, then
403 FORBIDDEN is returned.
Typically an app would hide this functionality as well, if the
role was not applicable to the user. Therefore
the last line of defense, not the first.
The following gives some insight into how roles and permissions are resolved.
Given the example of loading a specific
let prod = Product.get('[id]'),
the platform will check for
As additional operations on the instance are performed,
product.title = 'New Title',
the system will use all in-scope roles to determine
To determine whether a specific operation is possible, the platform is considering a combination of permission rules as follows:
- Roles assigned to the authenticated user (by way of user profiles)
- Roles assigned between authenticated user and the model's parent + ancestor containers (by way of container user profiles).
As we are only concerned with granting permissions, if multiple roles are in effect then the final effective role is a combination of all assigned and in-scope roles.
It's also important to keep in mind the first step of the process. For this process 👤.yaml is referring to the currently in-scope settings file, which may be a sub-directory file. In this way both revocation and super-user scenarios are possible simply redefining roles for specific sub-directories.