Since Tesseral's data model is that users belong-to organizations, anytime you have a user, an organization is also available to you (e.g. in the context of a JWT's claims, or an API call to `api.tesseral.com/v1/users/user_...`, etc):
For authz checks, you have a similar denormalization when you use Tesseral's RBAC. When a user gets an access token, those access tokens have a list of `actions` that the user is allowed to carry out. All of our SDKs have a `hasPermission` function that basically just `accessToken.actions.contains(...)`:
e.g. Go: https://pkg.go.dev/github.com/tesseral-labs/tesseral-sdk-go@...
Again in Go, here's the data type for access tokens:
https://pkg.go.dev/github.com/tesseral-labs/tesseral-sdk-go#... (organization lives in .Organization, list of permissions lives in .Actions)
So we do a little bit of denormalization whenever we mint an access token, but in exchange your code doesn't need to do any network hops to get an organization or do a permission check. (Access tokens are ES256-signed, and our SDKs handle caching the public keys, so that network hop is very infrequent.)
Oh nice, that seems ideal. Good stuff.