Skip to content

Commit 0da85a2

Browse files
dvdksnclaude
andcommitted
sbx: document team-scoped and time-bounded governance policies
Add docs for scoping organization governance policies to specific teams and bounding them with validity windows. Explains org-wide vs team-scoped policies, how a user's effective policies combine (additive allows, absolute denies, org-wide guardrails), and updates the AI Governance API Scope schema with the teams and validity fields. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent ff616c4 commit 0da85a2

3 files changed

Lines changed: 132 additions & 26 deletions

File tree

content/manuals/ai/sandboxes/governance/concepts.md

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,17 @@ Docker sandbox governance is built around two resource types: **policies** and
1111
**rules**.
1212

1313
A **policy** is a named collection of rules that controls sandbox access.
14-
Policies exist at different levels:
14+
Policies exist at two levels:
1515

1616
- **Local**: configured per machine using the `sbx policy` CLI. Applies to
1717
sandboxes on that machine only.
1818
- **Organization**: configured in the Docker Admin Console or via the
19-
[Governance API](/reference/api/ai-governance/). Applies uniformly across every sandbox in the
20-
organization.
21-
- **Team**: applies to sandboxes used by a specific team within an
22-
organization. Coming soon.
19+
[Governance API](/reference/api/ai-governance/). Applies to sandboxes across
20+
the organization. An organization can have several policies, each applying
21+
either org-wide or to specific teams. See [Policy scope](#policy-scope).
2322

24-
When multiple levels are active, organization policies take precedence over
25-
local policies. See [Precedence](#precedence).
23+
When organization governance is active, organization policies replace local
24+
policies entirely. See [Precedence](#precedence).
2625

2726
A **rule** is the unit of access control within a policy. Each rule has:
2827

@@ -34,6 +33,32 @@ A **rule** is the unit of access control within a policy. Each rule has:
3433
Rules are grouped by domain: all rules in a policy must share the same domain,
3534
either `network` or `filesystem`.
3635

36+
## Policy scope
37+
38+
Each organization policy applies either across the whole organization or only
39+
to specific teams. The policy's scope determines which members it applies to:
40+
41+
- **Org-wide**: with no teams assigned, the policy applies to every member of
42+
the organization.
43+
- **Team-scoped**: with one or more teams assigned, the policy applies only to
44+
members of those teams.
45+
46+
Teams are the same [teams](/manuals/admin/organization/manage/manage-a-team.md)
47+
you manage for your organization. A team-scoped policy references the teams it
48+
applies to, and Docker matches those teams against each user's team membership.
49+
Because assignment follows team membership, you can govern an organization with
50+
thousands of users without configuring policies per user.
51+
52+
An organization can mix org-wide and team-scoped policies. A user's effective
53+
policy set is every org-wide policy plus every team-scoped policy for a team
54+
the user belongs to. See [Rule evaluation](#rule-evaluation) for how those
55+
policies combine.
56+
57+
A policy can also be bound in time with a validity window, independent of team
58+
scope. A validity window can set a start time, an end time, both, or neither. A
59+
policy with no validity window is always active while governance is enabled for
60+
the organization.
61+
3762
## Rule syntax
3863

3964
### Network rules
@@ -43,12 +68,12 @@ hostnames, CIDR ranges, or ports.
4368

4469
**Hostname patterns**
4570

46-
| Pattern | Example | Matches |
47-
| ------- | ------- | ------- |
48-
| Exact hostname | `example.com` | `example.com` only, not subdomains |
49-
| Single-level wildcard | `*.example.com` | One subdomain level: `api.example.com` |
50-
| Multi-level wildcard | `**.example.com` | Any depth: `api.example.com`, `v2.api.example.com` |
51-
| Hostname with port | `example.com:443` | `example.com` on port 443 only |
71+
| Pattern | Example | Matches |
72+
| --------------------- | ----------------- | -------------------------------------------------- |
73+
| Exact hostname | `example.com` | `example.com` only, not subdomains |
74+
| Single-level wildcard | `*.example.com` | One subdomain level: `api.example.com` |
75+
| Multi-level wildcard | `**.example.com` | Any depth: `api.example.com`, `v2.api.example.com` |
76+
| Hostname with port | `example.com:443` | `example.com` on port 443 only |
5277

5378
`example.com` and `*.example.com` don't cover each other. Specify both if you
5479
need to match the root domain and its subdomains.
@@ -63,11 +88,11 @@ Both IPv4 and IPv6 notation are supported: `10.0.0.0/8`, `192.168.1.0/24`,
6388
Filesystem rules use the actions `read` and `write`. Resources are host paths
6489
that sandboxes can mount as workspaces.
6590

66-
| Pattern | Example | Matches |
67-
| ------- | ------- | ------- |
68-
| Exact path | `/data` | `/data` only |
69-
| Segment wildcard | `/data/*` | `/data/project`, one path segment only, not subdirectories |
70-
| Recursive wildcard | `/data/**` | `/data/project`, `/data/project/src`, any depth |
91+
| Pattern | Example | Matches |
92+
| ------------------ | ---------- | ---------------------------------------------------------- |
93+
| Exact path | `/data` | `/data` only |
94+
| Segment wildcard | `/data/*` | `/data/project`, one path segment only, not subdirectories |
95+
| Recursive wildcard | `/data/**` | `/data/project`, `/data/project/src`, any depth |
7196

7297
Use `**` when you intend to match a directory tree recursively. A single `*`
7398
only matches within one path segment and won't cross directory boundaries.
@@ -76,15 +101,22 @@ matches only direct children of `~`.
76101

77102
## Rule evaluation
78103

79-
All rules in a policy are evaluated against every request. The outcome follows
80-
two principles:
104+
When organization governance is active, the rules from all of a user's
105+
effective policies (every org-wide policy plus every matching team-scoped
106+
policy) are combined and evaluated together against each request. Evaluation
107+
follows two principles:
81108

82109
**Deny wins.** If any rule matches with `decision: deny`, the request is
83110
denied regardless of any matching allow rules.
84111

85112
**Default deny.** Outbound traffic is blocked unless an explicit allow rule
86113
matches.
87114

115+
Because rules combine across policies, allows are additive (a request is
116+
allowed if any effective policy allows it) and denies are absolute (a request
117+
is blocked if any effective policy denies it). A deny rule in an org-wide
118+
policy therefore acts as a guardrail that no team-scoped policy can override.
119+
88120
These principles apply within whichever policy is active. When organization
89121
governance is active, only organization rules are evaluated; local rules have
90122
no effect.
@@ -101,5 +133,7 @@ whether your organization has governance enabled:
101133
developer machines, and local and kit-defined rules are not evaluated. They
102134
still appear in `sbx policy ls`, but with an `inactive` status.
103135

104-
Within the active policy, deny rules beat allow rules regardless of specificity
105-
or order.
136+
When organization governance is active, all of a user's effective
137+
organization policies combine into a single rule set, where deny rules beat
138+
allow rules regardless of which policy they come from, their specificity, or
139+
their order. See [Rule evaluation](#rule-evaluation).

content/manuals/ai/sandboxes/governance/org.md

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,56 @@ access**. Each rule takes a path pattern and an action (allow or deny).
5454
For path pattern syntax including the difference between `*` and `**`, see
5555
[Policy concepts](concepts.md#filesystem-rules).
5656

57+
## Scope policies to teams
58+
59+
An organization can have more than one policy, and each policy applies either
60+
to the whole organization or to specific teams. Use scoping to give different
61+
parts of the organization different rules: for example, a permissive policy for
62+
a security research team alongside a stricter default for everyone else.
63+
64+
When you create or edit a policy in the Admin Console, the **Scope** setting
65+
controls who it applies to:
66+
67+
- Leave the team list empty to make the policy org-wide. It applies to every
68+
member of the organization.
69+
- Add one or more teams to scope the policy to those teams. It applies only to
70+
members of the listed teams.
71+
72+
Teams are the same [teams](/manuals/admin/organization/manage/manage-a-team.md)
73+
you manage for your organization, so assignment follows existing team
74+
membership. This lets you manage policies for an organization with thousands of
75+
users without configuring anything per user. When team membership changes in
76+
your identity provider, the policies a user receives change with it.
77+
78+
### How org-wide and team-scoped policies combine
79+
80+
A user receives every org-wide policy plus every team-scoped policy for a team
81+
they belong to. The rules from all of these policies are combined and evaluated
82+
together:
83+
84+
- **Allows are additive.** A request is allowed if any of the user's effective
85+
policies allow it.
86+
- **Denies are absolute.** A request is blocked if any of the user's effective
87+
policies deny it.
88+
89+
Because deny always wins, a deny rule in an org-wide policy acts as a guardrail
90+
that team-scoped policies can't override. Use org-wide policies for rules that
91+
must apply everywhere, and team-scoped policies to grant additional access to
92+
specific teams.
93+
94+
### Validity windows
95+
96+
A policy can also be limited to a time window, independent of its team scope.
97+
Set a start time, an end time, both, or neither when you create or edit the
98+
policy. A policy with no validity window is always active while governance is
99+
enabled. Use a validity window for time-bound exceptions, such as temporary
100+
access granted for the duration of a project.
101+
57102
## Precedence
58103

59-
Within the active policy, deny rules beat allow rules. If a domain matches both,
60-
it's blocked regardless of specificity. Outbound traffic is blocked unless a
61-
rule allows it.
104+
Deny rules beat allow rules. If a resource matches both an allow and a deny, in
105+
the same policy or across a user's effective policies, it's blocked regardless
106+
of specificity. Outbound traffic is blocked unless a rule allows it.
62107

63108
When organization governance is active, local rules are not evaluated. Only
64109
organization rules set in the Admin Console determine what is allowed or

content/reference/api/ai-governance/api.yaml

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,11 @@ components:
488488

489489
Scope:
490490
type: object
491-
description: Restricts the policy to specific profiles or teams. Empty or absent lists mean the policy applies org-wide.
491+
description: >
492+
Restricts the policy to specific profiles or teams, and optionally to a
493+
time window. An empty or absent `teams` list means the policy applies to
494+
every member of the organization. A non-empty `teams` list means the
495+
policy applies only to members of the listed teams.
492496
properties:
493497
profiles:
494498
type: array
@@ -498,8 +502,31 @@ components:
498502
- ["security"]
499503
teams:
500504
type: array
505+
description: >
506+
Identifiers of the teams (organization groups) the policy applies
507+
to. Each value must be a valid group in the target organization;
508+
requests referencing unknown identifiers are rejected.
501509
items:
502510
type: string
511+
validity:
512+
type: object
513+
description: >
514+
Optional time window during which the policy is active. Both fields
515+
are optional; a policy with neither set is always active while
516+
governance is enabled for the organization.
517+
properties:
518+
notBefore:
519+
type: string
520+
format: date-time
521+
description: The policy is not active before this timestamp.
522+
examples:
523+
- "2026-04-22T00:00:00Z"
524+
notAfter:
525+
type: string
526+
format: date-time
527+
description: The policy is not active after this timestamp.
528+
examples:
529+
- "2026-07-22T00:00:00Z"
503530

504531
AllowlistV0:
505532
type: object

0 commit comments

Comments
 (0)