Skip to main content
Your progress
0 of 7 complete0%
T4 / M4.1 / L4 OF 6 / Architect LEVEL / 9 min

Team-scoped access

Outcome

By the end of this lesson, you will be able to configure team-scoped access using the allResources and resourceIds fields, distinguish team scoping from role scoping, and reason about the three-state scope model (nil / empty / list).


PrerequisitesM4.1.L1-L3 (policy table, system roles, custom roles)
Time9 minutes

1. Concept

A role says what somebody may do. A team scope says what to.

They are separate questions, and mixing them up is the most common permissions mistake we see. Somebody grants a broader role because a person could not see something, when the thing they could not see was a scope problem and the role was already right.

Team scoping restricts a user’s effective policy set to a subset of the org’s resources. A user who holds Editor as their role on the platform team can apply Editor actions only to resources assigned to that team; the rest of the estate is invisible to them. The role has to come through the team membership: a role assigned to the user org-wide covers every resource and overrides the team scope.

Terminal window
SCOPE FLAG MEANING
───────────────────────────────────────────────────────
allResources=true The user can act on ALL resources in the org.
Used for cross-team roles (Admin, FinOps Lead).
allResources=false The user is restricted to a specific set.
Then resourceIds[] determines that set.
resourceIds=[...] The explicit list of resource UIDs the user
can see and (per role) act on. Computed at
request-time from team membership.

How team-scoped access works in practice

A typical setup:

Terminal window
USER: jane@platform.com
TEAMS: [platform], with Editor as her role on that team
(no org-wide role)
SCOPE FIELDS (computed):
allResources = false
resourceIds = [resources assigned to the platform team] +
[members of resource groups assigned to platform]
EFFECT when Jane logs in:
Inventory page filtered to platform's resources only
Recommendations only on platform's resources
Audit log whole org (not narrowed by team)
Org-wide rollups hidden or aggregated without other teams
Cost dashboards scoped to platform spend

The scope follows from team membership. Resources assigned to the platform team (or sitting in a resource group assigned to it) are scoped to Jane. Tags play no part. A new resource becomes visible to Jane once someone assigns it to the team or adds it to one of the team’s groups; no role re-assignment needed.

The three-state scope model

ZopNight’s scope field has three valid states, each with distinct database-level behavior:

Terminal window
STATE SQL EQUIVALENT MEANING
──────────────────────────────────────────────────────────────────
nil (null) no WHERE clause User sees everything.
Equivalent to allResources=true.
[] (empty) WHERE id IN () User sees nothing.
Total isolation. Happens for a
member of a team that has no
resources or groups yet.
[uid1, uid2,…] WHERE id IN (uid1,...) User sees only listed
resources. The normal
team-scoped state.

The empty-list state is intentional: it is the safe default for a team member whose team owns nothing yet. They can log in and see the product structure, but no data leaks until resources or groups are assigned to the team. Without this state, an empty team would either grant everything (insecure) or fail logins (bad UX). Note the opposite case: a newly invited user given a role directly, with no team, gets nil and sees everything.

Team scoping vs custom roles

Terminal window
PROBLEM SOLUTION
──────────────────────────────────────────────────────────────
"Engineer can do Editor actions Team scoping. Role stays Editor;
but only on their team's stuff" scope restricts the data.
"Engineer can do Editor actions Custom role. Edit the actions,
but cannot apply recommendations" not the data scope.
"Engineer can do Editor actions BOTH. Custom role for the action
on their team's stuff and cannot restriction; team scope for the
apply recommendations" data restriction.

This split is what makes the model composable. The role describes capability; the scope describes visibility. Combining them lets you express arbitrary “role × team” matrices without exploding role count.

Cross-team users

For practitioners who legitimately need to span multiple teams (a FinOps lead reviewing all teams’ spend, a security auditor investigating an incident across teams):

Terminal window
OPTION 1: Multiple team memberships
jane@finops.com
teams: [platform, product, data]
resourceIds = union of all three teams' resources
Pro: bounded view (still excludes unassigned teams)
Con: must add team manually as new teams are created
OPTION 2: Admin role
jane@finops.com
role: Admin
allResources = true
Pro: automatic visibility of new teams
Con: also grants RBAC-management capability; usually too broad
for FinOps practitioners
OPTION 3: Custom "Cross-team Viewer" role
Custom role with view-only across operational entities
Combined with allResources=true
Pro: cross-team visibility without RBAC-management power
Con: requires custom-role design (L3)

Most customers settle on option 3 for FinOps leads and option 2 for true org admins. Option 1 is brittle but occasionally right when a practitioner truly only needs two or three teams.

Resource discovery and team scope

When a new resource is discovered (cloud-account sync), it belongs to no team. It joins a team’s scope in one of two ways:

Terminal window
WAY WHERE
──────────────────────────────────────────────────────────
1. Assigned to the team directly Team page, assign resources
2. Member of a group the team owns Resource group assigned to the team
(otherwise) Stays in the org-wide pool

Tags and cloud accounts do not assign team scope. Unassigned resources are visible only to users with allResources=true. This is intentional: it surfaces ownership gaps. A team-scoped user simply does not see the unassigned resource until someone assigns it. Assigning groups rather than single resources is the low-effort path: anything later added to the group comes along.

How ZopNight uses the scope model

The two checks happen in different places:

Terminal window
client → gateway policy check (role → can action), 403 if denied
→ backend scope lookup (which resources may this user see?)
and the query is filtered to that set

The gateway only answers “may this user take this action at all?”. Each backend service then asks for the user’s scope and filters its own query, so an out-of-scope resource simply is not in the results. The role-permission 403 fires when the user is trying an action they cannot perform anywhere, not when the resource is outside their scope.


2. Demo

A mid-size org’s structure after a clean team scope design:

Terminal window
ORG: Acme Corp
─────────────────────────────────────────────────────────────
TEAMS:
platform (6 engineers + 1 lead) scope=platform
product (12 engineers + 1 lead) scope=product
data (4 engineers + 1 lead) scope=data
CROSS-TEAM ROLES:
finops-lead (1 person) Custom "Cross-team Viewer"
+ recommendation:update on all
security (2 people) Custom "Compliance Auditor"
+ audit-log:view on all
org-admin (2 people) Admin (allResources=true)
EFFECT:
Platform engineer sees only platform's resources
FinOps lead sees all teams' resources, can apply recs
Security can view all audit logs, modify nothing
Org admins can do everything (rotation, role mgmt)
UNASSIGNED RESOURCES:
Visible to org-admins and security; invisible to team-scoped users
Surfaces ownership gaps automatically

3. Hands-on (6 min)

Map your org’s structure:

Terminal window
TEAMS (list):
__________________________________________________________
PER-USER scope decisions:
USER ROLE SCOPE (team / cross / all)
__________________ ___________ ___________________________
__________________ ___________ ___________________________
__________________ ___________ ___________________________
CROSS-TEAM USERS: for each, choose Option 1/2/3 from the concept:
__________________ Option: ___ (why?)
__________________ Option: ___ (why?)
UNASSIGNED RESOURCES (estimated count): _____
Action plan: assign them to a team or accept them in the org-wide pool

The unassigned-resource count is the team-scope hygiene number to track quarterly. Healthy orgs trend toward zero.


4. Knowledge check

Q1

A user is a member of the platform team (Editor on that team) and has no org-wide role. What do they see?

A. Only resources assigned to platform, directly or through the team’s resource groups
B. Nothing at all, since team members are restricted by default
C. Every resource in the whole of the organisation, without any exception
D. Only those resources that they themselves originally provisioned themselves

Show answer

Correct: A. resourceIds is computed at request time from the team’s assigned resources plus the members of its assigned groups. Tags play no part. A new resource becomes visible once it is assigned to the team or added to one of its groups.

Q2

A FinOps lead needs to see cost across all teams but should not manage RBAC. Best approach:

A. Grant them the full Admin role right across every team in the organisation
B. Multiple team memberships, one for every single team in the whole organisation at once
C. The Editor role, with a manual filter applied on every single report
D. Custom “Cross-team Viewer” role (view-only across operational entities) with allResources=true

Show answer

Correct: D. The role excludes role/user/cloud-account management. Scope grants visibility; role limits capability. The combination of a narrow custom role and broad scope is the cleanest way to express “broad view, narrow capability.” Admin would over-grant; multi-team is brittle as teams are added.

Q3

The scope state [] (empty list) means:

A. That all of the resources are visible
B. Total isolation: user sees no resources
C. A bug in the scope computation code
D. It is precisely equivalent to nil

Show answer

Correct: B. It happens for a member of a team that has no resources or groups assigned yet. It produces a WHERE id IN () query: valid SQL, zero results. Different from nil (no filter, sees everything), which is what a user with a directly assigned role and no team gets.


5. Apply

Manage team scopes on the Teams page. Add users to a team with a role on that team; assign resources to the team, or assign resource groups so their members come along.

Quarterly hygiene: review the count of resources assigned to no team. Trending up is a signal of weakening team-scoping discipline.


Glossary terms touched

Team scope


Start with the bill.

Foundations takes about five hours. The first lesson is nine minutes.

Free curriculum. No paywall. 290 lessons across 7 courses, plus an optional 24-lesson beginner course. Browse every course without an account; a free account opens the lessons, saves your progress and opens the exams for three publicly verifiable credentials. Read it on the train, take the exam on a Saturday, list the credential on your résumé Monday.

5h median time to finish Foundations
free account, every course, no paywall
3 certifications, each with a public verifier
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·