Files
rehearshalhub/BAND_INVITATION_ANALYSIS.md
Mistral Vibe ce228919df Add comprehensive band invitation system analysis and implementation plan
- Deep dive into existing band invitation implementation
- Identified gaps in current system (invite listing, revocation, user search)
- Created detailed architecture analysis and design options
- Documented comprehensive implementation plan with phases
- Includes backend endpoints, frontend components, and testing strategy

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-04-01 11:26:08 +02:00

16 KiB

Band Invitation System - Current State Analysis & New Design

📊 Current System Overview

Existing Implementation

The current system already has a basic band invitation feature implemented:

Backend (API)

  • Database Models: band_invites table with token-based invites (72h expiry)
  • Endpoints:
    • POST /bands/{id}/invites - Generate invite link
    • POST /invites/{token}/accept - Join band via invite
  • Repositories: BandRepository has invite methods
  • Services: BandService handles invite creation

Frontend (Web)

  • InvitePage.tsx: Accept invite page (/invite/:token)
  • BandPage.tsx: Generate invite link UI with copy functionality

Current Limitations

  1. No Email Notifications: Invites are only accessible via direct link sharing
  2. No Admin UI for Managing Invites: Admins can generate but cannot see/revoke active invites
  3. No Invite Listing: No endpoint to list all pending invites for a band
  4. No Invite Expiry Management: 72h expiry is hardcoded, no admin control
  5. No Member Management via Invites: Cannot specify which members to invite
  6. No Bulk Invites: Only one invite at a time
  7. No Invite Status Tracking: Cannot track which invites were sent to whom

🎯 Requirements Analysis

Based on the new requirements:

Functional Requirements

  1. A user with an existing band instance can invite users registered to the system
  2. Invited users are added to the band
  3. No link handling needed (requirement clarification needed)
  4. The user with the band instance is the admin (can add/remove members)

Clarification Needed

  • "No link handling needed" - Does this mean:
    • Option A: No email notifications, just direct link sharing (current system)
    • Option B: Implement email notifications
    • Option C: Implement both with configuration

🏗️ Current Architecture Analysis

Data Flow (Current)

Admin User → POST /bands/{id}/invites → Generate Token → Display Link → 
User → GET /invites/{token} → Accept → POST /invites/{token}/accept → 
Add to Band as Member

Key Components

Backend Components

┌───────────────────────┐    ┌───────────────────────┐
│   BandRepository      │    │     BandService       │
│                       │    │                       │
│ - create_invite()     │    │ - Create token        │
│ - get_invite_by_token()│   │ - Set 72h expiry      │
├───────────────────────┤    ├───────────────────────┤
│                       │    │                       │
│   BandInvite Model    │    │   Auth Flow           │
│                       │    │                       │
│ - token (UUID)        │    │ JWT based auth        │
│ - band_id (FK)        │    │                       │
│ - role (admin/member) │    │                       │
│ - created_by (FK)     │    │                       │
│ - expires_at          │    │                       │
│ - used_at             │    │                       │
│ - used_by (FK)        │    │                       │
└───────────────────────┘    └───────────────────────┘

Frontend Components

┌───────────────────────────────────────────────────┐
│                 Web Application                    │
├─────────────────┬─────────────────┬───────────────┤
│   InvitePage    │    BandPage     │   Auth        │
│  (Accept Invite)│ (Generate Link) │               │
└─────────────────┴─────────────────┴───────────────┘

🔍 Gap Analysis

Backend Gaps

Feature Current Status Gap Priority
Invite generation No bulk invite support High
Invite listing No endpoint to list invites High
Invite acceptance
Invite expiry Hardcoded 72h, no admin control Medium
Invite revocation No way to revoke pending invites High
Member removal Only via direct removal, not invite-based Medium
Email notifications No integration Low (optional)
Search for users to invite No user search/filter High

Frontend Gaps

Feature Current Status Gap Priority
Generate invite UI exists but no invite management High
View active invites No UI to view/list invites High
Revoke invites No revoke functionality High
Email copy Copy to clipboard works
Search users No user search for invites High
Bulk invites No UI for multiple invites Medium

🎨 Proposed New Architecture

Pros:

  • Minimal changes to existing flow
  • Maintains simplicity
  • No email dependency
  • Works well for small bands

Cons:

  • Requires manual link sharing
  • No notification system

Option 2: Email-Based Invitation System

Pros:

  • Automatic notifications
  • Better UX for invitees
  • Can track delivery status

Cons:

  • Requires email infrastructure
  • More complex setup
  • Privacy considerations
  • May need SMTP configuration

Option 3: Hybrid Approach

Pros:

  • Best of both worlds
  • Flexibility for users
  • Can start simple, add email later

