Policy
Policy says who may do what to which stored records. Each entity, a kind of stored record such as a todo, lists who may create, read, change and delete its records. The compiler applies those lists to every read and write your code makes, so you never write a permission check yourself.
This todo may be created, read, changed and deleted only by its owner:
domains/todos/entities/todo.jadpo:
use todos/entities { User }/// Something to do, belonging to one person.entity Todo { id: Uuid owner_id: User.id { on_delete: OnDelete.restricted } title: Text { max_length: 200 } policy: { create: [owner_id] read: [owner_id] update: [owner_id] delete: [owner_id] }}
owner_id is a reference to a User, so the person it points to is the
one let in. A caller no list names is refused, and a todo they may not
read behaves as if it didn't exist (When policy says no).
entity, policy:, Uuid, Text and OnDelete are built into Jadpo.
Todo and User are your app's own, and use brings User in from its
own file. Your app says which entity is a person in app.jadpo, which is
what lets a list mean "the signed-in user"
(The principal):
domains/todos/entities/user.jadpo:
/// A person with an account.entity User { id: Uuid email: Email { unique: true } policy: { create: [Access.system] read: [id] }}
app.jadpo:
use todos/entities { User }application {}principal { user: { subject: User.email }}
Each entry in a list names who it lets in, in one of four ways:
| Who | Written | Lets in |
|---|---|---|
| A user field on the record | owner_id |
the user that field points to |
| A membership role | CompanyRole.editor |
a user with that role in the record's company |
| Anyone signed in, or anyone | Access.authenticated, Access.public |
anyone signed in; anyone at all |
| Policy and background work | Access.system |
schedules and subscribers, limited to the tenant their event came from |
When your app is shared by many customer companies, Tenancy keeps each company's records to its own members, whatever the lists say.
| Grants A grant says who may do one thing to an entity's records. |
| A user field on the record Use a user field when a record belongs to one person, such as a todo and its owner. |
| A membership role Use a role when people get access by belonging to something, such as the editors of a company. |
| Anyone signed in, or anyone Use these for records that everyone signed in, or the whole world, may see, such as published articles. |
| Tenancy Keep customers' data apart does the whole job, start to finish. |
| Permissions on actions Most actions need no permission of their own: an action takes its permission from the entities it touches. |
| Field restrictions A field follows its entity's grants unless it says otherwise. |
| Policy and background work Schedules and event subscribers are the work your app does without a request (Background work). |
| The permissions report Policy is written beside each entity, so nobody has to keep a central copy. |
| Protecting policy An agent can edit policy, but the change can't ship without a person's approval, wherever it is written. |
| When policy says no Your code never handles a policy refusal itself. |
What is built says which of this works today.
Markdown for agents: /docs/policy.md.Built from Jadpo main at aee2e8f.