Skip to content
GitmoapdocsBeta
Guide· How do I…?

Teams

Overview

A team is a named set of people in your organisation — Backend, SRE, Security reviewers. A team can do nothing by itself. You give it access the way you give a person access, with a grant on a group or repository, and everyone on the team has that access for as long as they are on it.

That is what makes teams worth having: the roster and the access are kept apart. When someone joins Backend, you add them to the team once, and they can do everything Backend can do everywhere. When they leave, you take them off once. Nobody has to find and change each group and repository by hand.

Quick start

Quick start3 steps

Create a team, give it access, and put someone on it

You’ll need Owner of the organisation.
  1. Create the team: gitmoap teams create-team --group-id acme --slug backend --name Backend. You are its first maintainer.

  2. Give it access: gitmoap access create-group-access-grants --group-id acme/platform --subjects '[{"team":"<team-id>"}]' --role '{"builtin":"developer"}'.

  3. Put someone on it: gitmoap teams put-team-member --team-id <team-id> --user-id <user-id>. They can now do everything a Developer can on acme/platform.

Before you start

  • Owner of the organisation to create, rename or delete a team.Teams belong to the organisation as a whole, so they are made at its top-level group.
  • A team's maintainers keep its roster.A maintainer can put people on the team and take them off, and change its description, without being an Owner — but only within what they could give themselves: see How it works.
  • Anyone in the organisation can see its teams, who is on them and what they can do. Someone whose only access is to one repository — an outside collaborator — sees none of this.
  • A token with the right scope, if you are using the CLI or the API: team:read to list and read, team:manage to create, change and delete teams and their rosters. They come with the read_api and write_api bundles.

How it works

A team has people, and grants. Its people are the roster. Its grants are made through access, exactly as for a person, and say what the team can do and where. Everyone on the roster has every one of the team's grants.

Only people join teams. A service account cannot be put on a team — every place a team is named, such as an approver list or a code owner, is a place a bot silently joining would be a surprise. Give a service account access directly instead.

Joining a team is being given its access, and is checked that way. You can put someone on a team only if you could have given them each of the team's grants yourself. A maintainer who is a Developer on a repository cannot add someone to a team that is Owner of it; an Owner there can. The same check applies when you make someone a maintainer, or let their place run longer. Taking someone off a team, making a maintainer a member, or ending their place sooner gives nobody anything, and is never refused for this reason.

A refusal says what you lack, where you can see it. If the team holds access somewhere you cannot see, the refusal says so without naming the place.

Places can end on their own. Give someone an end date, up to a year away, and the team's access stops reaching them then, with nothing to remember to undo.

A team can follow a group in your identity provider. Link it to the group's name, and each time someone signs in through single sign-on, their place on the team follows what your provider says: they are put on it when the group is in their sign-in, and taken off when it is not. A place your provider confirms lasts for the connection's sync period — 30 days unless you change it — so someone who stops signing in drops off on their own. Linking makes the people already on the team subject to the same rule — an end date you set by hand that comes sooner stays. Groups are read only for accounts linked to your organisation's own provider, and only your provider can set them, so nobody can put themselves on a linked team. While a team is linked, nobody changes its people by hand, and nobody can leave it except through your provider. If your organisation provisions over SCIM, sign-in sync is off: linked teams stop following sign-ins, and their places lapse at the end of the sync period.

A team your provider keeps over SCIM is your provider's too. It is one of your provider's groups, pushed as it changes: people are put on it and taken off it as your provider says, not at sign-in, and their places do not lapse. As with a linked team, nobody changes its people by hand, and it cannot be linked to a group in the sign-in instead: its roster is your provider's, over SCIM.

Deleting a team takes its access with it. Every grant the team holds is revoked, and everyone on it loses what the team gave them. What they hold in their own right is untouched. Preview a deletion first to see how far the team's access reaches.

Every change is recorded. Creating and deleting a team, and every change to its roster made by a person or pushed over SCIM, lands in the organisation's audit log. The places a sign-in adds to or removes from a linked team are not recorded there one by one.

How to

Create a team

Name it with a slug — lowercase letters, digits and hyphens, unique in the organisation — and a display name. You can list its first people in the same request; you become a maintainer unless you list yourself otherwise.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams create-team --group-id <id> --name <name> --slug <slug>
curlbash
curl -X POST https://api.gitmoap.example/groups/{group_id}/teams \
-H "Authorization: Bearer $GITMOAP_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "members[].user_id": "<uuid>", "name": "<string>", "slug": "<string>" }'

