Skip to main content
Access is expressed as roles, and a role is a set of grants, entity by entity.

No inheritance, no wildcards

An entity a role does not name is an entity that role cannot touch. There is no *, and no role extends another. This is more typing, and it buys the thing worth buying: reading one role file tells you exactly what that role can do. You never have to resolve a chain to find out, and a new entity is not silently readable by everyone the moment it is added.
Adding an entity does not add it to any role. Until you grant it, nobody but the owner and a platform administrator can see it. That is the intended direction to fail in.

What enforcement actually does

Grants are checked on every operation, through the API as well as through the interface. Two behaviours are worth knowing because they are not what people expect. Read responses drop fields the role may not read. Not an error, just absent. A list silently drops a filter on a hidden field, but an aggregate refuses it. These look inconsistent and are not. A list returning fewer rows leaks nothing. An aggregate that quietly ignored a groupBy would hand back a confidently wrong number, so it answers 403 instead.

404 and 403 mean different things

no relationship
You have no relationship to this app at all. It answers exactly as a missing app does. Whether an app exists is not something an unrelated caller gets to learn.
the role denies it
You have a relationship, and the roles it grants do not permit this operation.

Writing them

upsert_role and remove_behaviour are the operations. Or edit roles/*.cordango.yaml directly.

In a generated application

A standalone application generated by cordango build carries its own users, authentication and permissions, built from the same role definitions. The enforcement is a second implementation of the same rules, pinned by hand-written fixtures that both products assert against. Same roles, same grants, no shared code path. That is on purpose: two implementations that must agree catch mistakes one implementation cannot.