Skip to content

feat(iam): add createTeam, editTeam, and listTeams#166

Merged
designcode merged 1 commit into
mainfrom
feat/storage/teams
Jun 25, 2026
Merged

feat(iam): add createTeam, editTeam, and listTeams#166
designcode merged 1 commit into
mainfrom
feat/storage/teams

Conversation

@designcode

@designcode designcode commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds team management to @tigrisdata/iam for creating, editing, and listing teams within an organization.

  • createTeam(team, options?) — creates a team from CreateTeamInput (name required, optional description and members) and returns the new teamId.
  • editTeam(teamId, team, options?) — applies a partial update (Partial<CreateTeamInput>); errors with No fields to update when no fields are provided.
  • listTeams(options?) — returns the organization's teams, each mapped to a Team (id, name, description, members, createdAt, updatedAt).

Adds the /tigris-iam/teams endpoint and exports the team functions plus their option/response/input types (CreateTeamInput, CreateTeamOptions, CreateTeamResponse, EditTeamOptions, EditTeamResponse, ListTeamsOptions, ListTeamsResponse, Team).

import { createTeam, editTeam, listTeams } from '@tigrisdata/iam';

const { data } = await createTeam({
  name: 'engineering',
  description: 'Engineering team',
  members: ['user@example.com'],
});

await editTeam(data.teamId, { name: 'engineering-renamed' });

const { data: teams } = await listTeams();

Implementation notes

  • All three functions follow the existing IAM conventions: createIAMClient auth/guard, HTTP-level error check and body-level status === 'error' check surfacing the API message.
  • Request/response keys are mapped between the SDK's camelCase shape and the API's snake_case (user_id, created_at, …).
  • createTeam / editTeam share a single CreateTeamInput type (edit uses Partial<CreateTeamInput>) for a symmetric API surface.

Notes / follow-ups

  • deleteTeam / getTeam are intentionally not in this PR — planned as a follow-up.
  • Integration tests are deferred to a follow-up (the IAM package has no test infra yet).

Release

Includes a changeset bumping @tigrisdata/iam (minor).

🤖 Generated with Claude Code


Note

Medium Risk
New IAM org membership APIs can affect access grouping if misused; behavior depends on the backend teams endpoint with no integration tests in this PR.

Overview
Adds organization team management to @tigrisdata/iam via three new public APIs wired to /tigris-iam/teams.

createTeam POSTs a team (name plus optional description and members), maps members to user_id in the request body, and returns teamId. editTeam PATCHes /{teamId} with a partial CreateTeamInput and fails locally with No fields to update when the patch body would be empty. listTeams GETs all teams and normalizes API snake_case fields into the exported Team shape (including Date timestamps and member user IDs).