See an organisation's teams

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams list-teams --group-id <id>
curlbash
curl -X GET https://api.gitmoap.example/groups/{group_id}/teams \
-H "Authorization: Bearer $GITMOAP_TOKEN"

Narrow the list with search, a fragment of a team's slug or name.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams get-team --team-id <id>
curlbash
curl -X GET https://api.gitmoap.example/teams/{team_id} \
-H "Authorization: Bearer $GITMOAP_TOKEN"

Put someone on a team, or change their place

Choose member or maintainer, and optionally when their place ends. Putting someone on a team they are already on replaces their place with the one you send, so leaving out the end date makes it last until they are taken off.

Add dry_run=true — --dry-run in the CLI — to see what they would gain, and change nothing. The answer counts the team's grants, how many of the groups and repositories they reach you can see, and whether there are others.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams put-team-member --team-id <id> --user-id <id>
curlbash
curl -X PUT https://api.gitmoap.example/teams/{team_id}/members/{user_id} \
-H "Authorization: Bearer $GITMOAP_TOKEN"

See who is on a team

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams list-team-members --team-id <id>
curlbash
curl -X GET https://api.gitmoap.example/teams/{team_id}/members \
-H "Authorization: Bearer $GITMOAP_TOKEN"

See what a team can do

Every grant the team holds on a group or repository you can see, with the role and when it ends. If the team holds access somewhere you cannot see, hidden_scopes says so.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams list-team-access --team-id <id>
curlbash
curl -X GET https://api.gitmoap.example/teams/{team_id}/access \
-H "Authorization: Bearer $GITMOAP_TOKEN"

See where a team is used

A team can be more than access. It can be named as approvers on an approval rule or a protected environment, be allowed to push or merge on a protected branch, own a service, or own code through a line of a repository's CODEOWNERS file (@your-org:release). Before you add someone to a team, look here: they will be asked for approvals, be able to approve deployments, own what the team owns, and be a required reviewer of that code.

Each place is listed only if you can see it there, and hidden says whether the team is named anywhere else. Each list holds at most 100 places; truncated says when one stops short.

CODEOWNERS lines are read from each repository's default branch the next time something is pushed or merged there, so a repository nobody has pushed to since this list existed does not show its lines yet. A line that names the team by an old name is not listed — it no longer makes anyone a reviewer either, so fix the line.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams get-team-usage --team-id <id>
curlbash
curl -X GET https://api.gitmoap.example/teams/{team_id}/usage \
-H "Authorization: Bearer $GITMOAP_TOKEN"

Take someone off a team, or leave one

A maintainer, or an Owner of the organisation, can take anyone off. Anyone can leave a team themselves — except a team your identity provider keeps, which you leave by leaving the group there.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams remove-team-member --team-id <id> --user-id <id>
curlbash
curl -X DELETE https://api.gitmoap.example/teams/{team_id}/members/{user_id} \
-H "Authorization: Bearer $GITMOAP_TOKEN"

Keep a team's roster in your identity provider

Name the group exactly as your provider sends it in the sign-in, capital letters included — Engineering, not its id, unless your provider sends ids. Your single sign-on connection has to map a groups claim first (attribute_mapping.groups), or no sign-in would ever say who is in the group. Linking needs the right to manage the organisation's teams, and — because everyone the provider puts in the group gets the team's access — you must be able to give each of the team's grants yourself. From the moment you link it, everyone already on the team has one sync period to be confirmed by a sign-in before their place lapses.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams link-team-idp-group --team-id <id> --idp-group <idp group>
curlbash
curl -X PUT https://api.gitmoap.example/teams/{team_id}/idp-link \
-H "Authorization: Bearer $GITMOAP_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "idp_group": "<string>" }'

Keep a team's roster by hand again

Unlinking leaves everyone your provider last confirmed on the team, and their places stop lapsing. A place that had already lapsed is removed, so nobody whose place ran out comes back. An end date you set by hand before you linked the team stays; the ones the sync set go. Unlinking a team kept by hand changes nothing. A team your provider keeps over SCIM cannot be unlinked — it was never linked.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams unlink-team-idp-group --team-id <id>
curlbash
curl -X DELETE https://api.gitmoap.example/teams/{team_id}/idp-link \
-H "Authorization: Bearer $GITMOAP_TOKEN"

Rename a team, or change its description

