Follow-up from #44, which introduced self-serve Team creation. The limitation below is deliberate and documented in the source; this issue exists so it is tracked rather than living only in a code comment.
Reproduction steps
- Sign in as any authenticated user.
POST /api/v1/teams fifty times. TEAM_MEMBERSHIP_LIMIT (50) now refuses the fifty-first.
- For each Team, invite a second account and promote it to admin.
leave each Team. #guardDeparture only requires that another admin exists, not that the caller is the sole one, so every departure succeeds and each membership becomes left.
- The active-membership count is back to zero. Repeat from step 2 indefinitely.
Expected behavior
Self-serve Team creation is bounded per account.
Actual behavior
Only the active-membership count is bounded. The Teams created in each round persist, and so do their canonical names — which are globally unique via teams_name_unique on lower(name). One account can therefore consume short canonical names for the whole deployment.
TEAM_MEMBERSHIP_LIMIT is not the fix and does not claim to be; packages/server/src/services/teams/team-membership-service.ts states that it bounds the /me membership fan-out and is explicitly not a durable creation quota.
Root cause
There is no durable record of who created a Team. teams carries id, name, display_name, created_at, updated_at — nothing attributing authorship — so "how many Teams has this account created" cannot be answered after the creator leaves.
The same missing column blocks a second item: the product plan (first-tree-context#962 §6.12) specifies that Settings → Team shows 创建者, which is currently unimplementable for the same reason.
Environment
main at 16dd77e (#44). Server-side only; no client or platform dependency.
Notes on fixing
Adding teams.created_by would address both this and §6.12, but it is a schema change and needs explicit approval per the repo's DB-change rule. Rate limiting POST /api/v1/teams would bound the abuse without a migration, though the repository has no rate-limiting infrastructure today — ErrorCodeSchema already reserves RATE_LIMITED.
Realistic exposure is low for a single-organization deployment, where the actor would be an authenticated colleague. It matters more for any multi-tenant or open-signup deployment.
Follow-up from #44, which introduced self-serve Team creation. The limitation below is deliberate and documented in the source; this issue exists so it is tracked rather than living only in a code comment.
Reproduction steps
POST /api/v1/teamsfifty times.TEAM_MEMBERSHIP_LIMIT(50) now refuses the fifty-first.leaveeach Team.#guardDepartureonly requires that another admin exists, not that the caller is the sole one, so every departure succeeds and each membership becomesleft.Expected behavior
Self-serve Team creation is bounded per account.
Actual behavior
Only the active-membership count is bounded. The Teams created in each round persist, and so do their canonical names — which are globally unique via
teams_name_uniqueonlower(name). One account can therefore consume short canonical names for the whole deployment.TEAM_MEMBERSHIP_LIMITis not the fix and does not claim to be;packages/server/src/services/teams/team-membership-service.tsstates that it bounds the/memembership fan-out and is explicitly not a durable creation quota.Root cause
There is no durable record of who created a Team.
teamscarriesid,name,display_name,created_at,updated_at— nothing attributing authorship — so "how many Teams has this account created" cannot be answered after the creator leaves.The same missing column blocks a second item: the product plan (first-tree-context#962 §6.12) specifies that Settings → Team shows 创建者, which is currently unimplementable for the same reason.
Environment
mainat 16dd77e (#44). Server-side only; no client or platform dependency.Notes on fixing
Adding
teams.created_bywould address both this and §6.12, but it is a schema change and needs explicit approval per the repo's DB-change rule. Rate limitingPOST /api/v1/teamswould bound the abuse without a migration, though the repository has no rate-limiting infrastructure today —ErrorCodeSchemaalready reservesRATE_LIMITED.Realistic exposure is low for a single-organization deployment, where the actor would be an authenticated colleague. It matters more for any multi-tenant or open-signup deployment.