Skip to content

feat: add team member role for team-level permission control#1023

Merged
elrrrrrrr merged 2 commits intomasterfrom
feat/team-member-role
Apr 8, 2026
Merged

feat: add team member role for team-level permission control#1023
elrrrrrrr merged 2 commits intomasterfrom
feat/team-member-role

Conversation

@elrrrrrrr
Copy link
Copy Markdown
Member

@elrrrrrrr elrrrrrrr commented Apr 2, 2026

Summary

Cherry-pick from #1021 (feat/user-team-api branch).

  • Add role field (owner / member) to TeamMember, enabling team-level permission control
  • Team creator is auto-added as team owner; team write operations now require team owner, org owner, or admin
  • Add private API GET /-/team/:org/:team/member returning [{user, role}]
  • Add private API PATCH /-/team/:org/:team/member/:username for updating member role
  • Keep npm compatible endpoints unchanged
  • Update docs (Chinese + English)
  • SQL migration: 4.32.0.sql adds role column to team_members

Test plan

  • Run npm run test:local test/port/controller/TeamController/index.test.ts
  • Run full test suite
  • Verify npm CLI commands still work unchanged

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Team members can now have assignable roles (owner or member) controlling team permissions
    • New API endpoints to view team member roles and update member permissions
    • Team creators automatically receive team owner status upon team creation
  • Documentation

    • Added comprehensive guide to organization, team, and package permission models with API endpoint reference

…ontrol

Cherry-pick from PR #1021 (feat/user-team-api branch).

- Add `role` field to TeamMember entity/model (owner or member, default member)
- Team creator is auto-added as team owner
- Team write operations now require team owner, org owner, or admin
- Add private API `GET /-/team/:org/:team/member` returning [{user, role}]
- Add private API `PATCH /-/team/:org/:team/member/:username` for role updates
- Keep npm compatible endpoints unchanged
- Update docs (Chinese + English)

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a team member role system that extends the existing Team infrastructure. It adds a role field to TeamMember entities (defaulting to 'member'), enabling owner and member designations. Changes propagate through service, repository, and controller layers, including new API endpoints for listing and updating team member roles, database schema migrations, and comprehensive documentation with tests.

Changes

Cohort / File(s) Summary
Entity & Model Layer
app/core/entity/TeamMember.ts, app/repository/model/TeamMember.ts
Added role: string field to TeamMemberData interface and TeamMember class with default value 'member'. Repository model updated with new persisted role attribute.
Service Layer
app/core/service/TeamService.ts, app/core/service/OrgService.ts
TeamService.createTeam now accepts optional creatorUserId, auto-adding creator as team owner. TeamService.addMember gains optional role parameter with role-update logic for existing members. OrgService explicitly sets roles when creating team members.
Repository Layer
app/repository/TeamRepository.ts
listTeamsByUserIdAndOrgId return type changed to include role alongside team entities. addMember now supports updating existing member roles via id lookup.
Controller & API
app/port/controller/TeamController.ts, app/port/controller/OrgController.ts
TeamController gained two private API endpoints: GET /-/team/:orgName/:teamName/member (list members with roles) and PATCH /-/team/:orgName/:teamName/member/:username (update member role). Authorization logic rewired to require team-owner/org-owner/admin status. OrgController.listUserTeams response now includes role field.
Database Migrations
sql/mysql/4.32.0.sql, sql/postgresql/4.32.0.sql
Added role varchar(20) column to team_members table with default value 'member'.
Documentation
docs/org-team.en.md, docs/org-team.md
New and updated documentation defining org/team/role concepts, permission model, and split between npm-compatible and cnpmcore-private API endpoints. Clarifies team-owner authorization requirements and role-management workflows.
Tests
test/port/controller/TeamController/index.test.ts, test/port/controller/package/ReadAccessAuth.test.ts
Expanded TeamController test suite covering team creation with creator auto-assignment, team member listing/role-management CRUD operations, authorization scenarios (401/403/422/404), and team deletion. Updated ReadAccessAuth.test.ts to explicitly set role in team member setup.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant TeamController
    participant TeamService
    participant TeamRepository
    participant Database

    Client->>TeamController: POST /team (createTeam with creatorUserId)
    TeamController->>TeamService: createTeam(orgId, name, description, creatorUserId)
    TeamService->>TeamRepository: createTeam(team)
    TeamRepository->>Database: INSERT team
    Database-->>TeamRepository: team_id
    TeamRepository-->>TeamService: team
    
    Note over TeamService: Creator auto-added as owner
    TeamService->>TeamRepository: addMember(teamId, creatorUserId, role='owner')
    TeamRepository->>Database: INSERT team_member (role='owner')
    Database-->>TeamRepository: member record
    TeamRepository-->>TeamService: TeamMember
    
    TeamService-->>TeamController: Team
    TeamController-->>Client: 201 Team created