Renaming needs an Owner of the organisation. A team's maintainers can change its description.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams update-team --team-id <id>
curlbash
curl -X PATCH https://api.gitmoap.example/teams/{team_id} \
-H "Authorization: Bearer $GITMOAP_TOKEN"

Delete a team

Warning

Deleting a team revokes every grant it holds, on the next request. Everyone on it loses what the team gave them. Creating the team again does not bring the grants back.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams delete-team --team-id <id>
curlbash
curl -X DELETE https://api.gitmoap.example/teams/{team_id} \
-H "Authorization: Bearer $GITMOAP_TOKEN"

See your own teams

Every team you are on, in every organisation, with your place on each.

The web app has no screen for this yet; use the CLI or the API.

Terminalbash
gitmoap teams list-my-teams
curlbash
curl -X GET https://api.gitmoap.example/user/teams \
-H "Authorization: Bearer $GITMOAP_TOKEN"

Reference

13 endpoints

POST/groups/{group_id}/teamsteam:manage

Create a team in an organization, with its first people.

create_teamPOST /groups/{group_id}/teamsOpen in the API reference

Token scope

team:manage

Counts against

teams_per_org

Send

Path
  • group_iduuidThe organization's top-level group
Body
  • descriptionobjectoptional
  • members[]object3 fields
    • expires_atdate-timeoptional
    • rolemaintainermemberoptionalA member's place on a team. Maintainers manage the roster.
    • user_iduuid
  • namestring
  • slugstring

Refuses

  • 400Invalid request, or the group is not an organization's top-level group
  • 401Authentication required
  • 403The caller cannot manage the organization's teams
  • 404Group or person not found
  • 409The organization already has a team with this slug
  • 422A service account was listed as a member
  • 429Team or team member limit reached

Receive

  • created_atdate-time
  • created_byobjectoptional
  • descriptionstring
  • idp_groupobjectoptionalThe identity provider's group this team mirrors. Absent for a team whose roster is kept by hand.
  • member_countint64People on the team, counting any whose place has lapsed but not yet been removed.
  • namestring
  • organization_iduuid
  • roster_sourceidentity_providermanualscimWho keeps a team's roster: people, through the API, or an identity provider.
  • slugstring
  • team_iduuid
  • updated_atdate-time
GET/groups/{group_id}/teamsteam:read

An organization's teams.

list_teamsGET /groups/{group_id}/teamsOpen in the API reference

Token scope

team:read

Send

Path
  • group_iduuidThe organization's top-level group
Query
  • searchstringoptionalA fragment of a team's slug or name
  • limitint64optionalMaximum number of teams, 1-100 (default 50)
  • next_tokenstringoptionalPagination token

Refuses

  • 400Invalid pagination token, or the group is not an organization's top-level group
  • 401Authentication required
  • 403Only members of the organization see its teams
  • 404Group not found

Receive

  • next_tokenobjectoptional
  • teams[]object11 fields
    • created_atdate-time
    • created_byobjectoptional
    • descriptionstring
    • idp_groupobjectoptionalThe identity provider's group this team mirrors. Absent for a team whose roster is kept by hand.
    • member_countint64People on the team, counting any whose place has lapsed but not yet been removed.
    • namestring
    • organization_iduuid
    • roster_sourceidentity_providermanualscimWho keeps a team's roster: people, through the API, or an identity provider.
    • slugstring
    • team_iduuid
    • updated_atdate-time
GET/teams/{team_id}team:read

One team.

get_teamGET /teams/{team_id}Open in the API reference

Token scope

team:read

Send

Path
  • team_iduuidTeam ID

Refuses

  • 400Invalid team id
  • 401Authentication required
  • 403The token lacks the scope
  • 404Team not found

Receive

The same shape create_team returns — 11 fields. Go to it

Show it here
  • created_atdate-time
  • created_byobjectoptional
  • descriptionstring
  • idp_groupobjectoptionalThe identity provider's group this team mirrors. Absent for a team whose roster is kept by hand.
  • member_countint64People on the team, counting any whose place has lapsed but not yet been removed.
  • namestring
  • organization_iduuid
  • roster_sourceidentity_providermanualscimWho keeps a team's roster: people, through the API, or an identity provider.
  • slugstring
  • team_iduuid
  • updated_atdate-time
PATCH/teams/{team_id}team:manage

Rename a team, or change its description.

update_teamPATCH /teams/{team_id}Open in the API reference

Token scope

team:manage

Send

Path
  • team_iduuidTeam ID
