# The permissions report

Policy is written beside each entity, so nobody has to keep a central
copy. To see the whole app at once, read the report `jadpo check` writes:
`build/report/permissions.md`, with a `.json` twin. It says who can do
what to every entity and field, and which actions are listed separately.
Each list is shown as written, and an effect nobody is granted says so.

Here is part of the report for [Policy, end to end](when-policy-says-no.md#policy-end-to-end):

| `work.Project` | create | read | update | delete |
|---|---|---|---|---|
| the record | `CompanyRole.owner`, `CompanyRole.editor` | `CompanyRole.owner`, `CompanyRole.editor`, `CompanyRole.viewer` | `CompanyRole.owner`, `CompanyRole.editor` | `CompanyRole.owner` |

Belongs to a `Company` through `company_id`. Only an action listed under `actions:` changes `company_id`.

A field that narrows its entity's grants gets a row of its own beside "the
record". For the `Project` under [Field restrictions](field-restrictions.md):

| `work.Project` | create | read | update | delete |
|---|---|---|---|---|
| the record | `CompanyRole.editor` | `CompanyRole.viewer`, `CompanyRole.editor` | `CompanyRole.editor` | `CompanyRole.owner` |
| `budget` | as the record | `CompanyRole.editor` | `CompanyRole.editor` | as the record |
| `import_reference` | server only | server only | server only | as the record |

When a change alters this table, the approval review shows it in plain
terms, such as "viewers can now read `budget`"
([Review and sign-off](review-and-sign-off.md)).

Policy adds no index of its own. Every field a condition filters on is a
reference (a user field, a role's or the tenant's reference, a
membership's scope and member), and each already has its own
[index](indexes.md). Keeping a reference inside the tenant finds
the record it points at by `id`, its primary key. A move to another tenant
finds the records referring to it by their reference, which has its
index. So neither needs an index or a migration of its own.
