Last updated 2026-06-29
Sharing Resources
This guide models direct per-object sharing — "share this task with dad" — and shows how a single resource combines direct shares, group shares, and parent inheritance into one effective access set.
What you'll learn: how to grant and revoke access on an
individual resource with one tuple each, how the three sources of access
union together, and which WriteRelationTuples /
ReadRelationTuples calls back them.
Direct sharing: one tuple per grant
A directly-shared resource has no parent workspace — access is whatever was granted on the object itself. This is the personal-assistant pattern: a task a user shares with specific people.
resource:task#viewer@user:dad # dad can viewresource:task#editor@user:partner # partner can edit
Subjects here are concrete users, so these are plain this() leaf
tuples — no rewrite needed for the grant to take effect. Write them with
AuthzService.WriteRelationTuples:
curl -X POST http://localhost:8080/workspace.v1.AuthzService/WriteRelationTuples \ -H "Authorization: Bearer $WS_SERVICE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"updates":[ {"op":"INSERT","tuple":{ "namespace":"resource","object_id":"task","relation":"viewer", "subject":{"user_id":"dad"}}} ]}'Then "can dad view this task?" is a single Check:
curl -X POST http://localhost:8080/workspace.v1.AuthzService/Check \ -H "Authorization: Bearer $WS_SERVICE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"namespace":"resource","object_id":"task","relation":"viewer","subject_user_id":"dad"}'{ "allowed": true }Three sources, one union
The viewer relation on a resource is a union of everything that
can confer view access:
viewer := union(this(), computed("editor"), tupleToUserset("parent", "member"))So a single document can draw viewers from all three at once:
resource:doc#viewer@user:dad # 1. direct share with a personresource:doc#viewer@group:family#member # 2. share with a whole groupresource:doc#parent@workspace:W#member # 3. inherit from a parent workspace| Source | Tuple | Resolved by |
|---|---|---|
| Direct (person) | resource:doc#viewer@user:dad | this() leaf |
| Group | resource:doc#viewer@group:family#member | this() leaf → recurse into the group |
| Inherited | resource:doc#parent@workspace:W#member | tupleToUserset("parent","member") |
Check(resource, doc, viewer, <user>) returns
allowed if any source grants it: the user is shared
directly, or is a member of family (resolved transitively through
the group), or is a member of workspace W. You don't choose a
strategy per resource — mix them freely on the same object.
Revoking access
Revoke is the inverse of share: delete the exact tuple. A
DELETE op removes a single grant; access from the other two
sources is unaffected.
curl -X POST http://localhost:8080/workspace.v1.AuthzService/WriteRelationTuples \ -H "Authorization: Bearer $WS_SERVICE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"updates":[ {"op":"DELETE","tuple":{ "namespace":"resource","object_id":"task","relation":"viewer", "subject":{"user_id":"dad"}}} ]}'
Insert and delete can be batched in one call — the updates array
is applied together — so re-sharing (revoke from one user, grant to another)
is a single atomic request.
Seeing what is shared
To list the raw grants directly stored on a resource — for a
share-management UI — use ReadRelationTuples. It returns the
stored tuples matching an exact filter, with no rewrite
evaluation: it shows the direct viewers and any group/parent subjects you
wrote, but not the users those usersets expand to.
curl -X POST http://localhost:8080/workspace.v1.AuthzService/ReadRelationTuples \ -H "Authorization: Bearer $WS_SERVICE_TOKEN" \ -H "Content-Type: application/json" \ -d '{"namespace":"resource","object_id":"task","relation":"viewer"}'ReadRelationTuples is a raw store read — use it to render "who is
this shared with" exactly as written. To decide whether a specific user may
act, always use Check, which expands groups and inheritance. To
see the fully-expanded set of who has access, use Expand (see
Check & Expand).
Where to next
- Check & Expand — evaluate, debug, and batch writes
- Groups & Nesting — the group shares used above
- Personal-Assistant App — the full worked share scenario