Loading
sequenceDiagram
    participant Client
    participant TeamController
    participant TeamRepository
    participant TeamService
    participant Database

    Client->>TeamController: PATCH /-/team/:orgName/:teamName/member/:username
    activate TeamController
    TeamController->>TeamController: Verify admin/org-owner/team-owner
    TeamController->>TeamRepository: findTeamMemberByUserId(teamId, userId)
    Database-->>TeamRepository: existing member
    TeamRepository-->>TeamController: TeamMember record
    
    Note over TeamController: Validate new role, verify user exists
    TeamController->>TeamService: addMember(teamId, userId, role='owner')
    TeamService->>TeamRepository: addMember with existing member.id
    TeamRepository->>Database: UPDATE team_member SET role='owner'
    Database-->>TeamRepository: updated member
    TeamRepository-->>TeamService: TeamMember
    TeamService-->>TeamController: TeamMember
    deactivate TeamController
    TeamController-->>Client: 200 { user, role }
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • PR #1018: Directly related as this PR extends the same TeamMember model and wires role handling through shared service/repository/controller code paths introduced there.

Suggested reviewers

  • fengmk2

Poem

🐰 A role for each rabbit upon the team,
Owner and member, a permission scheme,
Through services flowing, the defaults so kind,
With tests and with docs, a clear design!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add team member role for team-level permission control' directly and clearly summarizes the main change: introducing a role field to TeamMember entities to enable team-level permission control, which is the core feature across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/team-member-role

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a role-based access control (RBAC) system for teams, adding 'owner' and 'member' roles to team memberships. Key changes include updating the TeamMember entity and database schema, modifying the TeamService to handle role assignments (automatically making creators 'owners'), and implementing new private API endpoints in the TeamController for role management. The permission logic has been refactored to allow Admins, Org Owners, and Team Owners to perform write operations, and comprehensive documentation and tests have been added. Feedback focuses on improving the clarity of error messages regarding authorized roles and ensuring consistency when listing team members by filtering out records for missing users.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.30%. Comparing base (b17983e) to head (8c005a9).
⚠️ Report is 5 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1023      +/-   ##
==========================================
+ Coverage   94.12%   94.30%   +0.17%     
==========================================
  Files         211      211              
  Lines        8619     8675      +56     
  Branches     1701     1690      -11     
==========================================
+ Hits         8113     8181      +68     
+ Misses        506      494      -12     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@elrrrrrrr elrrrrrrr requested a review from fengmk2 April 2, 2026 15:34
@elrrrrrrr elrrrrrrr added the enhancement New feature or request label Apr 2, 2026
@elrrrrrrr elrrrrrrr marked this pull request as ready for review April 2, 2026 15:34
Copilot AI review requested due to automatic review settings April 2, 2026 15:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a role (owner / member) to team membership so team-level write operations can be restricted to team owners (plus org owners/admin), while keeping npm-compatible endpoints stable and introducing private endpoints for role-aware membership management.