Body
  • descriptionobjectoptional
  • nameobjectoptional
  • slugobjectoptional

Refuses

  • 400Invalid request
  • 401Authentication required
  • 403The caller cannot make this change
  • 404Team not found
  • 409The organization already has a team with this slug

Receive

The same shape create_team returns — 11 fields. Go to it

Show it here
  • created_atdate-time
  • created_byobjectoptional
  • descriptionstring
  • idp_groupobjectoptionalThe identity provider's group this team mirrors. Absent for a team whose roster is kept by hand.
  • member_countint64People on the team, counting any whose place has lapsed but not yet been removed.
  • namestring
  • organization_iduuid
  • roster_sourceidentity_providermanualscimWho keeps a team's roster: people, through the API, or an identity provider.
  • slugstring
  • team_iduuid
  • updated_atdate-time
DELETE/teams/{team_id}team:manage

Delete a team, revoking every grant it holds.

delete_teamDELETE /teams/{team_id}Open in the API reference

Token scope

team:manage

Send

Path
  • team_iduuidTeam ID
Query
  • dry_runbooleanoptionalSay what would be taken away, and change nothing

Refuses

  • 400Invalid team id or dry_run value
  • 401Authentication required
  • 403The caller cannot manage the organization's teams
  • 404Team not found
  • 409The request conflicts with the resource's current state; `reason` says how

Receive

  • accessobject3 fields
    • grantsint64Grants the team holds.
    • hidden_scopesbooleanWhether the team also holds access somewhere you cannot see. Those places are never named.
    • scopes_visible_to_youint64Groups and repositories among them that you can see.
  • membersint64People on the team, each of whom loses the team's access.
  • team_iduuid
GET/teams/{team_id}/membersteam:read

The people on a team.

list_team_membersGET /teams/{team_id}/membersOpen in the API reference

Token scope

team:read

Send

Path
  • team_iduuidTeam ID
Query
  • limitint64optionalMaximum number of people, 1-100 (default 50)
  • next_tokenstringoptionalPagination token

Refuses

  • 400Invalid pagination token
  • 401Authentication required
  • 403The token lacks the scope
  • 404Team not found

Receive

  • members[]object10 fields
    • added_byobjectoptional
    • created_atdate-time
    • expires_atdate-timeoptionalWhen their place on the team ends. After it, the team's access no longer reaches them.
    • rolemaintainermemberA member's place on a team. Maintainers manage the roster.
    • synced_atdate-timeoptionalWhen the identity provider last confirmed this place, for a mirrored roster.
    • team_iduuid
    • userobject4 fields
      • avatar_urlobjectoptional
      • emailstring
      • idstring
      • usernamestring
  • next_tokenobjectoptional
PUT/teams/{team_id}/members/{user_id}team:manage

Put a person on a team, or change their place on it.

put_team_memberPUT /teams/{team_id}/members/{user_id}Open in the API reference

Token scope

team:manage

Counts against

members_per_team

Send

Path
  • team_iduuidTeam ID
  • user_iduuidThe person
Query
  • dry_runbooleanoptionalSay what they would gain, and change nothing
Body
  • expires_atdate-timeoptional
  • rolemaintainermemberoptionalA member's place on a team. Maintainers manage the roster.

Refuses

  • 400Invalid request
  • 401Authentication required
  • 403The caller cannot change this roster, or cannot give the access the team holds
  • 404Team or person not found
  • 409The team's people are kept by the identity provider
  • 422A service account cannot join a team
  • 429Member limit reached for this team

Receive

  • dry_runbooleanWhether this was only a preview, and nothing was changed.
  • gained_accessobject3 fields
    • grantsint64Grants the team holds.
    • hidden_scopesbooleanWhether the team also holds access somewhere you cannot see. Those places are never named.
    • scopes_visible_to_youint64Groups and repositories among them that you can see.
  • memberobject10 fields
    • added_byobjectoptional
    • created_atdate-time
    • expires_atdate-timeoptionalWhen their place on the team ends. After it, the team's access no longer reaches them.
    • rolemaintainermemberA member's place on a team. Maintainers manage the roster.
    • synced_atdate-timeoptionalWhen the identity provider last confirmed this place, for a mirrored roster.
    • team_iduuid
    • userobject4 fields
      • avatar_urlobjectoptional
      • emailstring
      • idstring
      • usernamestring
DELETE/teams/{team_id}/members/{user_id}team:manage

Take a person off a team, or leave one yourself.

