Kizaki
Learn

Add Access Policies

Put authorization rules in Inspire so reads, writes, routes, and live queries all follow the same model.

Kizaki policies are declarative. You define who can act on which rows, and the runtime enforces those rules everywhere. Authorization is part of the data model, not something each handler remembers to check.

Start With Ownership

For first apps, ownership policies are usually enough:

entity Project {
  name: string,
  ownerId: __User.id,

  @grant read, write, delete where resource.ownerId == principal.id
}

This one rule applies across:

  • server-side queries
  • generated client calls
  • browser live queries
  • related data loaded through includes

If your product has a clear concept of "my data", start with ownership. It is simple, readable, and hard to misinterpret later.

Add Roles When Needed

entity Invoice {
  total: decimal(10, 2),
  accountId: Account.id,

  @grant read to role(Admin)
  @grant read where resource.accountId == principal.accountId
  @deny delete to *
}

Use roles when access is organizational rather than personal.

Good role design stays small:

  • Admin
  • Manager
  • Billing
  • Support

Prefer a small set of durable roles over a large matrix of narrow permissions in your first version.

Keep App Code Thin

Follow this split:

  • schema owns authorization
  • server functions own workflow
  • frontend owns presentation

If a rule can live in Inspire, keep it out of your UI code.

A Good Policy Design Sequence

For most apps, build policies in this order:

  1. ownership rules first
  2. role-based reads next
  3. role-based writes when needed
  4. deny rules for hard invariants

This sequence produces policies that stay readable as the app grows.

Next Step

Once access rules are in place, you can add business logic. Continue with Write Server Functions.

On this page