Changes:

  • Introduces TeamMember.role with DB migrations (MySQL/PostgreSQL) and updates entity/model/service/repository layers accordingly.
  • Tightens authorization for team write operations via team-owner checks and auto-adds the team creator as an owner.
  • Adds private APIs to list members with roles and to update a member’s role; expands tests and updates docs (ZH + new EN doc).

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
app/core/entity/TeamMember.ts Adds role field to the TeamMember domain entity.
app/repository/model/TeamMember.ts Persists role on the TeamMember ORM model.
sql/mysql/4.32.0.sql Adds role column to team_members (MySQL).
sql/postgresql/4.32.0.sql Adds role column to team_members (PostgreSQL).
app/core/service/TeamService.ts Auto-add creator as owner; supports role updates via addMember().
app/core/service/OrgService.ts Ensures developers-team membership uses explicit team roles on org creation/member add.
app/repository/TeamRepository.ts Returns team role from membership in listTeamsByUserIdAndOrgId(); supports member updates when id exists.
app/port/controller/TeamController.ts Adds/uses requireTeamWriteAccess() with team-owner checks; adds private member-role endpoints.
app/port/controller/OrgController.ts Includes role in “list user’s teams in org” response.
test/port/controller/TeamController/index.test.ts Expands test coverage for role behavior, private endpoints, and permission paths.
test/port/controller/package/ReadAccessAuth.test.ts Updates fixture setup to include TeamMember.role.
docs/org-team.md Updates Chinese docs to describe npm-compatible vs private APIs and role semantics.
docs/org-team.en.md Adds English documentation covering the same protocol/role behavior and endpoint tables.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
app/core/service/TeamService.ts (2)

22-39: ⚠️ Potential issue | 🟠 Major

Make the team + creator-owner write atomic.

createTeam() now owns a two-table invariant, but saveTeam() commits before the owner row is inserted. If the second write fails, the request errors while the team remains persisted, and retries can only hit "already exists" with no owner attached. You already handle the delete-side invariant atomically via removeTeamCascade().

💡 One way to keep the invariant atomic
-    await this.teamRepository.saveTeam(team);
-
-    // Auto-add creator as team owner
-    if (creatorUserId) {
-      const member = TeamMember.create({ teamId: team.teamId, userId: creatorUserId, role: 'owner' });
-      await this.teamRepository.addMember(member);
-    }
+    await this.teamRepository.createTeamWithCreator(team, creatorUserId);

createTeamWithCreator() should wrap both inserts in the same transaction.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/core/service/TeamService.ts` around lines 22 - 39, createTeam currently
persists the Team via teamRepository.saveTeam and then separately adds the
creator via teamRepository.addMember, which can leave a team without an owner if
the second write fails; wrap both operations in a single DB transaction so they
commit or rollback together. In TeamService.createTeam (or by adding a new
createTeamWithCreator called from createTeam when creatorUserId is present)
obtain a transactional context from the repository/ORM (e.g., a transaction
callback, EntityManager, or teamRepository.runInTransaction), then call
teamRepository.saveTeam(transactionalContext, team) and
teamRepository.addMember(transactionalContext, member) inside that transaction;
ensure failures roll back and propagate the error, and keep removeTeamCascade
behavior unchanged.

64-90: ⚠️ Potential issue | 🟠 Major

Keep the npm-compatible add-member path idempotent.

Line 267 in app/port/controller/TeamController.ts calls this without a role for PUT /-/team/:orgName/:teamName/user. With the new default 'member', re-adding an existing owner now demotes them to member instead of being a no-op, and that can leave the team with zero owners. Only mutate existing.role when a caller explicitly requested a role change, and protect the last-owner path here and in removeMember().

🛡️ Safer split between add and role-change
-  async addMember(teamId: string, userId: string, role: 'owner' | 'member' = 'member'): Promise<TeamMember> {
+  async addMember(teamId: string, userId: string, role?: 'owner' | 'member'): Promise<TeamMember> {
@@
     const existing = await this.teamRepository.findMember(teamId, userId);
     if (existing) {
-      // Update role if changed
-      if (existing.role !== role) {
+      if (role && existing.role !== role) {
+        await this.ensureOwnerWillRemain(teamId, existing, role);
         existing.role = role;
         await this.teamRepository.addMember(existing);
       }
       return existing;
     }
 
-    const member = TeamMember.create({ teamId, userId, role });
+    const member = TeamMember.create({ teamId, userId, role: role ?? 'member' });

Call the same ensureOwnerWillRemain() guard from removeMember() so the last owner cannot be removed either.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/core/service/TeamService.ts` around lines 64 - 90, The addMember path is
currently idempotent-breaking because the function signature default role =
'member' will demote an existing owner when callers omit role; change addMember
to accept role as optional (role?: 'owner' | 'member') and only mutate
existing.role when role is explicitly provided and different, calling the
existing ensureOwnerWillRemain guard before demoting an owner; also call
ensureOwnerWillRemain from removeMember to protect the last-owner path. Locate
addMember, removeMember, teamRepository.findMember and teamRepository.addMember
and update the logic so implicit calls (no role passed) are no-ops for existing
members while explicit role changes use ensureOwnerWillRemain to prevent
removing the last owner.
🧹 Nitpick comments (3)
app/core/entity/TeamMember.ts (1)