remove_team_memberDELETE /teams/{team_id}/members/{user_id}Open in the API reference

Token scope

team:manage

Send

Path
  • team_iduuidTeam ID
  • user_iduuidThe person
Query
  • dry_runbooleanoptionalSay what they would lose, and change nothing

Refuses

  • 400Invalid id or dry_run value
  • 401Authentication required
  • 403The caller cannot change this roster
  • 404Team not found, or the person is not on it
  • 409The team's people are kept by the identity provider

Receive

  • dry_runboolean
  • lost_accessobject3 fields
    • grantsint64Grants the team holds.
    • hidden_scopesbooleanWhether the team also holds access somewhere you cannot see. Those places are never named.
    • scopes_visible_to_youint64Groups and repositories among them that you can see.
  • team_iduuid
  • user_iduuid
GET/teams/{team_id}/accessteam:read

The access a team holds, on the groups and repositories you can see.

list_team_accessGET /teams/{team_id}/accessOpen in the API reference

Token scope

team:read

Send

Path
  • team_iduuidTeam ID
Query
  • limitint64optionalMaximum number of grants, 1-100 (default 50)
  • next_tokenstringoptionalPagination token

Refuses

  • 400Invalid pagination token
  • 401Authentication required
  • 403The token lacks the scope
  • 404Team not found

Receive

  • grants[]object12 fields
    • atobject3 fields
      • full_pathstring
      • idstring
      • typegrouprepository
    • created_atdate-time
    • expires_atdate-timeoptional
    • grant_iduuid
    • granted_byobjectoptional
    • reasonobjectoptional
    • roleobject4 fields
      • builtinobjectoptional
      • customobjectoptional
      • namestringThe role's display name: a built-in name such as Developer, or the custom role's name.
      • rankdeveloperguestmaintainerownerreporter
  • hidden_scopesbooleanWhether the team also holds access somewhere you cannot see. Those places are never named.
  • next_tokenobjectoptional
GET/teams/{team_id}/usageteam:read

Where a team is named besides its grants.

get_team_usageGET /teams/{team_id}/usageOpen in the API reference

Token scope

team:read

Send

Path
  • team_iduuidTeam ID

Refuses

  • 400Invalid team id
  • 401Authentication required
  • 403The token lacks the scope
  • 404Team not found

Receive

  • approval_rules[]object5 fields
    • atobject3 fields
      • full_pathstring
      • idstring
      • typegrouprepository
    • namestring
    • rule_iduuid
  • branch_rules[]object7 fields
    • atobject3 fields
      • full_pathstring
      • idstring
      • typegrouprepository
    • branch_patternstring
    • branch_rule_iduuid
    • mergebooleanWhether the team may merge into them.
    • pushbooleanWhether the team may push to the branches the rule protects.
  • codeowners[]object6 fields
    • atobject3 fields
      • full_pathstring
      • idstring
      • typegrouprepository
    • file_pathstringCODEOWNERS or .gitmoap/CODEOWNERS, on the repository's default branch.
    • lineint32The line, counting from 1.
    • patternstringThe paths the line covers, as written.
  • environments[]object6 fields
    • atobject3 fields
      • full_pathstring
      • idstring
      • typegrouprepository
    • environment_iduuid
    • slugstring
    • tierdevelopmentproductionstagingtestingWhat kind of environment this is, whatever it is called: development, testing, staging or production. A production environment is protected by default.
GET/user/teamsteam:read

The teams you are on, in every organization.

list_my_teamsGET /user/teamsOpen in the API reference

Token scope

team:read

Send

Query
  • limitint64optionalMaximum number of teams, 1-100 (default 50)
  • next_tokenstringoptionalPagination token

Refuses

  • 400Invalid pagination token
  • 401Authentication required
  • 403The token lacks the scope

Receive

  • next_tokenobjectoptional
  • teams[]object13 fields
    • expires_atdate-timeoptional
    • rolemaintainermemberA member's place on a team. Maintainers manage the roster.
    • teamobject11 fields
      • created_atdate-time
      • created_byobjectoptional
      • descriptionstring
      • idp_groupobjectoptionalThe identity provider's group this team mirrors. Absent for a team whose roster is kept by hand.
      • member_countint64People on the team, counting any whose place has lapsed but not yet been removed.
      • namestring
      • organization_iduuid
      • roster_sourceidentity_providermanualscimWho keeps a team's roster: people, through the API, or an identity provider.
      • slugstring
      • team_iduuid
      • updated_atdate-time

