Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion docs-site/public/openapi/workspace-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1848,7 +1848,9 @@ components:
items:
$ref: '#/components/schemas/workspace.v1.UsersetTree'
title: children
description: 'For UNION / INTERSECTION / EXCLUSION nodes: the child subtrees.'
description: |-
For UNION / INTERSECTION nodes: the child subtrees. Empty for EXCLUSION
(which uses `include` / `exclude` instead).
expanded:
title: expanded
description: The userset this node expands.
Expand All @@ -1857,6 +1859,16 @@ components:
type: boolean
title: wildcard
description: 'For LEAF nodes: true if the public wildcard subject is present.'
include:
title: include
description: |-
For EXCLUSION nodes only: the include leg (the base set) and the exclude
leg (subjects removed from it). The effective set is `include` minus
`exclude`. Unset for every other node type.
$ref: '#/components/schemas/workspace.v1.UsersetTree'
exclude:
title: exclude
$ref: '#/components/schemas/workspace.v1.UsersetTree'
title: UsersetTree
additionalProperties: false
workspace.v1.Workspace:
Expand Down
23 changes: 21 additions & 2 deletions docs-site/public/proto/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4352,7 +4352,8 @@ <h3 id="workspace.v1.UsersetTree">UsersetTree</h3>
<td>children</td>
<td><a href="#workspace.v1.UsersetTree">UsersetTree</a></td>
<td>repeated</td>
<td><p>For UNION / INTERSECTION / EXCLUSION nodes: the child subtrees. </p></td>
<td><p>For UNION / INTERSECTION nodes: the child subtrees. Empty for EXCLUSION
(which uses `include` / `exclude` instead). </p></td>
</tr>

<tr>
Expand All @@ -4369,6 +4370,22 @@ <h3 id="workspace.v1.UsersetTree">UsersetTree</h3>
<td><p>For LEAF nodes: true if the public wildcard subject is present. </p></td>
</tr>

<tr>
<td>include</td>
<td><a href="#workspace.v1.UsersetTree">UsersetTree</a></td>
<td></td>
<td><p>For EXCLUSION nodes only: the include leg (the base set) and the exclude
leg (subjects removed from it). The effective set is `include` minus
`exclude`. Unset for every other node type. </p></td>
</tr>

<tr>
<td>exclude</td>
<td><a href="#workspace.v1.UsersetTree">UsersetTree</a></td>
<td></td>
<td><p> </p></td>
</tr>

</tbody>
</table>

Expand Down Expand Up @@ -4780,7 +4797,9 @@ <h3 id="workspace.v1.UsersetTree.NodeType">UsersetTree.NodeType</h3>
<tr>
<td>NODE_TYPE_EXCLUSION</td>
<td>4</td>
<td><p>EXCLUSION nodes carry exactly two children: [include, exclude].</p></td>
<td><p>EXCLUSION encodes its operands EXPLICITLY in `include` / `exclude`, NOT
in `children`: the effective set is `include` minus `exclude`. `children`
is empty for EXCLUSION nodes.</p></td>
</tr>

</tbody>
Expand Down
12 changes: 10 additions & 2 deletions docs-site/public/proto/workspace-v1.proto
Original file line number Diff line number Diff line change
Expand Up @@ -651,19 +651,27 @@ message UsersetTree {
NODE_TYPE_UNION = 1;
NODE_TYPE_LEAF = 2;
NODE_TYPE_INTERSECTION = 3;
// EXCLUSION nodes carry exactly two children: [include, exclude].
// EXCLUSION encodes its operands EXPLICITLY in `include` / `exclude`, NOT
// in `children`: the effective set is `include` minus `exclude`. `children`
// is empty for EXCLUSION nodes.
NODE_TYPE_EXCLUSION = 4;
}
NodeType type = 1;
// For LEAF nodes: the concrete subjects and usersets at this node.
repeated string user_ids = 2;
repeated SubjectSet sets = 3;
// For UNION / INTERSECTION / EXCLUSION nodes: the child subtrees.
// For UNION / INTERSECTION nodes: the child subtrees. Empty for EXCLUSION
// (which uses `include` / `exclude` instead).
repeated UsersetTree children = 4;
// The userset this node expands.
SubjectSet expanded = 5;
// For LEAF nodes: true if the public wildcard subject is present.
bool wildcard = 6;
// For EXCLUSION nodes only: the include leg (the base set) and the exclude
// leg (subjects removed from it). The effective set is `include` minus
// `exclude`. Unset for every other node type.
UsersetTree include = 7;
UsersetTree exclude = 8;
}

message ExpandResponse { UsersetTree tree = 1; }
Expand Down
10 changes: 7 additions & 3 deletions docs/authorization-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,13 @@ Traversal must carry a visited-set / depth bound so cyclic group nesting cannot
loop (see ADR-0003).

`Expand(namespace, object_id, relation)` is the set-valued sibling: instead of
testing one user, it returns the effective **`UsersetTree`** — `UNION` nodes
with child subtrees, and `LEAF` nodes carrying concrete `user_ids` and nested
`sets`. Use it to answer "who has access?" and for audit.
testing one user, it returns the effective **`UsersetTree`** — `UNION` /
`INTERSECTION` nodes with child subtrees (in `children`), and `LEAF` nodes
carrying concrete `user_ids` and nested `sets`. An `EXCLUSION` node encodes its
operands **explicitly** in the dedicated `include` and `exclude` fields (the
effective set is `include` minus `exclude`); it does **not** use `children` and
relies on no positional convention. Use it to answer "who has access?" and for
audit.

`ReadRelationTuples` is **not** a permission check — it returns raw stored
tuples matching an exact filter, with no rewrite evaluation. Use `Check` for
Expand Down
Loading
Loading