56 lines
2.3 KiB
Markdown
56 lines
2.3 KiB
Markdown
# Access
|
|||
|
|
|
||
|
|
Who may do what to what is compiled from content on every load into
|
||
|
|
one Cedar policy set, and every server entry point asks that one
|
||
|
|
policy. Identity stays Kanidm's; portal only decides.
|
||
|
|
|
||
|
|
## What content compiles to
|
||
|
|
|
||
|
|
| content | rule |
|
||
|
|
|---|---|
|
||
|
|
| a page with no `qualifies` | anyone may open and submit |
|
||
|
|
| `qualifies: case_officers` | that group may open and submit |
|
||
|
|
| `requires_chain: /start` | the visitor's verified answer lineage must reach it |
|
||
|
|
| a resource with `public: true` | anyone may read it |
|
||
|
|
| a resource with `requires_group: g` | that group may read it |
|
||
|
|
| a desk resource's `transitions` | that group may make those moves |
|
||
|
|
| an alternative's `self_transition` | the submitter may make it, from each state in `from`, with their link and their matching email |
|
||
|
|
| an alternative's `invite: {group}` | the page's own group may invite into that group |
|
||
|
|
|
||
|
|
Mutations always need a group, whatever `public` says. A resource with
|
||
|
|
neither `public` nor `requires_group` is unreachable rather than open:
|
||
|
|
the policy fails closed.
|
||
|
|
|
||
|
|
## Reading the policy
|
||
|
|
|
||
|
|
```sh
|
||
|
|
iris check --path questions --access
|
||
|
|
```
|
||
|
|
|
||
|
|
prints every rule the content compiled to, as a table of who may do
|
||
|
|
what from where to where. It is the fastest way to find a rule a
|
||
|
|
content repo did not mean to write — a refusal available on the day a
|
||
|
|
case arrives, a board that can decide a case it never received.
|
||
|
|
|
||
|
|
## Asking it
|
||
|
|
|
||
|
|
Every decision carries the rule ids that granted it. Refusals and
|
||
|
|
every mutation are published on `portal.access.decided`.
|
||
|
|
|
||
|
|
Other applications ask the same question over NATS request-reply on
|
||
|
|
`portal.access.<site>.may`, with the same principal, action, resource
|
||
|
|
and context the server uses internally — so an automation acting as a
|
||
|
|
group gets exactly the answer a person in that group would.
|
||
|
|
|
||
|
|
## The submitter
|
||
|
|
|
||
|
|
A person who sent a form has no account. Their credential is the link:
|
||
|
|
an unguessable chain hash, plus the email they gave, which the policy
|
||
|
|
compares against the one stored on the record.
|
||
|
|
|
||
|
|
What they may do, and from where, is `self_transition.from`. Its
|
||
|
|
default is the initial state alone. A refusal reads "not found" while
|
||
|
|
the record is somewhere the move could have been made from — so the
|
||
|
|
endpoint cannot be used to discover which records or addresses exist —
|
||
|
|
and "already processed" once the case has moved past it.
|