nextcloud / nextcloud/circles

To discuss: Nesting teams, evil or not?

Open
#2,786 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

0. Needs triage enhancement feedback-requested
Dominant language
JavaScript
Stars
177
Forks
68
Avg merge
2d 22h
Merged PRs (30d)
60

Description

Currently, a team can be a member of a team. There are use cases for this, but it can also cause some issues, in particular, it can reduce the transparency around ownership. I will use the term 'sub team' going forward for these teams-that-are-member-of-another-team.

What does it do?

If you add Team A as a member (subteam) of Team B, you can set the role of Team A as a block. Access to Team B's resources is granted to all members of the subteam, Team A, under the constraints of the role.

What can nesting do?

Everything below can also be done by adding people one by one and putting in more time to manage the teams. But subteams make these a lot easier and more intuitive. Some basic use cases for subteams:

1. Let a team lead manage their own people

The Sales Director Europe owns Sales Europe and its teamfolder. She does not want to hand out access herself every time someone joins or leaves a sub-team, and the team leads don't want to file a ticket with IT or HR for it.

So New Accounts Europe sits inside Sales Europe. Its lead adds a new hire to New Accounts Europe — that person now also reaches everything in Sales Europe. Nobody had to touch Sales Europe itself.

This is specifically for day-to-day churn (someone switches to another account, a contractor joins for six months), not about formal org changes that HR handles anyway.

2. Give the sub-team a space the parent can't see

The Customer 1 account team includes people from sales, sales engineering and marketing. The engineers on it want a folder for technical drafts and internal assessments that the rest of the account team has no need reading.

Customer 1 Engineering inside Customer 1: its own teamfolder, its own smaller membership. The engineers still get everything from Customer 1; the sales people don't get the engineering folder.

3. Build a big team out of existing smaller ones

All Sales should cover everyone in sales worldwide. Instead of a list of 200 names that someone has to keep correct, you add Sales Europe, Sales US and Sales APAC as members. The big team is now assembled, but maintained in a distributed way.

4. Use one team in several places

The Design team is part of Engineering. The conference team in marketing also needs designers.

Add the whole Design team to Conference Orga rather than picking out three designers by hand. New designer hired → they have conference access. Designer leaves the company → access gone, everywhere, in one step. That last part is the security argument: one place to remove someone, instead of hunting through every team they were ever added to.

The trade-off is that it's all-or-nothing — every designer gets in. If only a subset should, make a Conference Design sub-team instead, or just add the individuals.