4-25: Make the default part of create() and narrow role to the supported literals.

Right now this is a two-value domain field, but the entity re-opens it to arbitrary strings and silently coerces falsy values to 'member'. A shared 'owner' | 'member' type plus a create-time default gives you a tighter contract and makes the default visible to typed callers.

♻️ Suggested change
+export type TeamMemberRole = 'owner' | 'member';
+
 interface TeamMemberData extends EntityData {
   teamMemberId: string;
   teamId: string;
   userId: string;
-  role: string;
+  role: TeamMemberRole;
 }
 
-export type CreateTeamMemberData = Omit<EasyData<TeamMemberData, 'teamMemberId'>, 'id'>;
+export type CreateTeamMemberData =
+  Omit<EasyData<TeamMemberData, 'teamMemberId'>, 'id' | 'role'> & {
+    role?: TeamMemberRole;
+  };
@@
-  role: string;
+  role: TeamMemberRole;
@@
-    this.role = data.role || 'member';
+    this.role = data.role;
   }
 
   static create(data: CreateTeamMemberData): TeamMember {
-    const newData = EntityUtil.defaultData(data, 'teamMemberId');
+    const newData = EntityUtil.defaultData({
+      role: 'member',
+      ...data,
+    }, 'teamMemberId');
     return new TeamMember(newData);
   }
If external input will be validated against this type, I’d also add the usual `isTeamMemberRole()` guard alongside the union. As per coding guidelines, "Use strict TypeScript with comprehensive type definitions; avoid `any` types", "Export types and interfaces for reusability across modules", and "Implement type guards for union types in entity files (e.g., `isGranularToken()`)".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/core/entity/TeamMember.ts` around lines 4 - 25, The TeamMember entity
currently allows any string for role and coerces falsy values in the
constructor; change the domain to a strict union and apply the default at
creation time: introduce and export type TeamMemberRole = 'owner' | 'member',
update TeamMemberData.role to TeamMemberRole, make CreateTeamMemberData.role
optional so callers can omit it, ensure the creation path (the static create()
factory or caller that constructs TeamMember) sets role = 'member' when
undefined (not by coercing falsy in the TeamMember constructor), remove the
truthy/coercion logic from the TeamMember constructor so it assumes a valid
TeamMemberRole, and add an exported type guard isTeamMemberRole(role: string):
role is TeamMemberRole to validate external input before creating TeamMember.
app/port/controller/TeamController.ts (1)

225-245: Move the role contract into request validation.

This endpoint calls requireTeamWriteAccess() before validating body.role, so malformed requests bypass the controller's schema-validation path and return auth/authorization errors before 422. Defining a typed schema for { role: 'owner' | 'member' } here would also remove the cast at Line 244.

As per coding guidelines, "Use @eggjs/typebox-validate for type-safe request validation in controllers" and "Validate requests in exact order: Parameter Validation (using @eggjs/typebox-validate) → Authentication → Authorization".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/port/controller/TeamController.ts` around lines 225 - 245, The
updateTeamMemberRole handler currently validates body.role after calling
requireTeamWriteAccess; move the role contract into request validation by adding
a TypeBox schema (e.g., Type.Object({ role: Type.Union([Type.Literal('owner'),
Type.Literal('member')]) })) and applying the `@HTTPBody/`@Validate decorator so
the controller validates the body before calling requireTeamWriteAccess; update
the method signature to use the typed body (no runtime string checks) and remove
the unnecessary cast at the teamService.addMember(...) call so it accepts the
typed 'owner' | 'member' value directly.
test/port/controller/TeamController/index.test.ts (1)

