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
@@ -4,7 +4,9 @@
|
||||
use axum::routing::{get, post};
|
||||
use axum::Router;
|
||||
|
||||
use crate::handlers::{analytics, assets, auth, cards, health, profile, share, wallet, webhooks};
|
||||
use crate::handlers::{
|
||||
analytics, assets, auth, cards, health, profile, share, teams, wallet, webhooks,
|
||||
};
|
||||
use crate::middleware::cors;
|
||||
use crate::state::AppState;
|
||||
|
||||
@@ -42,6 +44,16 @@ pub fn build_router(state: AppState) -> Router {
|
||||
.route("/s/:token", get(share::resolve_share))
|
||||
.route("/profile/:handle/contact", post(profile::submit_contact))
|
||||
.route("/webhooks/revenuecat", post(webhooks::revenuecat))
|
||||
.route("/teams", post(teams::create_team))
|
||||
.route("/teams/:id", get(teams::get_team))
|
||||
.route(
|
||||
"/teams/:id/members",
|
||||
get(teams::list_members).post(teams::add_member),
|
||||
)
|
||||
.route(
|
||||
"/teams/:id/members/:userId",
|
||||
axum::routing::delete(teams::remove_member),
|
||||
)
|
||||
.route("/analytics/event", post(analytics::ingest_event))
|
||||
.route("/assets/upload", post(assets::presign_upload))
|
||||
.route("/assets/*key", axum::routing::delete(assets::delete_asset));
|
||||
|
||||
Reference in New Issue
Block a user