(3 and 4 are the same mechanism seen from two directions: don't keep a second copy of a list that already exists.)

5. Same team, different permissions in different places.

Design is a member of Product A as editor and of Marketing read-only. One team, multiple access levels. Can of course also be done by giving them just access to the appropriate resources - but if you restrict access to team resources strictly to members, you'd either be managing a lot of ppl manually, or allow nesting.

When not to nest

Customer 1 is a member of nothing. Members come from sales, sales engineering, marketing and engineering, but the team hangs free.

If it were nested under Sales, everyone on it would inherit access to the whole sales department — including the marketing and engineering people. Sensitive key-account material would spread exactly where it shouldn't. Cross-functional teams are usually the case where you want membership flat.

What does the competition do?

Microsoft 365 / Teams: no nesting. Security groups and distribution lists nest fine, but Microsoft 365 Groups cannot be nested inside another Microsoft 365 Group. Each is a flat membership object tied to one mailbox, one SharePoint site, one team, and Entra ID blocks unified groups from being members of other unified groups. Since Teams membership is an M365 Group, there is no nesting in Teams. Workarounds are dynamic groups (attribute-based rules, needs Entra ID P1/P2) or PowerShell scripts that flatten. Adding a group to a team performs a one-time expansion into individual users, but no ongoing sync. It is a long-standing complaint, on the roadmap since ~2020, still not shipped.

Google Workspace: yes, and it works properly. Share content with a group that contains a subgroup, and the subgroup's members get the same access as the parent group's members. Remove someone from a group and they lose access to everything shared with it. The same group can be a member of multiple shared drives, with a different access level per drive. Similar to our approach of "permissions set at the membership level"

Atlassian kind of hybrid. Nested structure is not preserved on sync; nested groups are converted to a flat structure while retaining all memberships, so members of a nested group become members of both groups and inherit permissions from both. So hierarchy is kept in the external user directory but flattened inside Atlassian.

LDAP/IDP: and of course most IDP's, perhaps app, do nesting which is heavily used in organisations.

For discussion

The mess with Microsoft

Microsoft's mess with regards to nesting has less to do with the concept, and more with the implementation.

A parent group may show it contains another group, but Exchange, Teams roster management, SharePoint permissions, licensing, and Conditional Access each handle that relationship differently. Some expand nested groups, some ignore them, some support nesting only for specific group types. Thus nested groups can obscure who really has access, complicate audits, and create security gaps.

So the lesson is: be consistent. We have to make sure all apps treat subteams/nested teams the same way.

Transparency

How can a manager maintain control? Within the current mechanism - by joining each sub-team. But is that needed? There's a difference between reading the content and knowing the team exists. A department head usually doesn't need to read the engineers' technical drafts. Rather, they need to know which subteams exist under their department, who's in them, what folders they hold, and that nobody has walked off with access they shouldn't have.

What would be needed is an effective-membership / team-overview view for team owners/admins, that covers all teams under them. Especially if you create a more complicated structure, like below:

Example structure
General (dept. group)                              [GF] General
│
├── Sales (dept. group)                             [GF] Sales
│     │
│     ├── Sales Europe (team)                        [TF] Sales Europe
│     │     member of: Sales
│     │     │
│     │     └── New Accounts Europe (team)            [TF] New Accounts Europe
│     │           member of: Sales Europe, Sales
│     │
│     └── Sales-Engineering (team)                   [TF] Sales-Engineering
│           member of: Sales
│
├── Marketing (dept. group)                         [GF] Marketing
│     │
│     └── Conference Orga (team)                     [TF] Conference
│           member of: Marketing
│
└── Engineering (dept. group)                       [GF] Engineering


Customer 1 (team, standalone)                          [TF] Customer 1
  member of:       — none (deliberately not nested, avoids leaking
                      the account team's access into Sales/Eng/Marketing)
  members drawn from: New Accounts Europe, Sales-Engineering,
                       Marketing, Engineering

Legend: [GF] = groupfolder   [TF] = teamfolder
Membership detail
Team / group Type Folder Member of (parent) Notes
General dept. group GF whole company
Sales dept. group GF
Marketing dept. group GF
Engineering dept. group GF
Sales Europe team TF Sales region team
New Accounts Europe team TF Sales Europe, Sales inherits Sales Europe access via nesting
Sales-Engineering team TF Sales
Conference Orga team TF Marketing one-off/recurring event team
Customer 1 team TF (none) members pulled directly from New Accounts Europe, Sales-Engineering, Marketing, Engineering — not nested, to keep key-account data out of the wider dept. teams

For a matrix organization, things are even simpler. There is little need for nesting there.

Example Matrix organization
  • Functional teams (discipline home, own resources): Engineering, Design, QA, Marketing, Sales
  • Product teams (cross-functional, project resources): Product A, Product B, Product C

Alice (an engineer staffed on Product A) is a direct member of both Engineering and Product A. There is no nesting and no hierarchy. She gets Engineering's teamfolder (code standards, internal eng docs) via one membership, and Product A's teamfolder (specs, project files) via the other. Bob (designer, also on Product A) is in Design + Product A. Neither team contains the other.

Risks

It makes sense to somehow show the hierarchy of teams. As admin, you might also want to be aware of sub team structure.

But often the question isn't so much about structure but more like "what can Alice reach, and by which path?" That's a per-user reverse lookup, a different feature. Second question: "who can reach this folder?". These we have to find answers to.

Here some risks that nesting brings, and ideas on how to resolve them.

1. Adding a team is a one-click action with invisible blast radius. "Add Design to Product A" reads like adding one thing. It grants ~8 people access to Product A's folder, its Talk rooms, its Deck boards and everything Product A is itself a member of, transitively. The person clicking sees none of that.

2. Access grows through other people's actions. Worse than 1. Today Product A is small. Next month someone adds Product A to All Products. Everyone in Design now has access to things nobody ever decided to give them. Nobody performed a bad action; the graph changed underneath. No amount of viewing helps if nobody's looking that day.

3. No consent model. Can I add your team to my team? If yes, I've granted your members access without you knowing — and now your membership changes silently propagate into my resources. If no, cross-team reuse (use case 4) needs an invite/accept flow, which is more UI and more states.

4. Removal appears to work and doesn't. Alice is in Design and also directly in Product A. Owner removes Alice from Product A. UI says done. Alice still has full access via Design. This is a security failure that looks like a success, and it's the single most likely support ticket. Fix requires showing effective access with path, everywhere membership is displayed.

5. Externals and guests. Google specifically added filtering of indirect external members because nesting silently leaked content to people outside the org. Federated users and guests reaching resources through a two-hop path is a plausible CVE-shaped bug.

6. Permission conflicts need a stated rule. Alice reaches a teamfolder as read-only via Design and read-write via direct membership. Multiple paths, different levels. Union is the normal answer, but it means the restrictive grant you carefully set is silently overridden — and with teamfolder ACLs layered on top, explaining the outcome to a customer becomes genuinely hard.

Possible solutions:

  • Impact preview at write time. "Adding Design grants 8 people access to: [list of resources, including inherited ones]. Continue?" Catches risks 1 and 2 at the only moment anyone is paying attention.
  • Effective access, shown inline. Wherever members are listed, show inherited members and the path they came through. Removes risk 4 entirely.
  • Per-user reverse lookup. "What can Alice reach and why." The incident-response tool.
  • Notification to a team owner when their team gets added somewhere new.
Off by default?

Say we implement things as above, including a nice overview for team admins and system administrators of the team hierarchy and ownership and such. Nesting is a feature for large, hierarchical, directory-driven orgs, like public sector, big enterprise. They will be happy. But we might want to have it off by default, to avoid the complexity for smaller organizations.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

This is a broad design discussion and names no implementation files, tests, or entry points. Start by reviewing the existing team-membership and access-propagation behavior, then use the nesting use cases and listed risks to define a consistent model, transparency requirements, and effective-access behavior before implementation.

Written by the indexing model from the issue text.

Assessment

Domain
authorization, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.