You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: app/best-practices/page.mdx
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -170,6 +170,12 @@ One of the big benefits to using a centralized authorization system like SpiceDB
170
170
It can be tempting to define the authorization logic for an endpoint as being the `AND` or `OR` of the checks of other permissions, especially when the alternative is writing a new schema.
171
171
However, this increases the likelihood of drift across your system, hides the authorization logic for a system in that system's codebase, and increases the load on SpiceDB.
172
172
173
+
### Use Typechecking
174
+
175
+
Tags: **schema**
176
+
177
+
Adding [type-checking](https://authzed.com/docs/spicedb/concepts/schema#typechecking) to your schema can turn some silent bugs into failures at `WriteSchema` time.
Copy file name to clipboardExpand all lines: app/spicedb/concepts/schema/page.mdx
+125Lines changed: 125 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -444,6 +444,131 @@ definition user {
444
444
But in order to express that a user should be able to view themselves, you'll need to write a corresponding relationship (e.g. `user:alice#viewer@user:alice`)
445
445
for the check to evaluate to true. The `self` keyword requires less DB space and computation to achieve the same result.
446
446
447
+
### Typechecking
448
+
449
+
The `use typechecking` feature allows you to explicitly declare and validate the types that permissions can resolve to, providing type safety for your authorization schemas.
450
+
451
+
Consider this schema:
452
+
453
+
```zed
454
+
definition user {}
455
+
definition serviceaccount {}
456
+
457
+
definition document {
458
+
relation viewer: user
459
+
relation admin: serviceaccount
460
+
permission edit = viewer & admin
461
+
}
462
+
```
463
+
464
+
This schema writes successfully, but a call to `CheckPermission` for `document#edit` will _always_ return false at runtime because no relationship can simultaneously be for a `user` subject and for a `serviceaccount` subject. This is a bug that can go unnoticed for a long period of time, because the API call doesn't return an error.
465
+
466
+
Adding [type-checking](https://authzed.com/docs/spicedb/concepts/schema#typechecking) will turn that silent bug into a failure:
467
+
468
+
```zed
469
+
use typechecking
470
+
471
+
definition user {}
472
+
definition serviceaccount {}
473
+
474
+
definition document {
475
+
relation viewer: user
476
+
relation admin: serviceaccount
477
+
permission edit: user = viewer & admin
478
+
}
479
+
```
480
+
481
+
This will fail at `WriteSchema` time because the type annotation provided is incomplete: it needs to be `permission edit: user | serviceaccount = viewer & admin` for the satisfy the type checker. However, the error given by the typechecker is really pointing at the underlying issue: you should fix the permission itself.
482
+
483
+
- Should the `edit` permission really be an intersection?
484
+
- Is `serviceaccount` the only type that can be an `admin`?
485
+
- Is `user` the only type that can be a `viewer`?
486
+
487
+
#### Use
488
+
489
+
Enable type checking by adding `use typechecking` at the top of your schema, and then add the type annotations to the permissions:
Note that type annotations must be complete: they must include **all** types reachable through the permission expression.
509
+
510
+
You can also slowly transition into a type-annotated schema by mixing annotated and non-annotated permissions:
511
+
512
+
```zed
513
+
use typechecking
514
+
515
+
definition user {}
516
+
517
+
definition document {
518
+
relation viewer: user
519
+
permission view: user = viewer // Validated
520
+
permission edit = viewer // Not validated (no annotation)
521
+
}
522
+
```
523
+
524
+
#### Examples
525
+
526
+
- Single Type
527
+
528
+
```zed
529
+
use typechecking
530
+
531
+
definition user {}
532
+
533
+
definition document {
534
+
relation viewer: user
535
+
permission view: user = viewer
536
+
}
537
+
```
538
+
539
+
- Multiple Types
540
+
541
+
```zed
542
+
use typechecking
543
+
544
+
definition user {}
545
+
definition team {}
546
+
547
+
definition document {
548
+
relation viewer: user | team
549
+
relation owner: user | team
550
+
permission view: user | team = viewer + owner
551
+
}
552
+
```
553
+
554
+
- With Arrow Operations: the annotations must be for the types on the right-hand side of the arrow:
555
+
556
+
```zed
557
+
use typechecking
558
+
559
+
definition user {}
560
+
definition team {}
561
+
562
+
definition organization {
563
+
relation member: user | team
564
+
}
565
+
566
+
definition document {
567
+
relation org: organization
568
+
permission view: user | team = org->member
569
+
}
570
+
```
571
+
447
572
### Naming Permissions
448
573
449
574
Permissions define a set of objects that can perform an action or have some attribute, and thus **permissions should be named as verbs or nouns**, read as `(is/can) {permission name} (the object)`.
0 commit comments