-
Notifications
You must be signed in to change notification settings - Fork 46
chore: add documentation of LR debugging #547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+122
−19
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
854b335
chore: add documentation of LR debugging
tstirrat15 e3875fe
chore: remove outdated documentation
tstirrat15 5673b95
Update app/spicedb/modeling/recursion-and-max-depth/page.mdx
tstirrat15 6ea93dc
Update app/spicedb/modeling/validation-testing-debugging/page.mdx
tstirrat15 4357fe6
Update app/spicedb/modeling/validation-testing-debugging/page.mdx
tstirrat15 44e6e2a
chore: add debug flag section
tstirrat15 e352ac3
chore: a few fixes
miparnisari File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| import { Callout } from "nextra/components"; | ||
|
|
||
| # Cyclical Relationships and Traversal Limits | ||
|
|
||
| SpiceDB answers permissions questions by traversing a **tree** constructed from your [schema] (structure) and [relationships] (data). | ||
|
|
@@ -188,6 +190,106 @@ If the subject is found before the traversal hits the cycle or exceeds the depth | |
|
|
||
| However, if the subject is **not** found, the traversal continues until it hits the depth limit and returns an error. | ||
|
|
||
| ### What do I do about a max depth error on LookupResources? | ||
|
|
||
| _Note: the following debug behavior was added in SpiceDB 1.52.0_ | ||
|
|
||
| Consider the following validation file: | ||
|
|
||
| ```yaml | ||
| schema: |- | ||
| definition user {} | ||
|
|
||
| definition folder { | ||
| relation viewer: user | ||
| relation parent: folder | ||
| permission view = parent->view + viewer | ||
| } | ||
|
|
||
| definition resource { | ||
| relation folder: folder | ||
| permission view = folder->view | ||
| } | ||
| relationships: |- | ||
| folder:a#viewer@user:someuser | ||
| folder:a#parent@folder:b | ||
| folder:b#parent@folder:a | ||
| ``` | ||
|
|
||
| Note that the `parent` relation on the `folder` definition is recursive, and that we've written a `parent` relationship from `folder:a` to `folder:b` and vice versa, creating a cycle. | ||
|
|
||
| If you run `zed import` on this file, and then run `zed permission lookup-resources resource view user:someuser`, you'll get a `max depth exceeded` error: | ||
|
|
||
| ``` | ||
| rpc error: code = FailedPrecondition desc = max depth exceeded: this usually indicates a recursive or too deep data dependency. | ||
| ``` | ||
|
|
||
| This indicates that either a branch was too deep or a cycle was encountered as SpiceDB was walking the set of reachable resources. You can re-run the request with `--debug` to get a stack trace that shows the cycle: | ||
|
|
||
| ```sh | ||
| zed permission lookup-resources resource view user:someuser --debug | ||
| ``` | ||
|
|
||
| You'll get output that looks like this: | ||
|
|
||
| ``` | ||
| The following resource/relation pairs were found in a cycle in LookupResources: | ||
|
|
||
| - folder:a#view | ||
|
|
||
| You will need to delete a relationship to break the cycle. | ||
| To find the pairs involved in the cycle, issue a check from the resource to itself across the relation. | ||
| For example: | ||
|
|
||
| zed permission check folder:a view folder:a --explain | ||
|
|
||
| ``` | ||
|
|
||
| If you call `zed permission check folder:a view folder:a --explain`, you'll get output like the following: | ||
|
|
||
| ``` | ||
| ! folder:a view (8.434693ms) | ||
| └── ! folder:b view (8.143951ms) | ||
| └── ! folder:a view (cycle) (7.970042ms) | ||
| ``` | ||
|
|
||
| Some notes on reading the output: | ||
|
|
||
| - The lines should be read as resources with the relation connecting them to the previous pair. For example, the line marked by `(cycle)` can be read as "there's a `view` relation between `folder:a` and `folder:b`." | ||
| - The relation can be a schema relation, a schema permission, or a schema subject relation. Notice that in the line marked by `cycle`, the relation is `view`, corresponding to the `view` permission on the `folder` definition in the schema. This means that you might need to do some translation to connect the relation in a line to a concrete relationship. | ||
| - The `(cycle)` marks the endpoints where a resource that is a member of a cycle was seen for the second time. It does _not_ mean that the marked relation is the offending relation, just that everything between the marks is a member of the cycle. You'll need to think about which relationships are written where to understand what needs to change in your business logic to avoid the cycle. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the other two bullets feel useless to me; i'd get rid of them. the third is the bullet that is important. |
||
|
|
||
| In this case, we can see in the output that `folder#view` is going back and forth between `folder:a` and `folder:b`, and from the permission definition we can see that `folder#view` is defined in terms of `viewer` and `parent`. `viewer` can't be a part of a cycle, because it points at a `user` and there's no outgoing relation from the `user definition.` This means that `parent` is the offending relation, and we can remove one of the `folder#parent` relationships to break the cycle. | ||
|
|
||
| #### Limitations | ||
|
|
||
| ##### Schema Structure | ||
|
|
||
| If your schema has certain structures, calling `zed permission check --explain` may return "no permission" rather than showing you a cycle. For example, if we changed the folder definition in the schema above to the following: | ||
|
|
||
| ``` | ||
| definition folder { | ||
| relation viewer: user | ||
| relation editor: user | ||
| relation folder: parent | ||
| permission view = (viewer + parent->view) & editor | ||
| } | ||
| ``` | ||
|
|
||
| to indicate that the user must also be an editor in order to view, `folder:a#view@folder:a` can never be satisfied, because it can never satisfy the `& editor` clause of the permission. Intersection arrows and certain negations may result in similar behavior. | ||
|
|
||
| One potential workaround is to make a check with the desired terminal subject (usually a `user`) on that object: | ||
|
|
||
| ```sh | ||
| zed permission check folder:a view user:someuser --explain | ||
| ``` | ||
|
|
||
| This will work if the permission walk enters the cycle and then cannot exit, but will potentially terminate normally if there's a permission path that terminates after branching off of the cycle. | ||
|
|
||
| ##### Caveats | ||
|
|
||
| If your schema has caveats and there are caveats along the LookupResources path, you'll also need to recover the original caveat context and submit it in the request. | ||
|
|
||
| ### How do I prevent cycles when writing relationships? | ||
|
|
||
| Before writing a relationship that could create a cycle, use `CheckPermission` to verify the relationship won't create a loop. | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i feel iffy about pasting the literal error here, which can change in the future. why not just say "use --debug which will give you more information"?
and the following paragraphs are more about
zed permission check --explainthan about LR 😅