# access control

to help limit who can see your post (and how far it is propagated), `parsav` uses **ACL expressions**. this is roughly equivalent to scoping in pleroma or GNU social terms. an ACL expression consists of one or more space-separated terms, each of which match a certain set of users. a term can be negated by prefixing it with `~`, a tilde character, so `~all` matches nobody, and `~followed` matches users you do not follow.

* **all**: matches any and all users
* **local**: matches users who belong to this instance
* **mutuals**: matches users you follow who also follow you
* **followed**: matches users you follow
* **followers**: matches users who follow you
* **groupies**: matches users who follow you, but whom you do not follow
* **mentioned**: matches users who are mentioned in the post
* **staff**: matches instance staff (equivalent to `~%0`)
* **admin**: matches the individual named as the instance administrator, if any
* **@**`handle`: matches the user `handle`
* **+**`circle`: matches users you have categorized under `circle`
* **#**`room`: matches users who are members of `room`
* **%**`rank`: matches users of `rank` or higher (e.g. `%3` matches users of rank 3, 2, and 1). as a special case, `%0` matches ordinary users
* **#**`room`**%**`rank`: matches users who hold `rank` in `room`
* **<**`title`**>**: matches peers of the net who have been created `title` by the sovereign
* **#**`room`**<**`title`**>**: matches peers of the chat who have been created `title` by `room` staff

to evaluate an ACL expression, `parsav` reads each term from start to finish. for each term, it considers whether it describes the user who is attempting to access the content. if the term matches, its policy is applied and the expression completes. if the term doesn't match, the server proceeds on to the next term and the process repeats until it finds a matching term or runs out of terms, applying the fallback policy.

**policy** is whether a term grants or denies access. the default term policy is **allow**, but you can control the policy with the keywords `allow` and `deny`. if a term finishes evaluating without any match being found, a fallback policy is applied; this fallback is the opposite of whatever the current policy is. this sounds confusing but makes ACL expressions much more intuitive; `allow @bob` and `deny trent` do exactly what you'd expect — the former allows bob and only bob in; the latter denies access only to trent, but grants access to the rest of the world.

expressions must contain at least one term to be valid. if they consist only of policy keywords, they will be rejected.

in effect, this all means that an ACL expression can be treated as a simple list of who is allowed to view your post. for instance, an expression of `local` means only local users can view it. however, much more complex expressions are possible.

* `deny groupies allow +illuminati`: permits access to the illuminati, but excluding those members who are groupies
* `+illuminati deny groupies`: allows access to everyone but groupies (unless they're in the illuminati)
* `@eve @alice@nowhere.tld deny @bob @trent@witches.live`: grants access to eve and alice, but locks out bob and trent
* `<grand duke> #4th-intl<comrade>`: restricts the post to the eyes of the Fourth International's secret cabal of anointed comrades and the grand dukes of the Empire
* `deny ~%3`: blocks a post from being seen by anyone with a staff rank level below 3

**limitations:** to inhibit potential denial-of-service attacks, ACL expressions can be a maximum of 128 characters, can contain at most 16 words, and cannot trigger queries against other servers. all information needed to evaluate an ACL expression must be known locally. this is particularly relevant with respect to rooms.