Cons:

  • More complex implementation
  • Two code paths

📋 Detailed Design (Option 1 - Enhanced Token-Based)

Backend Changes

Database Schema (No Changes Needed)

Current schema is sufficient. We'll use existing band_invites table.

New API Endpoints

# Band Invites Management
GET    /bands/{band_id}/invites          # List all pending invites for band
POST   /bands/{band_id}/invites          # Create new invite (existing)
DELETE /invites/{invite_id}              # Revoke pending invite

# Invite Actions
GET    /invites/{token}/info              # Get invite details (without accepting)
POST   /invites/{token}/accept            # Accept invite (existing)

# Member Management
DELETE /bands/{band_id}/members/{member_id}  # Remove member (existing)

Enhanced Band Service Methods

class BandService:
    async def list_invites(self, band_id: UUID, admin_id: UUID) -> list[BandInvite]
        """List all pending invites for a band (admin only)"""
        
    async def create_invite(
        self, 
        band_id: UUID, 
        created_by: UUID,
        role: str = "member",
        ttl_hours: int = 72,
        email: str | None = None  # Optional email for notifications
    ) -> BandInvite:
        """Create invite with optional email notification"""
        
    async def revoke_invite(self, invite_id: UUID, admin_id: UUID) -> None:
        """Revoke pending invite"""
        
    async def get_invite_info(self, token: str) -> BandInviteInfo:
        """Get invite details without accepting"""

New Schemas

class BandInviteCreate(BaseModel):
    role: str = "member"
    ttl_hours: int = 72
    email: str | None = None  # Optional email for notifications

class BandInviteRead(BaseModel):
    id: UUID
    band_id: UUID
    token: str
    role: str
    expires_at: datetime
    created_at: datetime
    used: bool
    used_at: datetime | None
    used_by: UUID | None
    
class BandInviteList(BaseModel):
    invites: list[BandInviteRead]
    total: int
    pending: int

Frontend Changes

New Pages/Components

// InviteManagement.tsx - New component for band page
// Shows list of active invites with revoke option

// UserSearch.tsx - New component for finding users to invite
// Searchable list of registered users

// InviteDetails.tsx - Modal for invite details
// Shows invite info before acceptance

Enhanced BandPage

// Enhanced features:
- Invite Management section
  - List of pending invites
  - Revoke button for each
  - Copy invite link
  - Expiry timer
  
- Invite Creation
  - Search users to invite
  - Select role (member/admin)
  - Set expiry (default 72h)
  - Bulk invite option

New API Wrappers

// api/invites.ts
export const listInvites = (bandId: string) => 
  api.get<BandInvite[]>(`/bands/${bandId}/invites`);

export const createInvite = (bandId: string, data: {
  role?: string;
  ttl_hours?: number;
  email?: string;
}) => 
  api.post<BandInvite>(`/bands/${bandId}/invites`, data);

export const revokeInvite = (inviteId: string) => 
  api.delete(`/invites/${inviteId}`);

export const getInviteInfo = (token: string) => 
  api.get<BandInviteInfo>(`/invites/${token}/info`);

🛠️ Implementation Plan

Phase 1: Backend Enhancements

Task 1: Add Invite Listing Endpoint

File: api/src/rehearsalhub/routers/bands.py
Method: GET /bands/{band_id}/invites
Returns: List of pending invites with details

Task 2: Add Invite Revocation Endpoint

File: api/src/rehearsalhub/routers/bands.py
Method: DELETE /invites/{invite_id}
Logic: Check admin permissions, soft delete if pending

Task 3: Add Get Invite Info Endpoint

File: api/src/rehearsalhub/routers/bands.py
Method: GET /invites/{token}/info
Returns: Invite details without accepting

Task 4: Enhance Create Invite Endpoint

File: api/src/rehearsalhub/routers/bands.py
Method: POST /bands/{band_id}/invites
Add: Optional email parameter, return full invite info

Task 5: Update BandRepository

File: api/src/rehearsalhub/repositories/band.py
Add: Methods for listing, updating invite status

Task 6: Update BandService

File: api/src/rehearsalhub/services/band.py
Add: Service methods for invite management

Task 7: Update Schemas

File: api/src/rehearsalhub/schemas/invite.py
Add: BandInviteRead, BandInviteList schemas

Phase 2: Frontend Implementation

Task 8: Create User Search Component

File: web/src/components/UserSearch.tsx
Function: Search and select users to invite

Task 9: Create Invite Management Component

File: web/src/components/InviteManagement.tsx
Function: List, view, and revoke invites

Task 10: Enhance BandPage

File: web/src/pages/BandPage.tsx
Add: Sections for invite management and creation

Task 11: Create BandInvite Type Definitions

