Skip to content
Scava Docs Join the waitlist

Scava opens soon. These docs describe how it works at launch. Join the waitlist

All chapters

Data

Permission rules for an internal tool - scava.json

To control who may see and change what in an internal tool, put a file named scava.json next to index.html. It says, per collection of entries, who reads and who writes. Scava enforces these rules on its own server for every request, so they hold even if someone edits the page in the browser or sends requests by hand. The app only shows or hides buttons; it is never the place where permissions are decided.

The file #

{
  "name": "Team vacation",
  "data": {
    "vacation": { "read": "all", "write": "own" }
  },
  "files": {
    "receipts": { "read": "own", "write": "own" }
  }
}

The four values #

ValueFor readFor write
"all"Everyone who can open the app reads all entries.Everyone changes and deletes all entries and adds new ones.
"own"Each person reads only the entries they created.Each person adds entries and changes or deletes only the entries they created.
"owner"Only the creator of the app reads.Only the creator adds, changes and deletes.
"group:<name>"Only members of that group read.Members of that group add, change and delete every entry.

"Own" means the entry's created_by is the person's email address.

The creator of the app can always read and change everything. A co-editor gets no more than the rules give any other person; they can, however, publish new rules.

Lists: any one is enough #

A list means a person needs only one of the values.

"read": ["own", "group:hr"]

Each person sees their own entries, and members of hr see all of them. Keep lists short; a list with too many values is refused.

Groups #

group:<name> refers to a group in the account of the app's owner, for example group:leads. The owner creates groups on the Overview page at scava.ai, in the browser. Agents cannot create groups. Group membership is read fresh on every request, so removing someone from a group takes effect at once.

If a version names a group that does not exist yet, publishing works and tells the agent which group is missing. Until the owner creates it, only the owner can do what the rule allows the group.

Rules for single fields #

Inside a collection, fields sets rules for single fields of an entry. They use the same values.

"vacation": {
  "read": "all",
  "write": ["own", "group:leads"],
  "fields": {
    "status": { "write": "group:leads" }
  }
}

Field rules can only take away. They never give more than the rule of the collection.

Example 1: a vacation planner where team leads approve #

{
  "name": "Team vacation",
  "data": {
    "vacation": {
      "read": "all",
      "write": ["own", "group:leads"],
      "fields": { "status": { "write": "group:leads" } }
    }
  }
}

What this does:

The app can hide the "Approve" button for everyone who is not a lead, with scava.me() returning groups. The button is only a convenience. The rule is the lock.

Example 2: salaries that only the person and HR see #

{
  "name": "Staff directory",
  "data": {
    "staff": {
      "read": "all",
      "write": ["own", "group:hr"],
      "fields": {
        "salary": { "read": ["own", "group:hr"], "write": "group:hr" }
      }
    }
  }
}

Each employee creates one entry about themselves, with name, team and phone. HR adds the salary to any entry.

Because "own" means "created by this person", the employee must be the one who creates their own entry. If HR created the entries, nobody but HR would see the salaries.

Rules for files #

files uses the same values, with these differences: it has no fields, and the rule says who sees the list and downloads and who uploads. See Files.

Rules apply to server code too #

Server code acts with the rights of the owner by default. Use env.SCAVA.db('vacation', { as: 'me' }) to act with exactly the rights of the person who asks. Then the rules above apply to that person, groups and fields included. Without a person (a webhook or a schedule), as: 'me' is refused.

Checks at publish time #

Scava refuses a scava.json that is not valid JSON, has an unknown rule value, a bad collection name or bad field rules, and says what is wrong. The error text of a refused request tells the person who may do it, for example "Only members of hr and the owner of this app can add entries here."