575-597: Add the owner-preservation idempotency case.

This test only proves that re-adding an existing member doesn't duplicate the row. The new service logic is riskier for existing owners, so a second case that promotes the user first, replays PUT /user, and asserts the role stays owner would catch the real regression.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/port/controller/TeamController/index.test.ts` around lines 575 - 597,
Add a new test alongside "should be idempotent when adding same user twice" that
covers owner-preservation: first use the same PUT
'/-/team/teamorg/add-team/user' endpoint (with adminUser authorization) to
promote normalUser to role "owner", then replay the identical PUT call that
previously re-added the member, and finally GET the members (GET
'/-/team/teamorg/add-team/user' using normalUser.authorization or adminUser) and
assert that normalUser's role is still "owner" (not downgraded/duplicated).
Ensure the test names the scenario clearly (e.g., "should preserve owner role
when re-adding same user") and references normalUser, adminUser and the PUT/GET
endpoints used in the existing test so it lives next to the current idempotency
case.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/repository/TeamRepository.ts`:
- Around line 94-100: The addMember method silently returns when member.id is
present but no DB row exists, hiding stale/concurrent-delete failures; change
behavior to throw an error if member.id exists but this.TeamMember.findOne({ id:
member.id }) returns null, and then handle update path normally (call
ModelConvertor.saveEntityToModel and persist), and rename the method to
saveMember to match repository naming conventions; update any call sites
accordingly and ensure the method signature and thrown error type/message are
consistent with other repository save* methods.

In `@docs/org-team.en.md`:
- Around line 311-324: The fenced code block showing the request flow is missing
a language tag (MD040); update the triple-backtick fence that precedes the flow
text to include a language (e.g., "text" or "markdown") so the block becomes
```text (or ```markdown) and leave the closing ``` unchanged; locate the block
in docs/org-team.en.md that starts with the Request GET /@scope/name flow and
add the language tag to the opening fence.

---

Outside diff comments:
In `@app/core/service/TeamService.ts`:
- Around line 22-39: createTeam currently persists the Team via
teamRepository.saveTeam and then separately adds the creator via
teamRepository.addMember, which can leave a team without an owner if the second
write fails; wrap both operations in a single DB transaction so they commit or
rollback together. In TeamService.createTeam (or by adding a new
createTeamWithCreator called from createTeam when creatorUserId is present)
obtain a transactional context from the repository/ORM (e.g., a transaction
callback, EntityManager, or teamRepository.runInTransaction), then call
teamRepository.saveTeam(transactionalContext, team) and
teamRepository.addMember(transactionalContext, member) inside that transaction;
ensure failures roll back and propagate the error, and keep removeTeamCascade
behavior unchanged.
- Around line 64-90: The addMember path is currently idempotent-breaking because
the function signature default role = 'member' will demote an existing owner
when callers omit role; change addMember to accept role as optional (role?:
'owner' | 'member') and only mutate existing.role when role is explicitly
provided and different, calling the existing ensureOwnerWillRemain guard before
demoting an owner; also call ensureOwnerWillRemain from removeMember to protect
the last-owner path. Locate addMember, removeMember, teamRepository.findMember
and teamRepository.addMember and update the logic so implicit calls (no role
passed) are no-ops for existing members while explicit role changes use
ensureOwnerWillRemain to prevent removing the last owner.

---

Nitpick comments:
In `@app/core/entity/TeamMember.ts`:
- Around line 4-25: The TeamMember entity currently allows any string for role
and coerces falsy values in the constructor; change the domain to a strict union
and apply the default at creation time: introduce and export type TeamMemberRole
= 'owner' | 'member', update TeamMemberData.role to TeamMemberRole, make
CreateTeamMemberData.role optional so callers can omit it, ensure the creation
path (the static create() factory or caller that constructs TeamMember) sets
role = 'member' when undefined (not by coercing falsy in the TeamMember
constructor), remove the truthy/coercion logic from the TeamMember constructor
so it assumes a valid TeamMemberRole, and add an exported type guard
isTeamMemberRole(role: string): role is TeamMemberRole to validate external
input before creating TeamMember.

In `@app/port/controller/TeamController.ts`:
- Around line 225-245: The updateTeamMemberRole handler currently validates
body.role after calling requireTeamWriteAccess; move the role contract into
request validation by adding a TypeBox schema (e.g., Type.Object({ role:
Type.Union([Type.Literal('owner'), Type.Literal('member')]) })) and applying the
`@HTTPBody/`@Validate decorator so the controller validates the body before
calling requireTeamWriteAccess; update the method signature to use the typed
body (no runtime string checks) and remove the unnecessary cast at the
teamService.addMember(...) call so it accepts the typed 'owner' | 'member' value
directly.

In `@test/port/controller/TeamController/index.test.ts`:
- Around line 575-597: Add a new test alongside "should be idempotent when
adding same user twice" that covers owner-preservation: first use the same PUT
'/-/team/teamorg/add-team/user' endpoint (with adminUser authorization) to
promote normalUser to role "owner", then replay the identical PUT call that
previously re-added the member, and finally GET the members (GET
'/-/team/teamorg/add-team/user' using normalUser.authorization or adminUser) and
assert that normalUser's role is still "owner" (not downgraded/duplicated).
Ensure the test names the scenario clearly (e.g., "should preserve owner role
when re-adding same user") and references normalUser, adminUser and the PUT/GET
endpoints used in the existing test so it lives next to the current idempotency
case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 59bd3553-29c9-4ba4-958e-d4aae5f76472

📥 Commits

Reviewing files that changed from the base of the PR and between 23924ac and 8c005a9.

📒 Files selected for processing (13)
  • app/core/entity/TeamMember.ts
  • app/core/service/OrgService.ts
  • app/core/service/TeamService.ts
  • app/port/controller/OrgController.ts
  • app/port/controller/TeamController.ts
  • app/repository/TeamRepository.ts
  • app/repository/model/TeamMember.ts
  • docs/org-team.en.md
  • docs/org-team.md
  • sql/mysql/4.32.0.sql
  • sql/postgresql/4.32.0.sql
  • test/port/controller/TeamController/index.test.ts
  • test/port/controller/package/ReadAccessAuth.test.ts

@elrrrrrrr elrrrrrrr merged commit d2fd3c5 into master Apr 8, 2026
21 checks passed
@elrrrrrrr elrrrrrrr deleted the feat/team-member-role branch April 8, 2026 06:28
fengmk2 pushed a commit that referenced this pull request Apr 8, 2026
[skip ci]

## 4.32.0 (2026-04-08)

* feat: add team member role for team-level permission control (#1023) ([d2fd3c5](d2fd3c5)), closes [#1023](#1023) [#1021](#1021)
* chore(deps): update dependency oxfmt to ^0.44.0 (#1025) ([2d5df34](2d5df34)), closes [#1025](#1025)
* chore(deps): update dependency oxlint-tsgolint to ^0.20.0 (#1024) ([407d659](407d659)), closes [#1024](#1024)
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 8, 2026

🎉 This PR is included in version 4.32.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants