Phase 4 backend: teams data layer + membership management
- Migration 0003: teams + team_memberships (owner/admin/member, seat_limit)
- POST /v1/teams (Team-tier gated), GET /v1/teams/{id},
GET|POST /v1/teams/{id}/members, DELETE …/members/{userId}
- Add-by-email (existing accounts), seat-cap enforcement (402), role-based
authorization (admin to mutate; non-members get 404; owner unremovable)
- Invite notification email; Tier::can_own_team()
100 backend tests; fmt + clippy clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
4ad3220917
commit
2b8e23dd3f
@@ -0,0 +1,23 @@
|
||||
-- 0003_teams.sql — Team tier data layer (PRD §21 Phase 4).
|
||||
|
||||
CREATE TABLE teams (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
owner_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
-- NULL = unlimited seats; otherwise the billed seat cap.
|
||||
seat_limit INTEGER,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_teams_owner ON teams(owner_id);
|
||||
|
||||
CREATE TABLE team_memberships (
|
||||
team_id UUID NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
role TEXT NOT NULL DEFAULT 'member'
|
||||
CHECK (role IN ('owner', 'admin', 'member')),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (team_id, user_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_team_memberships_user ON team_memberships(user_id);
|
||||
Reference in New Issue
Block a user