Skip to main content
Declare roles and row filters once in zite.permissions.json at the workspace root; every app and workflow enforces them on every zite.* call. Schema → permissions file; evaluation model → Roles & permissions.

A practical file

Managers get full access to Deals; account executives can read and update only their own rows:
One rule covers one role and one operation, so granting four operations means four rules. Use the built-in builtin:all-team-members role id to grant something to everyone internal.

Gotchas

  • "defaultPolicy": "deny" is what turns roles on. Leave it out and the whole file is inert: every rule above is stored and none is enforced, with no error. This is the single most common way a rule set silently does nothing.
  • Table keys are PascalCase. "Deals", not "deals", even though you call it as zite.deals. A mis-cased key passes validation and then matches nothing, which under deny-by-default locks the table rather than opening it.
  • Rules cover external apps too. External and anonymous visitors match builtin:all-users, not builtin:all-team-members, so a file that names only the team-members built-in locks every public visitor out. Scope a public app’s data with a row filter on a userField, and require a session on the workflow:
    See Auth and Authentication.
  • Check filter keys against .zite/db.ts. An unrecognized key in filters is dropped rather than raising, so a typo makes the query broader than you wrote. See the database client.
  • rowFilter does not apply to create. A create rule grants the operation outright; enforce constraints on new rows in the workflow.
  • You define roles here; a human assigns them on the Members tab. Keep each role’s id stable across renames so assignments survive.
  • Administrators and workspace editors bypass all rules when using internal apps.