# Modeling teams in Sourcegraph

<Callout type="note">
	This feature is in Experimental stage and might change in the future.
</Callout>

Teams in Sourcegraph are groups of users with a common handle. Teams are structured as a tree, so teams can have child teams.

Example team structure that can be modeled:

```
Engineering
├─ Security
├─ Code Graph
│  ├─ Batch Changes
│  ├─ Code Insights
├─ source
│  ├─ Repo Management
│  ├─ IAM
Product
```

Teams in Sourcegraph are usable in [code ownership](/own/), and other features in the future. Teams can be code owners and will influence the code ownership experience. You can search for code owned by a specific team, and in the future advanced ownership analytics will be informed by given team structures.

## Configuring teams

Teams can either be defined directly in Sourcegraph, or be ingested from external systems into Sourcegraph using [src-cli](https://github.com/sourcegraph/src-cli). A team name must be globally unique, and the global namespace for names is shared among users, teams, and orgs.

### From the UI

Go to **Teams** from the user navbar item. On this page, click "Create team". A team needs to have a unique name and can optionally take a display name. Additionally, you can add a parent team to build a tree structure as outlined above.

After hitting create, you will be redirected to the team page where you can add Sourcegraph users as team members.

> NOTE: It's common to define teams in Sourcegraph from a third party system. Teams defined from src-cli using the `-read-only` flag cannot be modified from the UI to prevent state drift from external systems.

### From the CLI

If you prefer a command line based approach, or would like to integrate an external system of record for teams into Sourcegraph, [src-cli](https://github.com/sourcegraph/src-cli) provides commands to manage teams:

```bash
# List configured teams. Lists root teams, using -parent-team can read child teams.
src teams list [-query=<query>] [-parent-team=<name>]

# Create a new team.
src teams create -name=<name> [-display-name=<displayName>] [-parent-team=<name>] [-read-only]

# Update a team.
src teams update -name=<name> [-display-name=<displayName>] [-parent-team=<name>]

# Delete a team.
src teams delete -name=<name>

# List team members.
src teams members list -name=<name> [-query=<query>]

# Add a new team member. See user account matching for details on how this works.
src teams members add -team-name=<name> [-email=<email>] [-username=<username>] [-id=<ID>] [-external-account-service-id=<serviceID> -external-account-service-type=<serviceType> [-external-account-account-id=<accountID>] [-external-account-login=<login>]] [-skip-unmatched-members]

# Remove a team member. See user account matching for details on how this works.
src teams members remove -team-name=<name> [-email=<email>] [-username=<username>] [-id=<ID>] [-external-account-service-id=<serviceID> -external-account-service-type=<serviceType> [-external-account-account-id=<accountID>] [-external-account-login=<login>]] [-skip-unmatched-members]
```

#### User account matching

Matching a user account in Sourcegraph from an external system can be achieved in a few different ways: Sourcegraph User ID, Sourcegraph account email, Sourcegraph username or an explicit external-account mapping can be provided.

The matching order is as follows:

-   try Sourcegraph user ID
-   then try email
-   then try username
-   then try external-account

Example for external account matching with configured GitHub auth provider:

```bash
# Match a user with the account ID 123123123:
src teams members add \
  -team-name='engineering' \
  -external-account-service-id='https://github.com/' \
  -external-account-service-type='github' \
  -external-account-account-id='123123123'
# Match a user with the GitHub login handle alice:
src teams members add \
  -team-name='engineering' \
  -external-account-service-id='https://github.com/' \
  -external-account-service-type='github' \
  -external-account-login='alice'
```

### Permissions in teams

For now, team permissions are based on membership. Read-only teams are only editable by site-admins. The creator of a team can always modify it, even if they are not a member of it.

|               **Action**                | **Site-admin** | **Regular user** | **Direct team member** |
| :-------------------------------------: | :------------: | :--------------: | :--------------------: |
|   Reading teams, metadata and members   |       🟢       |        🟢        |           🟢           |
|           Creating a new team           |       🟢       |        🟢        |          n/a           |
|        Creating a new child team        |       🟢       |        🔴        |           🟢           |
|      Creating a new read-only team      |       🟢       |        🔴        |          n/a           |
|     Updating team details/metadata      |       🟢       |        🔴        |           🟢           |
|             Deleting a team             |       🟢       |        🔴        |           🟢           |
|        Deleting a read-only team        |       🟢       |        🔴        |           🔴           |
|        Adding a member to a team        |       🟢       |        🔴        |           🟢           |
|      Removing a member from a team      |       🟢       |        🔴        |           🟢           |
|   Adding a member to a read-only team   |       🟢       |        🔴        |           🔴           |
| Removing a member from a read-only team |       🟢       |        🔴        |           🔴           |

### Known limitations

-   Read-only teams can only be created by site-admins
-   Identity Provider / SCIM integrations are not available at the moment