Package surface updates: new lib/team/* modules, IAM_ENDPOINTS.teams, re-exports from index.ts, and a minor changeset for @tigrisdata/iam.

Reviewed by Cursor Bugbot for commit ac5f42e. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 162b3c7. Configure here.

Comment thread packages/iam/src/lib/team/edit.ts
@greptile-apps

greptile-apps Bot commented Jun 24, 2026

Copy link
Copy Markdown

Greptile Summary

Adds createTeam, editTeam, and listTeams to @tigrisdata/iam, following the existing client/error-handling conventions throughout the package. The implementation is largely sound, but there are two correctness issues worth addressing before merging.

  • Team.description in list.ts is declared as a required string, but description is optional in CreateTeamInput. Teams that were created without a description will carry undefined at runtime while TypeScript treats the field as always present, silently breaking any downstream code that trusts the type.
  • All three files use a falsy guard (team.description && …) to conditionally include the description field. This works for undefined but silently drops an empty string '', meaning callers cannot intentionally blank out a description via editTeam, and will receive a misleading No fields to update error instead.

Confidence Score: 3/5

The team management additions are largely consistent with existing IAM patterns, but the Team.description type contract is wrong and will produce silent undefined values that TypeScript won't catch for callers.

The description: string vs optional mismatch in the Team type is a real defect that will affect every caller who lists teams created without a description — TypeScript will assert the field is always a string when it can be undefined at runtime. The falsy-check issue in editTeam is a narrower edge case but still leads to a confusing error message for valid input.

packages/iam/src/lib/team/list.ts (type contract for Team.description) and packages/iam/src/lib/team/edit.ts (falsy description guard)

Important Files Changed

Filename Overview
packages/iam/src/lib/team/list.ts Adds listTeams; Team.description is typed as required string but optional in CreateTeamInput, so teams without descriptions will carry undefined at runtime while TypeScript treats the field as always present.
packages/iam/src/lib/team/edit.ts Adds editTeam; correctly validates that at least one field is supplied. Same falsy description check means passing description: '' silently produces a No fields to update error.
packages/iam/src/lib/team/create.ts Adds createTeam; follows existing IAM conventions correctly. Minor: falsy check on description will silently drop an empty-string value.
packages/iam/src/lib/http-client.ts Adds the /tigris-iam/teams endpoint constant; straightforward addition consistent with existing endpoint definitions.
packages/iam/src/index.ts Exports the three new team functions and all associated types; follows existing export conventions.
.changeset/iam-teams.md Minor version bump changeset for @tigrisdata/iam; description and usage examples are accurate.

Reviews (1): Last reviewed commit: "feat(iam): add createTeam, editTeam, and..." | Re-trigger Greptile

Comment on lines +14 to +19
description: string;
id: string;
members: string[];
name: string;
updatedAt: Date;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 description typed as required string but it is optional in CreateTeamInput

Teams can be created without a description, so the API may return undefined (or omit the field) for those teams. The Team type declares description: string (non-optional), so callers will infer a string and won't add null guards, but at runtime team.description can be undefined. This is a type lie that will cause silent bugs downstream. It should match the optional shape: description?: string.

Comment on lines +30 to +36
const body = {
...(team?.name && { name: team.name }),
...(team?.description && { description: team.description }),
...(team?.members && {
members: team.members.map((member) => ({ user_id: member })),
}),
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Falsy check on description silently drops empty strings. Calling editTeam(id, { description: '' }) evaluates '' && { description: '' } to '', which spreads as nothing, so the description is never sent to the API and the caller gets a misleading No fields to update error instead. Checking !== undefined preserves the ability to clear or blank-out a description.

Suggested change
const body = {
...(team?.name && { name: team.name }),
...(team?.description && { description: team.description }),
...(team?.members && {
members: team.members.map((member) => ({ user_id: member })),
}),
};
const body = {
...(team?.name && { name: team.name }),
...(team?.description !== undefined && { description: team.description }),
...(team?.members && {
members: team.members.map((member) => ({ user_id: member })),
}),
};

Comment thread packages/iam/src/lib/team/create.ts Outdated
path: IAM_ENDPOINTS.teams,
body: {
name: team.name,
...(team.description && { description: team.description }),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Same falsy-check pattern: an explicitly passed empty-string description is silently dropped. Using !== undefined is more precise — it excludes only truly absent values, not empty strings.

Suggested change
...(team.description && { description: team.description }),
...(team.description !== undefined && { description: team.description }),

Add team management to @tigrisdata/iam for creating, editing, and
listing teams within an organization.

- createTeam(team, options?) creates a team from CreateTeamInput
  (name required, optional description and members)
- editTeam(teamId, team, options?) applies a partial update and
  errors with "No fields to update" when no fields are provided
- listTeams(options?) returns the organization's teams mapped to Team

Add the /tigris-iam/teams endpoint and export the team functions and
their option/response types.

Assisted-by: Opus 4.8 via Claude Code
@designcode designcode force-pushed the feat/storage/teams branch from 162b3c7 to ac5f42e Compare June 24, 2026 17:29
@designcode designcode merged commit 263e952 into main Jun 25, 2026
2 checks passed
@designcode designcode deleted the feat/storage/teams branch June 25, 2026 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants