Skip to content

Commit 77eb6f1

Browse files
committed
Clarify how arrows operate over subject relations
1 parent e23c1d3 commit 77eb6f1

File tree

1 file changed

+59
-21
lines changed

1 file changed

+59
-21
lines changed

pages/spicedb/concepts/schema.mdx

+59-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { Callout } from 'nextra/components'
1+
import { Callout } from 'nextra/components';
22
import YouTube from 'react-youtube';
3-
import { InlinePlayground } from '@/components/playground'
3+
import { InlinePlayground } from '@/components/playground';
44

55
# Schema Language
66

@@ -12,7 +12,8 @@ You can experiment with schemas in real-time with the [Playground](https://play.
1212

1313
The following video provides an overview of schema development using the Playground:
1414

15-
<br /><YouTube videoId="AoK0LrkGFDY" />
15+
<br />
16+
<YouTube videoId="AoK0LrkGFDY" />
1617

1718
After studying this page's content, you may want to also read the [Developing a Schema] doc.
1819

@@ -22,7 +23,6 @@ After studying this page's content, you may want to also read the [Developing a
2223

2324
The top level of a Schema consists of zero or more [Object Type definitions](#object-type-definitions) and [Caveats](./caveats).
2425

25-
2626
```zed
2727
/**
2828
* somecaveat is a caveat defined
@@ -38,8 +38,9 @@ definition someobjecttype {}
3838
```
3939

4040
<Callout type="info">
41-
Note that the examples are unprefixed.
42-
You'll need to add the prefix from your permissions system if calling `WriteSchema` for a permissions system hosted in Serverless.
41+
Note that the examples are unprefixed. You'll need to add the prefix from your
42+
permissions system if calling `WriteSchema` for a permissions system hosted in
43+
Serverless.
4344
</Callout>
4445

4546
### Object Type Definitions
@@ -84,7 +85,8 @@ definition document {
8485
<Callout type="info">
8586
In the above example, the `user` on `reader` does not contain a sub-relation
8687

87-
Occasionally you will see a subject which has a sub-relation such as `usergroup:admins#members` which refers not just to the `usergroup` as a whole, but the set of members which have that relation to the `usergroup`.
88+
Occasionally you will see a subject which has a sub-relation such as `usergroup:admins#members` which refers not just to the `usergroup` as a whole, but the set of members which have that relation to the `usergroup`.
89+
8890
</Callout>
8991

9092
### Subject Relations
@@ -105,7 +107,8 @@ definition group {
105107
```
106108

107109
<Callout type="info">
108-
Subject Relations are useful in RBAC-style permissions systems to grant "roles" to _sets_ of subjects, such as the members of a team.
110+
Subject Relations are useful in RBAC-style permissions systems to grant
111+
"roles" to _sets_ of subjects, such as the members of a team.
109112
</Callout>
110113

111114
### Wildcards
@@ -134,8 +137,8 @@ resource:someresource viewer user:*
134137
Now _any_ user is a `viewer` of the resource.
135138

136139
<Callout type="warning">
137-
Be **very careful** with wildcard support in your schema!
138-
**Only** grant it to read permissions, unless you intend to allow for universal writing.
140+
Be **very careful** with wildcard support in your schema! **Only** grant it to
141+
read permissions, unless you intend to allow for universal writing.
139142
</Callout>
140143

141144
### Naming Relations
@@ -218,7 +221,7 @@ permission can_only_read = reader - writer
218221

219222
#### `->` (Arrow)
220223

221-
Arrows allow for "walking" the heirarchy of relations (and permissions) defined for an object, referencing a permission or relation on the _resulting_ object.
224+
Arrows allow for "walking" the heirarchy of relations (and permissions) defined for an **object** of a subject, referencing a permission or relation on the _resulting_ subject's object.
222225

223226
For example, imagine a schema where a document is found under a folder:
224227

@@ -283,8 +286,38 @@ definition document {
283286
```
284287

285288
<Callout type="info">
286-
It is _recommended_ that the right side of all arrows refer to **permissions**, instead
287-
of relations. This allows for easy nested computation, and is more readable.
289+
It is _recommended_ that the right side of all arrows refer to
290+
**permissions**, instead of relations. This allows for easy nested
291+
computation, and is more readable.
292+
</Callout>
293+
294+
##### Subject relations and Arrows
295+
296+
<Callout type="warning">
297+
Arrows operate on the **object** of the subject(s) found on a `relation`. They
298+
*do not* operate on the relation/permission of a subject, *even if the subject
299+
refers to a relation or permission*.
300+
</Callout>
301+
302+
For example, in:
303+
304+
```
305+
defintion resource {
306+
relation parent: group#member
307+
permission someperm = parent->something
308+
}
309+
```
310+
311+
`parent->something` refers to the `something` permission on the **group**, and `#member` will be ignored for the arrow.
312+
313+
It is recommended to not use arrows over relations that allow for subject relations without noting that
314+
fact via a comment.
315+
316+
<Callout type="info">
317+
Why is this the case? In one word: **performance**. If arrows operated over
318+
the subject's relation or permission, a full LookupSubjects call would be
319+
necessary for the arrow to correctly "walk", which would make these
320+
CheckPermission requests potentially *incredibly* expensive.
288321
</Callout>
289322

290323
### Naming Permissions
@@ -301,15 +334,19 @@ Examples:
301334
| `member` | is member of the object |
302335

303336
<Callout type="info">
304-
You'll note that we also used `member` above in the relation example. Defining `member` as a **permission** might be found when you have multiple "ways" a subject can be a member of a resource, thus changing it from a simple relation to a _computed_ set of subjects.
337+
You'll note that we also used `member` above in the relation example. Defining
338+
`member` as a **permission** might be found when you have multiple "ways" a
339+
subject can be a member of a resource, thus changing it from a simple relation
340+
to a _computed_ set of subjects.
305341
</Callout>
306342

307343
## Comments
308344

309345
### Documentation Comments
310346

311347
<Callout type="info">
312-
It is **highly** recommended to put doc comments on all definitions, relations and permissions.
348+
It is **highly** recommended to put doc comments on all definitions, relations
349+
and permissions.
313350
</Callout>
314351

315352
```zed
@@ -327,7 +364,7 @@ It is **highly** recommended to put doc comments on all definitions, relations a
327364

328365
## Full Example
329366

330-
<InlinePlayground reference="vlduOcwEOmVY"/>
367+
<InlinePlayground reference="vlduOcwEOmVY" />
331368

332369
## Common Patterns
333370

@@ -340,7 +377,7 @@ Both admins and members are considered to have membership in the group.
340377
A role can be applied to individual users and groups.
341378
All individually applied users as well as members for applied groups will have the `allowed` permission.
342379

343-
<InlinePlayground reference="CNe3PXNuhypm"/>
380+
<InlinePlayground reference="CNe3PXNuhypm" />
344381

345382
### Global admin permissions
346383

@@ -350,7 +387,7 @@ In lieu of adding a <code>super_admin</code> relation on every object that can b
350387
Super admin users can be applied to <code>platform</code> and a relation to <code>platform</code> on top level objects.
351388
Admin permission on resources is then defined as the direct owner of the resource as well as through a traversal of the object hierarchy to the platform super admin.
352389

353-
<InlinePlayground reference="m1lRfaaYf9XP"/>
390+
<InlinePlayground reference="m1lRfaaYf9XP" />
354391

355392
### Synthetic relations
356393

@@ -375,15 +412,16 @@ In this example, a folder can have users with read permission.
375412
Additionally, users that can read the parent folder can also read the current folder.
376413
Checking read permission on a folder will recursively consider these relations as the answer is computed.
377414

378-
<InlinePlayground reference="8tE13O7iMM8W"/>
415+
<InlinePlayground reference="8tE13O7iMM8W" />
379416

380417
<Callout type="info">
381-
Note that since `parent->read` calls the same `read` permission, it will form a recursive lookup across the chain of parent folder(s).
418+
Note that since `parent->read` calls the same `read` permission, it will form
419+
a recursive lookup across the chain of parent folder(s).
382420
</Callout>
383421

384422
### Recursive permissions across different resource types
385423

386424
If a non-recursive resource is used as the starting point for a recursive lookup, it is
387425
**very important** that the permission name used on the right side of the arrow is the **same** in both the starting resource type and the parent resource type(s):
388426

389-
<InlinePlayground reference="EWVhjM3vGxE6"/>
427+
<InlinePlayground reference="EWVhjM3vGxE6" />

0 commit comments

Comments
 (0)