Limits

Teams per organisation — 10 on the Free plan. People per team — 50 on the Free plan.

PlanTeams per organisationPeople per team
Free1050
Pro50200
Team2001 000
Enterprise1 0005 000

At either limit the request is refused with 429 TOO_MANY_REQUESTS and nothing is written. Delete teams that are no longer used, or raise the limit: a higher plan lifts both, and an Owner can ask for a higher limit on one namespace.

A team holds at most 500 grants. Giving a team access beyond that is refused with 429; give it access on a group higher up instead, which reaches everything beneath.

An end date can be at most a year away.

Troubleshooting

403 FORBIDDEN— ACCESS_ESCALATION
Cause
The team holds access you could not give yourself. The message names what you lack, where you can see it
What to do
Ask someone who holds that access to add them, or an Owner of the organisation
403 FORBIDDENon a roster change
Cause
You are not one of the team's maintainers and cannot manage the organisation's teams
What to do
Ask a maintainer of the team
403 FORBIDDENlisting an organisation's teams
Cause
You are not a member of the organisation — your access is to something inside it
What to do
Ask an Owner to give you access to the organisation, or to put you on a team
404 NOT_FOUNDon a team id
Cause
The team was deleted, belongs to another organisation, or you are not a member of its organisation
What to do
Check the id against the organisation's list of teams
400 BAD_REQUEST— NOT_AN_ORGANIZATION
Cause
Teams were asked for on a subgroup
What to do
Use the organisation's top-level group
409 CONFLICT— TEAM_SLUG_TAKEN
Cause
The organisation already has a team with this slug
What to do
Choose another slug
409 CONFLICT— TEAM_ROSTER_MANAGED_BY_IDP
Cause
The team's people are kept by your identity provider — the team is linked to a group, or pushed over SCIM. Linking or unlinking a team pushed over SCIM is refused the same way
What to do
Change the group in your identity provider. A linked team can be unlinked to keep its roster by hand again; a team pushed over SCIM stays your provider's
409 CONFLICT— IDP_GROUP_LINKED
Cause
Another team of the organisation already follows that group, or a group your provider pushed over SCIM has that name as its identifier
What to do
Unlink the other team, or link this one to a different group
422 UNPROCESSABLE_ENTITY— IDP_GROUPS_NOT_MAPPED
Cause
Your single sign-on connection does not map a groups claim
What to do
Set attribute_mapping.groups on the connection to the claim your provider sends groups in
People stay on a linked team although they left the group
Cause
They have not signed in since. A place lapses after the sync period without a confirming sign-in
What to do
Wait for the period to pass, shorten it on the connection, or take them off after unlinking. For immediate removal, provision over SCIM
Everyone dropped off a linked team at once
Cause
The sync period passed with no confirming sign-ins — often because your organisation now provisions over SCIM, which turns sign-in sync off
What to do
Push the group over SCIM, or check that your provider sends the group in the sign-in under the claim the connection maps
422 UNPROCESSABLE_ENTITY— NOT_A_USER
Cause
A service account was named as a member
What to do
Give the service account access directly

Examples

Give a whole team access to one area

shellscript
gitmoap access create-group-access-grants --group-id acme/platform \
--subjects '[{"team":"<backend-team-id>"}]' \
--role '{"builtin":"developer"}'

Check what adding someone would give them, before doing it

shellscript
gitmoap teams put-team-member --team-id <team-id> --user-id <user-id> --dry-run --output json \
| jq '.gained_access'

List everyone on a team

shellscript
gitmoap teams list-team-members --team-id <team-id> --limit 100 --output json \
| jq -r '.members[] | [.user.username, .role, (.expires_at // "no end")] | @tsv'

FAQ

Can a team be on another team?

No. Teams do not nest, so what a person can do through teams is always one step from the roster to the grant.

Does being on a team make me a member of the organisation?

Yes. Anyone on one of an organisation's teams can see its teams and who is on them, even if every grant they have comes through the team.

What happens to a team's access when I leave it?

It stops reaching you on the next request. Access you hold in your own right is unchanged.

  • Accessgiving a team access to a group or repository, and seeing why someone can do something
  • Single sign-onthe groups claim a linked team follows, and its sync period
  • SCIM provisioningteams your identity provider keeps as its groups change
  • Groupsthe organisation's top-level group, where teams belong
  • Access tokensthe scopes a token needs to call these operations
  • Audit logevery change to a team and its roster