File: web/src/api/invites.ts
Add: TypeScript interfaces for new endpoints

Task 12: Update API Wrappers

File: web/src/api/invites.ts
Add: Functions for new invite endpoints

Phase 3: Testing

Unit Tests

  • BandRepository invite methods
  • BandService invite methods
  • API endpoint authentication/authorization

Integration Tests

  • Invite creation flow
  • Invite listing
  • Invite revocation
  • Invite acceptance
  • Permission checks

E2E Tests

  • Full invite flow in browser
  • Mobile responsiveness
  • Error handling

🧪 Testing Strategy

Test Scenarios

  1. Happy Path - Single Invite

    • Admin creates invite
    • Link is generated and displayed
    • User accepts via link
    • User is added to band
  2. Happy Path - Multiple Invites

    • Admin creates multiple invites
    • All links work independently
    • Each user accepts and joins
  3. Happy Path - Invite Expiry

    • Create invite with custom expiry
    • Wait for expiry
    • Verify invite no longer works
  4. Happy Path - Invite Revocation

    • Admin creates invite
    • Admin revokes invite
    • Verify invite link no longer works
  5. Error Handling - Invalid Token

    • User visits invalid/expired link
    • Clear error message displayed
  6. Error Handling - Non-Member Access

    • Non-admin tries to manage invites
    • Permission denied
  7. Error Handling - Already Member

    • User already in band tries to accept invite
    • Graceful handling

Test Setup

# api/tests/integration/test_api_invites.py
@pytest.fixture
def invite_factory(db_session):
    """Factory for creating test invites"""

@pytest.mark.asyncio
async def test_create_invite(client, db_session, auth_headers_for, current_member, band):
    """Test invite creation"""
    
@pytest.mark.asyncio  
async def test_list_invites(client, db_session, auth_headers_for, current_member, band):
    """Test invite listing"""
    
@pytest.mark.asyncio
async def test_revoke_invite(client, db_session, auth_headers_for, current_member, band):
    """Test invite revocation"""

🔄 Iteration Plan

Iteration 1: MVP (Minimum Viable Product)

Scope: Basic invite functionality with listing and revocation Timeline: 1-2 weeks Features:

  • Invite creation (existing)
  • Invite listing for admins
  • Invite revocation
  • Invite info endpoint
  • Frontend listing UI
  • Frontend revoke button

Iteration 2: Enhanced UX

Scope: Improve user experience Timeline: 1 week Features:

  • 🔄 User search for invites
  • 🔄 Bulk invite support
  • 🔄 Custom expiry times
  • 🔄 Invite copy improvements

Iteration 3: Optional Features

Scope: Add-ons based on user feedback Timeline: 1-2 weeks (optional) Features:

  • 🔄 Email notifications
  • 🔄 Invite analytics
  • 🔄 QR code generation
  • 🔄 Group invites

⚠️ Risk Assessment

Technical Risks

Risk Likelihood Impact Mitigation
Token collision Low High Use proper random generation (secrets.token_urlsafe)
Race conditions Medium Medium Proper locking in repo layer
Permission bypass Medium High Comprehensive auth checks
Frontend complexity Low Medium Incremental implementation

Design Risks

Risk Likelihood Impact Mitigation
Feature creep Medium Medium Strict MVP scope
UX complexity Low Medium User testing early
Performance issues Low Medium Pagination for invite lists

📊 Success Criteria

  1. Functional:

    • Users can be invited to bands
    • Invites can be listed and managed by admins
    • Invites properly expire
    • No security vulnerabilities
  2. Usability:

    • Clear UI for invite management
    • Intuitive invite generation
    • Good error messages
  3. Performance:

    • API endpoints < 500ms response time
    • Invite lists paginated (if > 50 invites)
    • No database bottlenecks
  4. Test Coverage:

    • Unit tests: 80%+ coverage
    • Integration tests: All critical paths
    • E2E tests: Happy paths

🎯 Recommendations

Immediate Actions

  1. Implement Phase 1 backend changes (MVP scope)
  2. Add comprehensive tests
  3. Get stakeholder feedback on UI design

Future Enhancements

  1. Add email notification system (Iteration 3)
  2. Implement analytics (views, acceptance rates)
  3. Add invitation analytics to admin dashboard

Questions for Stakeholders

  1. "No link handling needed" - Should we implement email notifications?
  2. Do we need bulk invite support in MVP?
  3. What's the expected scale (number of invites per band)?
  4. Should we track who created each invite?
  5. Do we need to support external (non-registered) email invites?

📝 Next Steps

  1. Review this analysis with stakeholders
  2. Prioritize features for MVP vs future iterations
  3. Assign tasks based on team capacity
  4. Start implementation with Phase 1 backend
  5. Iterate based on testing and feedback