docs: optimize documentation for token efficiency
- SESSION_CONTEXT.md: 485 → 132 lines (-73%) - Remove outdated "Next Steps" sections - Remove detailed file listings - Keep only essential quick-reference info - TODO.md: 917 → 118 lines (-87%) - Move detailed phase descriptions to COMPLETED.md - Keep security audit, checklist, future improvements - Remove redundant implementation details - CONTEXT.md: Update test count to 286/286
This commit is contained in:
@@ -89,7 +89,7 @@ Browser A ←──────────────────────
|
|||||||
- Socket.IO 4.8.1 (WebSocket)
|
- Socket.IO 4.8.1 (WebSocket)
|
||||||
- PostgreSQL 15 with Prisma ORM 5.8.0
|
- PostgreSQL 15 with Prisma ORM 5.8.0
|
||||||
- bcrypt + JWT authentication
|
- bcrypt + JWT authentication
|
||||||
- Jest + Supertest (223/223 tests passing)
|
- Jest + Supertest (286/286 tests passing, 73% coverage)
|
||||||
|
|
||||||
### WebRTC
|
### WebRTC
|
||||||
- RTCPeerConnection (implemented)
|
- RTCPeerConnection (implemented)
|
||||||
@@ -175,6 +175,6 @@ const wyslijWiadomosc = (wiadomosc) => {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Last Updated:** 2025-11-20
|
**Last Updated:** 2025-11-23
|
||||||
|
|
||||||
**Status:** ✅ MVP Complete - All core features implemented and tested
|
**Status:** ✅ MVP Complete - All core features implemented and tested
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Session Context - spotlight.cam
|
# Session Context - spotlight.cam
|
||||||
|
|
||||||
**Quick reference for resuming development sessions - optimized for minimal token usage**
|
**Quick reference for resuming development sessions**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -15,471 +15,118 @@
|
|||||||
|
|
||||||
## Current Status
|
## Current Status
|
||||||
|
|
||||||
**Phase:** 3 (MVP Finalization) - ✅ COMPLETED
|
**Phase:** MVP Complete - Ready for Production Deployment
|
||||||
**Current Phase:** Ready for Production Deployment
|
**Tests:** 286/286 backend tests passing (73% coverage)
|
||||||
**Previous Phases:**
|
**Next Goal:** Infrastructure setup (server, domain, SSL)
|
||||||
- Phase 2.5 (WebRTC P2P File Transfer) - ✅ COMPLETED
|
|
||||||
- Phase 2 (Matches & Ratings API) - ✅ COMPLETED
|
|
||||||
- Phase 1.6 (Competition Heats) - ✅ COMPLETED
|
|
||||||
- Phase 1.5 (Email & WSDC & Profiles & Security & QR Check-in) - ✅ COMPLETED
|
|
||||||
**Progress:** 100% MVP complete
|
|
||||||
**Next Goal:** Production deployment (infrastructure setup)
|
|
||||||
|
|
||||||
### What Works Now
|
### Core Features (All Implemented)
|
||||||
- ✅ Docker Compose (nginx:8080 + frontend + backend + PostgreSQL)
|
- JWT authentication with email verification (AWS SES)
|
||||||
- ✅ All frontend views with real API integration
|
- Real-time chat (Socket.IO) - event rooms + private 1:1
|
||||||
- ✅ Backend API (Node.js + Express)
|
- WebRTC P2P file transfer (RTCDataChannel, up to 700MB tested)
|
||||||
- ✅ PostgreSQL database with 8 tables (Prisma ORM)
|
- Competition heats system for matchmaking
|
||||||
- ✅ Real authentication (JWT + bcrypt)
|
- Recording matching system (auto-assign recorders)
|
||||||
- ✅ **Email verification (AWS SES with link + PIN code) - Phase 1.5**
|
- Matches & ratings API
|
||||||
- ✅ **Password reset workflow - Phase 1.5**
|
- QR code event check-in
|
||||||
- ✅ **WSDC ID integration for auto-fill registration - Phase 1.5**
|
- PWA (offline support, iOS compatible)
|
||||||
- ✅ **User profiles with social media & location - Phase 1.5**
|
- Security: CSRF, rate limiting, account lockout
|
||||||
- ✅ **Public profiles (/{username}) - Phase 1.5**
|
|
||||||
- ✅ **Event participation tracking - Phase 1.5**
|
|
||||||
- ✅ **Event security (unique slugs, no ID enumeration) - Phase 1.5**
|
|
||||||
- ✅ **QR code event check-in system - Phase 1.5** (requires physical presence at venue)
|
|
||||||
- ✅ **Competition heats declaration system - Phase 1.6** (matchmaking prerequisite)
|
|
||||||
- ✅ **Matches API (create/accept/list matches with slugs) - Phase 2**
|
|
||||||
- ✅ **Ratings API (rate partners, 1-5 stars, comments) - Phase 2**
|
|
||||||
- ✅ **WebRTC signaling (SDP/ICE exchange via Socket.IO) - Phase 2.5**
|
|
||||||
- ✅ **WebRTC P2P file transfer (RTCDataChannel, 16KB chunks, up to 700MB tested) - Phase 2.5**
|
|
||||||
- ✅ **WebRTC detection & fallback UX (auto-detect browser capabilities) - Phase 2.5**
|
|
||||||
- ✅ **STUN servers for NAT traversal (production-ready) - Phase 2.5**
|
|
||||||
- ✅ **Landing page with hero section and features showcase - Phase 3**
|
|
||||||
- ✅ **WebRTC test suite (7 backend tests passing) - Phase 3**
|
|
||||||
- ✅ **Security hardening (CSRF protection, Account Lockout, Rate Limiting) - Phase 3**
|
|
||||||
- ✅ **PWA features (manifest, icons, service worker, iOS support, install prompt) - Phase 3**
|
|
||||||
- ✅ Real-time chat (Socket.IO for event & match rooms)
|
|
||||||
|
|
||||||
### What's Missing
|
|
||||||
- ⏳ Competition heats UI integration improvements (optional UX enhancements)
|
|
||||||
|
|
||||||
### Ready for Production
|
|
||||||
- ✅ All core features implemented and tested
|
|
||||||
- ✅ Security hardening complete
|
|
||||||
- ✅ Operations scripts and monitoring ready
|
|
||||||
- ⏳ Awaiting infrastructure setup (server, domain, SSL)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Tech Stack
|
## Project Structure (Key Paths)
|
||||||
|
|
||||||
**Infrastructure:**
|
|
||||||
- Docker Compose (nginx, frontend, backend, PostgreSQL db)
|
|
||||||
- nginx reverse proxy on port 8080 (API + WebSocket)
|
|
||||||
|
|
||||||
**Frontend:**
|
|
||||||
- React 18 + Vite
|
|
||||||
- Tailwind CSS v3.4.0 (NOT v4 - compatibility issues)
|
|
||||||
- React Router
|
|
||||||
- Context API for state
|
|
||||||
- socket.io-client for real-time chat
|
|
||||||
- PWA (vite-plugin-pwa, Workbox for service worker)
|
|
||||||
|
|
||||||
**Backend:**
|
|
||||||
- Node.js 20 + Express 4.18.2
|
|
||||||
- Socket.IO 4.8.1 for WebSocket (real-time chat)
|
|
||||||
- PostgreSQL 15 with Prisma ORM 5.8.0
|
|
||||||
- bcrypt + JWT authentication
|
|
||||||
- Jest + supertest for testing (223/223 tests passing, 71% coverage)
|
|
||||||
|
|
||||||
**WebRTC:**
|
|
||||||
- RTCPeerConnection
|
|
||||||
- RTCDataChannel (file transfer)
|
|
||||||
- Chunking (16KB chunks)
|
|
||||||
- STUN/TURN servers
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Project Structure
|
|
||||||
|
|
||||||
```
|
```
|
||||||
/spotlightcam
|
/spotlightcam
|
||||||
├── docker-compose.yml # nginx + frontend + backend + PostgreSQL
|
├── docker-compose.yml # nginx:8080 + frontend + backend + db
|
||||||
├── nginx/ # Proxy config (API + WebSocket)
|
├── frontend/src/
|
||||||
├── frontend/ # React PWA
|
│ ├── pages/ # React pages
|
||||||
│ ├── src/
|
│ ├── components/ # Reusable components
|
||||||
│ │ ├── pages/ # All views (Login, Register, Events, Chat, Match, Rate, History)
|
│ ├── contexts/ # AuthContext
|
||||||
│ │ ├── contexts/ # AuthContext (JWT integration)
|
│ ├── services/ # api.js, socket.js
|
||||||
│ │ ├── components/ # Layout, Navbar
|
│ ├── hooks/ # useWebRTC.js
|
||||||
│ │ ├── services/ # API client, Socket.IO client
|
│ └── constants/ # MATCH_STATUS, SUGGESTION_STATUS, etc.
|
||||||
│ │ └── mocks/ # Mock data (events, users for UI)
|
├── backend/src/
|
||||||
├── backend/ # Node.js + Express API
|
│ ├── routes/ # API endpoints
|
||||||
│ ├── src/
|
│ ├── controllers/ # Business logic
|
||||||
│ │ ├── controllers/ # Auth, users, events
|
│ ├── services/ # matching.js (auto-matching algorithm)
|
||||||
│ │ ├── middleware/ # Authentication middleware
|
│ ├── socket/ # Socket.IO handlers
|
||||||
│ │ ├── routes/ # API routes
|
│ ├── constants/ # Status constants
|
||||||
│ │ ├── socket/ # Socket.IO server
|
│ └── __tests__/ # Jest tests
|
||||||
│ │ ├── utils/ # Auth utils, DB connection
|
|
||||||
│ │ └── __tests__/ # Jest unit tests
|
|
||||||
│ └── prisma/ # Database schema, migrations, seed
|
|
||||||
└── docs/
|
└── docs/
|
||||||
├── SESSION_CONTEXT.md # This file
|
├── TODO.md # Current tasks & security audit
|
||||||
├── CONTEXT.md # Full project description
|
|
||||||
├── TODO.md # Task list
|
|
||||||
├── ARCHITECTURE.md # Technical details
|
├── ARCHITECTURE.md # Technical details
|
||||||
├── QUICKSTART.md # Quick start guide
|
└── archive/COMPLETED.md # Historical reference
|
||||||
├── WEBRTC_TESTING_GUIDE.md # WebRTC testing
|
|
||||||
└── archive/ # Archived docs
|
|
||||||
├── COMPLETED.md # Completed tasks archive
|
|
||||||
└── RESOURCES.md # Learning resources
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Key Files
|
## Database Schema (11 tables)
|
||||||
|
|
||||||
**Frontend:**
|
Key models:
|
||||||
- `frontend/src/pages/HomePage.jsx` - **NEW: Landing page with hero section - Phase 3**
|
- `users` - Auth, profile, social links, location, lockout fields
|
||||||
- `frontend/src/pages/RegisterPage.jsx` - Two-step registration (WSDC lookup + form)
|
- `events` - Dance events with unique slugs
|
||||||
- `frontend/src/pages/VerifyEmailPage.jsx` - Email verification (link + code)
|
- `event_participants` - User-event relationship, competitorNumber
|
||||||
- `frontend/src/pages/ForgotPasswordPage.jsx` - Request password reset
|
- `divisions` / `competition_types` / `event_user_heats` - Competition system
|
||||||
- `frontend/src/pages/ResetPasswordPage.jsx` - Reset password with token
|
- `matches` - User pairings with CUID slugs
|
||||||
- `frontend/src/pages/ProfilePage.jsx` - **UPDATED: Edit profile (social media, location) - Phase 1.5**
|
- `ratings` - 1-5 stars, comments
|
||||||
- `frontend/src/pages/PublicProfilePage.jsx` - **NEW: View other user profiles - Phase 1.5**
|
- `recording_suggestions` - Auto-matching results
|
||||||
- `frontend/src/pages/EventsPage.jsx` - **UPDATED: Shows check-in requirement, dev-only QR access - Phase 1.5**
|
- `chat_rooms` / `messages` - Real-time chat persistence
|
||||||
- `frontend/src/pages/EventChatPage.jsx` - **UPDATED: Heats integration (banner, badges, filtering) - Phase 1.6**
|
|
||||||
- `frontend/src/pages/EventDetailsPage.jsx` - **NEW: QR code display, participant list - Phase 1.5**
|
|
||||||
- `frontend/src/pages/EventCheckinPage.jsx` - **NEW: Check-in confirmation page - Phase 1.5**
|
|
||||||
- `frontend/src/pages/MatchChatPage.jsx` - **UPDATED: WebRTC P2P file transfer - Phase 2.5**
|
|
||||||
- `frontend/src/hooks/useWebRTC.js` - **NEW: WebRTC hook (RTCPeerConnection, RTCDataChannel) - Phase 2.5**
|
|
||||||
- `frontend/src/utils/webrtcDetection.js` - **NEW: WebRTC browser detection - Phase 2.5**
|
|
||||||
- `frontend/src/components/WebRTCWarning.jsx` - **NEW: WebRTC blocked warning component - Phase 2.5**
|
|
||||||
- `frontend/src/components/heats/HeatsBanner.jsx` - **NEW: Heats declaration form component - Phase 1.6**
|
|
||||||
- `frontend/src/components/pwa/InstallPWA.jsx` - **NEW: PWA install prompt (Android + iOS) - Phase 3**
|
|
||||||
- `frontend/src/components/common/PasswordStrengthIndicator.jsx` - Password strength indicator
|
|
||||||
- `frontend/src/components/common/VerificationBanner.jsx` - Email verification banner
|
|
||||||
- `frontend/src/contexts/AuthContext.jsx` - JWT authentication integration
|
|
||||||
- `frontend/src/services/api.js` - **UPDATED: Heats API, CSRF token handling - Phase 1.6 & Phase 3**
|
|
||||||
- `frontend/src/services/socket.js` - Socket.IO client connection manager
|
|
||||||
- `frontend/src/data/countries.js` - **NEW: List of 195 countries - Phase 1.5**
|
|
||||||
- `frontend/src/utils/__tests__/webrtcDetection.test.js` - **NEW: WebRTC detection tests - Phase 3**
|
|
||||||
- `frontend/src/components/__tests__/WebRTCWarning.test.jsx` - **NEW: WebRTC warning tests - Phase 3**
|
|
||||||
- `frontend/vite.config.js` - **UPDATED: PWA plugin configuration - Phase 3**
|
|
||||||
- `frontend/index.html` - **UPDATED: iOS PWA meta tags, app icons, splash screens - Phase 3**
|
|
||||||
- `frontend/public/icons/` - **NEW: App icons (192x192, 512x512, apple-touch-icon) - Phase 3**
|
|
||||||
- `frontend/public/splash/` - **NEW: iOS splash screens for various devices - Phase 3**
|
|
||||||
|
|
||||||
**Backend:**
|
|
||||||
- `backend/src/app.js` - **UPDATED: CSRF protection, cookie-parser middleware - Phase 3**
|
|
||||||
- `backend/src/controllers/auth.js` - **UPDATED: Account lockout logic in login - Phase 3**
|
|
||||||
- `backend/src/controllers/user.js` - **UPDATED: Profile updates (social, location) - Phase 1.5**
|
|
||||||
- `backend/src/controllers/wsdc.js` - WSDC API proxy for dancer lookup
|
|
||||||
- `backend/src/config/security.js` - **Security configuration (CSRF, rate limiting, account lockout)**
|
|
||||||
- `backend/src/routes/events.js` - **UPDATED: Heats management endpoints (POST/GET/DELETE /heats) - Phase 1.6**
|
|
||||||
- `backend/src/routes/divisions.js` - **NEW: List all divisions - Phase 1.6**
|
|
||||||
- `backend/src/routes/competitionTypes.js` - **NEW: List all competition types - Phase 1.6**
|
|
||||||
- `backend/src/routes/users.js` - **UPDATED: Public profile endpoint - Phase 1.5**
|
|
||||||
- `backend/src/socket/index.js` - **UPDATED: WebRTC signaling (offer/answer/ICE), heats_updated - Phase 2.5**
|
|
||||||
- `backend/src/utils/email.js` - AWS SES email service with HTML templates
|
|
||||||
- `backend/src/utils/auth.js` - Token generation utilities
|
|
||||||
- `backend/src/middleware/auth.js` - Email verification middleware
|
|
||||||
- `backend/src/middleware/rateLimiter.js` - Rate limiting middleware (API, auth, email)
|
|
||||||
- `backend/src/middleware/validators.js` - **UPDATED: Social media URL validation - Phase 1.5**
|
|
||||||
- `backend/src/server.js` - Express server with Socket.IO integration
|
|
||||||
- `backend/src/__tests__/socket-webrtc.test.js` - **NEW: WebRTC signaling tests (7 tests) - Phase 3**
|
|
||||||
- `backend/src/__tests__/auth.test.js` - **UPDATED: Account lockout tests (6 new tests) - Phase 3**
|
|
||||||
- `backend/src/__tests__/csrf.test.js` - **NEW: CSRF protection tests (11 tests) - Phase 3**
|
|
||||||
- `backend/src/__tests__/events.test.js` - Events API tests
|
|
||||||
- `backend/src/__tests__/matches.test.js` - Matches API tests
|
|
||||||
- `backend/prisma/schema.prisma` - **UPDATED: Account lockout fields (failedLoginAttempts, lockedUntil) - Phase 3**
|
|
||||||
- `backend/prisma/migrations/20251113151534_add_wsdc_and_email_verification/` - Phase 1.5 migration
|
|
||||||
- `backend/prisma/migrations/20251113202500_add_event_slug/` - **NEW: Event slugs migration - Phase 1.5**
|
|
||||||
- `backend/prisma/migrations/20251114125544_add_event_checkin_tokens/` - **NEW: QR check-in tokens - Phase 1.5**
|
|
||||||
- `backend/prisma/migrations/20251119_add_account_lockout_fields/` - **NEW: Account lockout migration - Phase 3**
|
|
||||||
|
|
||||||
**Config:**
|
|
||||||
- `docker-compose.yml` - nginx, frontend, backend, PostgreSQL
|
|
||||||
- `nginx/conf.d/default.conf` - Proxy for /api and /socket.io
|
|
||||||
- `backend/.env.production` - **UPDATED: Security env variables - Phase 3**
|
|
||||||
- `backend/.env.development` - **UPDATED: Security env variables - Phase 3**
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Database Schema (Implemented - Prisma)
|
## Quick Commands
|
||||||
|
|
||||||
11 tables with relations:
|
```bash
|
||||||
- `users` - **EXTENDED in Phase 1.5 & Phase 3:**
|
# Start development
|
||||||
- Base: id, username, email, password_hash, avatar, created_at, updated_at
|
docker compose up --build
|
||||||
- **WSDC:** first_name, last_name, wsdc_id
|
|
||||||
- **Email Verification:** email_verified, verification_token, verification_code, verification_token_expiry
|
|
||||||
- **Password Reset:** reset_token, reset_token_expiry
|
|
||||||
- **Social Media:** youtube_url, instagram_url, facebook_url, tiktok_url
|
|
||||||
- **Location:** country, city
|
|
||||||
- **Account Lockout (Phase 3):** failed_login_attempts, locked_until
|
|
||||||
- `events` - id, **slug (unique)**, name, location, start_date, end_date, description, worldsdc_id, participants_count
|
|
||||||
- `event_participants` - **NEW in Phase 1.5:** id, user_id, event_id, joined_at (many-to-many)
|
|
||||||
- `event_checkin_tokens` - **NEW in Phase 1.5:** id, event_id (unique), token (cuid, unique), created_at
|
|
||||||
- `divisions` - **NEW in Phase 1.6:** id, name, abbreviation, display_order (Newcomer, Novice, Intermediate, Advanced, All-Star, Champion)
|
|
||||||
- `competition_types` - **NEW in Phase 1.6:** id, name, abbreviation (Jack & Jill, Strictly)
|
|
||||||
- `event_user_heats` - **NEW in Phase 1.6:** id, user_id, event_id, division_id, competition_type_id, heat_number (1-9), role (Leader/Follower/NULL)
|
|
||||||
- `chat_rooms` - id, event_id, match_id, type (event/private), created_at
|
|
||||||
- `messages` - id, room_id, user_id, content, type, created_at
|
|
||||||
- `matches` - id, user1_id, user2_id, event_id, room_id, status, created_at
|
|
||||||
- `ratings` - id, match_id, rater_id, rated_id, score, comment, would_collaborate_again, created_at
|
|
||||||
|
|
||||||
**Migrations:**
|
# Run backend tests
|
||||||
- `20251112205214_init` - Initial schema
|
docker compose exec backend npm test
|
||||||
- `20251113151534_add_wsdc_and_email_verification` - Phase 1.5 (email, WSDC, social, location)
|
|
||||||
- `20251113202500_add_event_slug` - **Phase 1.5 (event security - unique slugs)**
|
|
||||||
- `20251114125544_add_event_checkin_tokens` - **Phase 1.5 (QR code check-in system)**
|
|
||||||
- `20251114142504_add_competition_heats_system` - **Phase 1.6 (competition heats for matchmaking)**
|
|
||||||
- `20251119_add_account_lockout_fields` - **Phase 3 (account lockout security)**
|
|
||||||
|
|
||||||
**Seed data:** 4 events, 6 divisions, 2 competition types, event chat rooms
|
# Access
|
||||||
|
# Frontend: http://localhost:8080
|
||||||
---
|
# API: http://localhost:8080/api
|
||||||
|
# Health: http://localhost:8080/api/health
|
||||||
## User Flow
|
```
|
||||||
|
|
||||||
1. Register/Login
|
|
||||||
2. Choose event (from worldsdc.com list)
|
|
||||||
3. Event chat - matchmaking
|
|
||||||
4. Match confirmation → private 1:1 chat
|
|
||||||
5. **Select video from gallery** (recorded outside app)
|
|
||||||
6. **WebRTC P2P transfer** (direct, no server storage) OR link sharing fallback
|
|
||||||
7. Rate partner (1-5 stars, comment)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Development Guidelines
|
## Development Guidelines
|
||||||
|
|
||||||
### Code Language
|
- **Code language:** All code, strings, comments in ENGLISH
|
||||||
- **All code, strings, UI text, comments:** ENGLISH
|
- **Communication:** POLISH with developer
|
||||||
- **Variable/function names:** ENGLISH
|
- **Git commits:** Standard format, NO AI mentions
|
||||||
- **Communication with developer:** POLISH
|
- **Port:** 8080 (not 80)
|
||||||
|
- **Tailwind:** v3.4.0 (v4 has breaking changes)
|
||||||
### Git Commits
|
|
||||||
- Standard format, NO mentions of AI/automatic generation
|
|
||||||
- ✅ Good: `feat: add WebRTC P2P video transfer`
|
|
||||||
- ❌ Bad: `feat: add video transfer (generated by AI)`
|
|
||||||
|
|
||||||
### Important Decisions
|
|
||||||
- Port 8080 (port 80 was occupied)
|
|
||||||
- Tailwind CSS v3.4.0 (v4 has breaking changes with Vite)
|
|
||||||
- Mock authentication uses localStorage
|
|
||||||
- All UI text in English
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Next Steps (Phase 2 - Core Features)
|
## Key Constants
|
||||||
|
|
||||||
**Priority:** HIGH
|
```javascript
|
||||||
**Estimated Time:** 12-15 hours
|
// frontend/src/constants/ & backend/src/constants/
|
||||||
|
MATCH_STATUS: pending | accepted | rejected | completed
|
||||||
### Step 1: Matches API (3-4h)
|
SUGGESTION_STATUS: pending | accepted | rejected | not_found
|
||||||
- `POST /api/matches` - Create match request
|
CONNECTION_STATE: disconnected | connecting | connected | failed
|
||||||
- `POST /api/matches/:id/accept` - Accept match
|
|
||||||
- `GET /api/matches` - List user's matches
|
|
||||||
- Frontend integration (match request flow)
|
|
||||||
- Tests
|
|
||||||
|
|
||||||
### Step 2: Ratings API (2-3h)
|
|
||||||
- `POST /api/ratings` - Submit rating after collaboration
|
|
||||||
- `GET /api/users/:id/ratings` - Get user's ratings
|
|
||||||
- Frontend integration (rating form)
|
|
||||||
- Tests
|
|
||||||
|
|
||||||
### Step 3: WebRTC Signaling (3-4h)
|
|
||||||
- Socket.IO events for SDP/ICE exchange
|
|
||||||
- Signaling flow (offer/answer/ice-candidate)
|
|
||||||
- Frontend WebRTC setup (RTCPeerConnection)
|
|
||||||
- Connection establishment tests
|
|
||||||
|
|
||||||
### Step 4: WebRTC File Transfer (4-5h)
|
|
||||||
- RTCDataChannel setup
|
|
||||||
- File chunking (16KB chunks)
|
|
||||||
- Progress monitoring (sender & receiver)
|
|
||||||
- Error handling & reconnection
|
|
||||||
- Complete P2P video transfer flow
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Common Commands
|
|
||||||
|
|
||||||
**Start project:**
|
|
||||||
```bash
|
|
||||||
docker compose up --build
|
|
||||||
```
|
|
||||||
|
|
||||||
**Access:**
|
|
||||||
- Frontend: http://localhost:8080
|
|
||||||
- Backend API: http://localhost:8080/api
|
|
||||||
- Socket.IO: ws://localhost:8080/socket.io
|
|
||||||
- Health check: http://localhost:8080/api/health
|
|
||||||
|
|
||||||
**Rebuild after changes:**
|
|
||||||
```bash
|
|
||||||
docker compose down
|
|
||||||
docker compose up --build
|
|
||||||
```
|
|
||||||
|
|
||||||
**Git:**
|
|
||||||
```bash
|
|
||||||
git status
|
|
||||||
git add .
|
|
||||||
git commit -m "feat: description"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Known Issues & Solutions
|
## Test Accounts (Seeded)
|
||||||
|
|
||||||
### Issue: Tailwind v4 compatibility error
|
| Username | Email | Password |
|
||||||
**Solution:** Downgraded to Tailwind v3.4.0
|
|----------|-------|----------|
|
||||||
```bash
|
| john_dancer | john@example.com | Dance123! |
|
||||||
npm install -D tailwindcss@^3.4.0
|
| sarah_swings | sarah@example.com | Swing456! |
|
||||||
```
|
| mike_blues | mike@example.com | Blues789! |
|
||||||
|
|
||||||
### Issue: Port 80 already allocated
|
|
||||||
**Solution:** Changed nginx port to 8080 in docker-compose.yml
|
|
||||||
|
|
||||||
### Issue: Prisma OpenSSL error in Alpine Linux
|
|
||||||
**Solution:** Added OpenSSL to Dockerfile
|
|
||||||
```dockerfile
|
|
||||||
RUN apk add --no-cache openssl
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## WebRTC Implementation Notes (Future)
|
## For More Details
|
||||||
|
|
||||||
**Main functionality - P2P file transfer:**
|
- `docs/TODO.md` - Security audit, future improvements
|
||||||
- RTCPeerConnection for connection establishment
|
- `docs/ARCHITECTURE.md` - Technical implementation details
|
||||||
- RTCDataChannel for binary data transfer
|
- `docs/archive/COMPLETED.md` - Full history of completed features
|
||||||
- File chunking (16KB chunks recommended)
|
|
||||||
- Progress monitoring (both sender and receiver)
|
|
||||||
- Metadata exchange (filename, size, MIME type)
|
|
||||||
- Error handling and reconnection logic
|
|
||||||
- Fallback: link sharing (Google Drive, Dropbox)
|
|
||||||
|
|
||||||
**Signaling:**
|
|
||||||
- WebSocket (Socket.IO) for SDP/ICE exchange
|
|
||||||
- Server only for signaling, NOT for file storage
|
|
||||||
|
|
||||||
**Security:**
|
|
||||||
- WebRTC native encryption (DTLS/SRTP)
|
|
||||||
- Optional: additional chat encryption (WebCrypto API)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Quick Reference - Frontend Routes
|
**Last Updated:** 2025-11-23
|
||||||
|
|
||||||
- `/` - Landing page with hero section, features showcase, CTAs
|
|
||||||
- `/login` - Login page
|
|
||||||
- `/register` - Two-step registration (WSDC lookup + form)
|
|
||||||
- `/verify-email` - Email verification (link + PIN code)
|
|
||||||
- `/forgot-password` - Request password reset
|
|
||||||
- `/reset-password/:token` - Reset password with token
|
|
||||||
- `/profile` - Edit user profile (social media, location)
|
|
||||||
- `/:username` - Public profile view
|
|
||||||
- `/events` - Event list (joined events first, check-in requirement notice)
|
|
||||||
- `/events/:slug/chat` - Event chat (requires check-in, real-time Socket.IO)
|
|
||||||
- `/events/:slug/details` - **NEW:** Event details with QR code, participant list
|
|
||||||
- `/events/checkin/:token` - **NEW:** QR code check-in confirmation page
|
|
||||||
- `/matches/:id/chat` - Private 1:1 chat + WebRTC mockup
|
|
||||||
- `/matches/:id/rate` - Rate partner
|
|
||||||
- `/history` - Match history
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Test Accounts
|
|
||||||
|
|
||||||
**Test users for manual testing (seeded in database):**
|
|
||||||
|
|
||||||
1. **john_dancer**
|
|
||||||
- Email: `john@example.com`
|
|
||||||
- Password: `Dance123!`
|
|
||||||
- Profile: John Smith (WSDC #12345), Los Angeles, USA
|
|
||||||
- Social: Instagram, YouTube
|
|
||||||
- Events: Warsaw Dance Festival (checked in), Swing Camp Barcelona (checked in)
|
|
||||||
- Heats in Warsaw: J&J NOV 1 L, STR INT 2 L
|
|
||||||
|
|
||||||
2. **sarah_swings**
|
|
||||||
- Email: `sarah@example.com`
|
|
||||||
- Password: `Swing456!`
|
|
||||||
- Profile: Sarah Johnson (WSDC #23456), London, UK
|
|
||||||
- Social: TikTok, Facebook
|
|
||||||
- Events: Warsaw Dance Festival (checked in)
|
|
||||||
- Heats in Warsaw: J&J NOV 1 F, J&J ADV 3
|
|
||||||
|
|
||||||
3. **mike_blues**
|
|
||||||
- Email: `mike@example.com`
|
|
||||||
- Password: `Blues789!`
|
|
||||||
- Profile: Mike Williams (WSDC #34567), Stockholm, Sweden
|
|
||||||
- Social: Instagram, YouTube, TikTok, Facebook
|
|
||||||
- Events: Warsaw Dance Festival (checked in)
|
|
||||||
- Heats in Warsaw: J&J INT 5 L, STR ADV 1 F
|
|
||||||
|
|
||||||
**Note:** All test users are verified and checked in to Warsaw Dance Festival 2025 event. They have pre-configured heats to test the matchmaking system.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Quick Reference - Events
|
|
||||||
|
|
||||||
**Seeded Events (slugs are auto-generated cuid for security):**
|
|
||||||
- Warsaw Dance Festival 2025 (slug: auto-generated, e.g. `cmhz3lcgb00018vbn34v4phoi`)
|
|
||||||
- Swing Camp Barcelona 2025 (slug: auto-generated)
|
|
||||||
- Blues Week Herräng 2025 (slug: auto-generated)
|
|
||||||
- Krakow Swing Connection 2025 (slug: auto-generated)
|
|
||||||
|
|
||||||
**Note:** Event slugs are randomly generated cuid strings to prevent ID enumeration attacks. To find the actual slug, log in and check the Events page URL.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Files to Read for Full Context
|
|
||||||
|
|
||||||
**Minimal (for quick start):**
|
|
||||||
- `docs/SESSION_CONTEXT.md` (this file)
|
|
||||||
- `docker-compose.yml`
|
|
||||||
- `frontend/src/pages/MatchChatPage.jsx` (WebRTC mockup)
|
|
||||||
|
|
||||||
**Full context:**
|
|
||||||
- `docs/CONTEXT.md` (project description)
|
|
||||||
- `docs/TODO.md` (task list)
|
|
||||||
- `docs/ARCHITECTURE.md` (technical details)
|
|
||||||
|
|
||||||
**Archives:**
|
|
||||||
- `docs/archive/COMPLETED.md` (completed tasks archive)
|
|
||||||
- `docs/archive/RESOURCES.md` (learning resources)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Last Updated:** 2025-11-19
|
|
||||||
**Phase 1 Status:** ✅ COMPLETED - Backend Foundation (Express + PostgreSQL + JWT + Socket.IO)
|
|
||||||
**Phase 1.5 Status:** ✅ COMPLETED - Email Verification & WSDC Integration & User Profiles & Security
|
|
||||||
- AWS SES email verification (link + PIN)
|
|
||||||
- Password reset workflow
|
|
||||||
- WSDC API integration
|
|
||||||
- User profiles (social media, location)
|
|
||||||
- Public profiles (/{username})
|
|
||||||
- Event participation tracking
|
|
||||||
- Event security (unique slugs, no ID enumeration)
|
|
||||||
- **QR code event check-in system** (physical presence required, dev mode bypass)
|
|
||||||
**Phase 1.6 Status:** ✅ COMPLETED - Competition Heats System
|
|
||||||
- ✅ Backend: 3 new tables (divisions, competition_types, event_user_heats)
|
|
||||||
- ✅ API endpoints (GET /divisions, GET /competition-types, heats CRUD)
|
|
||||||
- ✅ Socket.IO heats_updated broadcast for real-time updates
|
|
||||||
- ✅ Frontend: HeatsBanner component for declaration
|
|
||||||
- ✅ EventChatPage integration: heat badges, filtering, Edit button
|
|
||||||
- ✅ Matchmaking disabled for users without declared heats
|
|
||||||
**Phase 2 Status:** ✅ COMPLETED - Matches & Ratings API
|
|
||||||
- ✅ Matches API (create/accept/list matches with slugs)
|
|
||||||
- ✅ Ratings API (rate partners, 1-5 stars, comments)
|
|
||||||
- ✅ Real-time notifications via Socket.IO
|
|
||||||
**Phase 2.5 Status:** ✅ COMPLETED - WebRTC P2P File Transfer
|
|
||||||
- ✅ WebRTC signaling (SDP/ICE exchange via Socket.IO)
|
|
||||||
- ✅ P2P file transfer (RTCDataChannel, 16KB chunking, 700MB tested)
|
|
||||||
- ✅ STUN servers for NAT traversal
|
|
||||||
- ✅ WebRTC detection & fallback UX
|
|
||||||
- ✅ E2E encryption (DTLS)
|
|
||||||
**Phase 3 Status:** ✅ COMPLETED - MVP Finalization
|
|
||||||
- ✅ Landing page with hero section
|
|
||||||
- ✅ WebRTC test suite (7 backend tests passing)
|
|
||||||
- ✅ Security hardening (CSRF, Account Lockout, env variables, comprehensive tests)
|
|
||||||
- ✅ PWA features (manifest, service worker, icons, iOS support, install prompts)
|
|
||||||
- ✅ Test isolation & fixes (223/223 tests passing, 71% coverage)
|
|
||||||
- ✅ Production operations (backup scripts, health checks, monitoring guide)
|
|
||||||
- ✅ Production Docker configs (Dockerfile.prod, docker-compose profiles)
|
|
||||||
**Next Goal:** Infrastructure setup for production deployment
|
|
||||||
|
|||||||
963
docs/TODO.md
963
docs/TODO.md
@@ -1,917 +1,118 @@
|
|||||||
# TODO - spotlight.cam
|
# TODO - spotlight.cam
|
||||||
|
|
||||||
**Active tasks and roadmap - optimized for quick reference**
|
**Active tasks and roadmap**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 CURRENT STATUS
|
## Current Status
|
||||||
|
|
||||||
**Phase:** 3 (MVP Finalization) - ✅ COMPLETED
|
**Phase:** MVP Complete - Ready for Production Deployment
|
||||||
**Previous Phases:**
|
**Tests:** 286/286 passing (73% coverage)
|
||||||
- Phase 2.5 (WebRTC Implementation) - ✅ COMPLETED
|
**Status:** Awaiting infrastructure setup
|
||||||
- Phase 2 (Matches & Ratings API) - ✅ COMPLETED
|
|
||||||
- Phase 1.6 (Competition Heats System) - ✅ COMPLETED
|
|
||||||
**Progress:** 100% MVP complete
|
|
||||||
**Status:** Ready for production deployment
|
|
||||||
|
|
||||||
### 🔧 CURRENT STATUS - Backend Tests (2025-11-23) - ✅ ALL PASSING!
|
### Recently Completed (2025-11-23)
|
||||||
|
- Recording Matching System (auto-assign recorders for heats)
|
||||||
|
- Competitor Number (Bib) Support
|
||||||
|
- Frontend Refactoring (component extraction, status constants)
|
||||||
|
- Dashboard with real-time updates (online count, unread messages)
|
||||||
|
|
||||||
**Test Status:** 286/286 passing (100%) - ✅ ALL TESTS FIXED!
|
**Full history:** See `docs/archive/COMPLETED.md`
|
||||||
- **Initial state:** 145/223 (65%) - 2025-11-20
|
|
||||||
- **After cleanup fixes:** 189/223 (84.8%)
|
|
||||||
- **After test isolation:** 223/223 (100%)
|
|
||||||
- **After new features:** 286/286 (100%) - 2025-11-23
|
|
||||||
- **Total improvement:** +141 tests (+63 new tests)
|
|
||||||
|
|
||||||
**Code Coverage:** 73.32% (up from ~45%)
|
|
||||||
|
|
||||||
**✅ All fixes completed:**
|
|
||||||
1. **Test cleanup** - replaced `deleteMany({})` with selective deletion:
|
|
||||||
- `backend/src/__tests__/events.test.js` - selective deletion by username/email/slug
|
|
||||||
- `backend/src/__tests__/matches.test.js` - selective deletion by username/email/slug
|
|
||||||
- `backend/src/__tests__/csrf.test.js` - selective deletion by username/email
|
|
||||||
2. **Cleanup resilience** - replaced `delete()` with `deleteMany()`:
|
|
||||||
- `backend/src/__tests__/socket.test.js` - all afterAll + inline cleanup
|
|
||||||
- `backend/src/__tests__/matches.test.js` - inline cleanup (2 locations)
|
|
||||||
- `backend/src/__tests__/socket-webrtc.test.js` - inline cleanup
|
|
||||||
3. **Socket tests fixes:**
|
|
||||||
- Changed `eventId` → `slug` in socket event handlers
|
|
||||||
- Added `EventParticipant` creation before join_event_room
|
|
||||||
- Added safety checks before creating FK relationships
|
|
||||||
4. **Auth tests fixes:**
|
|
||||||
- `app.test.js` - CORS origin localhost:8080
|
|
||||||
- `security.js` - added localhost:3000 to allowed origins (dev)
|
|
||||||
- `auth-phase1.5.test.js` - fixed error message expectations
|
|
||||||
5. **Test isolation** - unique test data per suite to prevent race conditions:
|
|
||||||
- `users.test.js` - prefixed usernames with `users_` (users_john_dancer, users_sarah_swings)
|
|
||||||
- `matches.test.js` - prefixed with `matches_` (matches_john_dancer, etc.) + unique event slug
|
|
||||||
- `events.test.js` - prefixed with `events_` (events_john_dancer, etc.) + unique slugs + unique worldsdc_id
|
|
||||||
|
|
||||||
**Commits made:**
|
|
||||||
- `test: fix socket.test.js cleanup and event room parameters`
|
|
||||||
- `test: improve test cleanup - selective deletion instead of wiping tables`
|
|
||||||
- `test: fix test isolation by using unique test data per suite`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔐 SECURITY AUDIT FINDINGS (2025-11-20)
|
## Security Audit Findings
|
||||||
|
|
||||||
**Audit Status:** Comprehensive security audit completed by nodejs-security-auditor
|
### Critical Issues (Must Fix Before Production)
|
||||||
**Overall Security Grade:** B+ (pending critical fixes)
|
|
||||||
**Production Readiness:** ❌ NOT READY - 3 critical blockers must be resolved
|
|
||||||
**Ready for Production:** 95% (after fixing critical issues)
|
|
||||||
|
|
||||||
### 🚨 CRITICAL ISSUES (BLOCKERS - Must Fix Immediately)
|
| Issue | Severity | File | Action |
|
||||||
|
|-------|----------|------|--------|
|
||||||
|
| AWS Credentials in Git | 10/10 | `.env.production` | Rotate & remove from history |
|
||||||
|
| Weak JWT Secret | 9/10 | `.env.production` | Generate 64+ byte secret |
|
||||||
|
| Default DB Password | 8/10 | `docker-compose.yml` | Remove default fallback |
|
||||||
|
|
||||||
**Status:** ❌ All must be resolved before production deployment
|
### High Priority Issues
|
||||||
|
|
||||||
1. **❌ HARDCODED AWS CREDENTIALS IN REPOSITORY**
|
| Issue | Severity | Action |
|
||||||
- **Severity:** CRITICAL (10/10)
|
|-------|----------|--------|
|
||||||
- **CWE:** CWE-798 (Use of Hard-coded Credentials)
|
| Missing HTTPS/TLS | 8/10 | Configure SSL certificate |
|
||||||
- **File:** `backend/.env.production` (lines with AWS keys)
|
| Missing nginx security headers | 6/10 | Add X-Frame-Options, CSP, etc. |
|
||||||
- **Issue:** Live AWS credentials committed to Git repository
|
| Dependency vulnerabilities | HIGH | Run `npm audit fix` |
|
||||||
- **Impact:**
|
| Excessive body size (500M) | 4/10 | Reduce to 10M |
|
||||||
- Unauthorized AWS account access
|
|
||||||
- Financial damage from resource abuse
|
|
||||||
- Email spam/phishing using your domain
|
|
||||||
- Potential data breach
|
|
||||||
- **Required Actions:**
|
|
||||||
```bash
|
|
||||||
# 1. ROTATE CREDENTIALS IMMEDIATELY in AWS Console
|
|
||||||
# 2. Remove from Git history:
|
|
||||||
git rm --cached backend/.env.production backend/.env.development
|
|
||||||
git filter-repo --path backend/.env.production --invert-paths
|
|
||||||
# 3. Use environment variables or Docker Secrets instead
|
|
||||||
# 4. Never commit .env.production files again
|
|
||||||
```
|
|
||||||
- **Location:** Backend deployment configuration
|
|
||||||
- **Priority:** IMMEDIATE - These credentials are compromised
|
|
||||||
|
|
||||||
2. **❌ WEAK PRODUCTION JWT SECRET**
|
### Positive Security Findings
|
||||||
- **Severity:** CRITICAL (9/10)
|
- Strong authentication (JWT, bcrypt, email verification)
|
||||||
- **CWE:** CWE-521 (Weak Password Requirements)
|
- Input validation (express-validator)
|
||||||
- **File:** `backend/.env.production` (JWT_SECRET line)
|
- Security headers (Helmet.js)
|
||||||
- **Issue:** `JWT_SECRET=production-secret-key-CHANGE-THIS-IN-REAL-PRODUCTION`
|
- Rate limiting implemented
|
||||||
- **Impact:**
|
- CORS configured
|
||||||
- Attackers can forge valid JWT tokens
|
- SQL injection prevention (Prisma)
|
||||||
- Complete authentication bypass
|
- Account lockout implemented
|
||||||
- Account takeover for any user
|
- WebRTC P2P (videos don't touch server)
|
||||||
- **Required Fix:**
|
|
||||||
```bash
|
|
||||||
# Generate cryptographically secure secret (minimum 256 bits)
|
|
||||||
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
|
|
||||||
# Use output as JWT_SECRET in production environment (not in Git!)
|
|
||||||
```
|
|
||||||
- **Location:** `backend/src/utils/auth.js:7` (implementation is correct, secret is weak)
|
|
||||||
- **Priority:** IMMEDIATE - Complete auth bypass possible
|
|
||||||
|
|
||||||
3. **❌ DEFAULT DATABASE PASSWORD IN PRODUCTION**
|
|
||||||
- **Severity:** CRITICAL (8/10)
|
|
||||||
- **CWE:** CWE-798 (Use of Hard-coded Credentials)
|
|
||||||
- **File:** `docker-compose.yml:196` (db-prod service)
|
|
||||||
- **Issue:** `POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-spotlightcam123}`
|
|
||||||
- **Impact:**
|
|
||||||
- Database compromise if default is used
|
|
||||||
- Access to all user data (emails, password hashes, messages)
|
|
||||||
- **Required Fix:**
|
|
||||||
```yaml
|
|
||||||
# Remove default fallback, force explicit password:
|
|
||||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}
|
|
||||||
```
|
|
||||||
- **Location:** Docker Compose production database service
|
|
||||||
- **Priority:** IMMEDIATE - Database security
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 🔴 HIGH PRIORITY ISSUES (Fix Before Production)
|
## Pre-Deployment Checklist
|
||||||
|
|
||||||
**Status:** ⏳ Should be resolved before public launch
|
- [ ] Rotate AWS credentials, remove from Git history
|
||||||
|
- [ ] Generate strong JWT_SECRET (64+ bytes)
|
||||||
4. **⏳ MISSING HTTPS/TLS CONFIGURATION**
|
- [ ] Set strong PostgreSQL password
|
||||||
- **Severity:** HIGH (8/10)
|
- [ ] Configure HTTPS/TLS
|
||||||
- **Files:** `nginx/conf.d.prod/default.conf`, `docker-compose.yml`
|
- [ ] Add nginx security headers
|
||||||
- **Issue:** Production nginx only listens on HTTP (port 80), no HTTPS/TLS
|
- [ ] Run npm audit fix
|
||||||
- **Impact:**
|
- [ ] Reduce nginx body size limit
|
||||||
- All traffic in plaintext (credentials, tokens, videos)
|
|
||||||
- JWT tokens exposed to network sniffing
|
|
||||||
- Session cookies vulnerable to interception
|
|
||||||
- No MITM protection
|
|
||||||
- **Required Actions:**
|
|
||||||
```bash
|
|
||||||
# 1. Obtain SSL certificate (Let's Encrypt recommended)
|
|
||||||
certbot certonly --webroot -w /var/www/html -d spotlight.cam
|
|
||||||
|
|
||||||
# 2. Update nginx config for HTTPS (see audit report for full config)
|
|
||||||
# 3. Update CORS_ORIGIN to https://spotlight.cam
|
|
||||||
# 4. Update Socket.IO to force secure transports
|
|
||||||
```
|
|
||||||
- **Priority:** Required for production deployment
|
|
||||||
|
|
||||||
5. **⏳ MISSING SECURITY HEADERS IN NGINX**
|
|
||||||
- **Severity:** HIGH (6/10)
|
|
||||||
- **File:** `nginx/conf.d.prod/default.conf`
|
|
||||||
- **Issue:** Production nginx missing critical security headers
|
|
||||||
- **Impact:** XSS, clickjacking, MIME sniffing vulnerabilities
|
|
||||||
- **Required Fix:**
|
|
||||||
```nginx
|
|
||||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
||||||
add_header X-Content-Type-Options "nosniff" always;
|
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
|
||||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
||||||
add_header Content-Security-Policy "default-src 'self'; ..." always;
|
|
||||||
# HSTS after HTTPS is working:
|
|
||||||
# add_header Strict-Transport-Security "max-age=31536000" always;
|
|
||||||
```
|
|
||||||
- **Priority:** Must fix before launch
|
|
||||||
|
|
||||||
6. **⏳ DEPENDENCY VULNERABILITIES**
|
|
||||||
- **Severity:** HIGH (frontend), MODERATE (backend)
|
|
||||||
- **Tool:** npm audit
|
|
||||||
- **Issues:**
|
|
||||||
- Backend: `js-yaml` (moderate - prototype pollution)
|
|
||||||
- Backend: `cookie` via `csurf` (low - out of bounds chars)
|
|
||||||
- Frontend: `glob` (high - command injection CVE, CLI only)
|
|
||||||
- **Required Actions:**
|
|
||||||
```bash
|
|
||||||
cd backend && npm audit fix
|
|
||||||
cd frontend && npm audit fix
|
|
||||||
# Monitor csurf package (maintenance mode) - consider migration
|
|
||||||
```
|
|
||||||
- **Priority:** Run before launch
|
|
||||||
|
|
||||||
7. **⏳ EXCESSIVE REQUEST SIZE LIMIT**
|
|
||||||
- **Severity:** HIGH (DoS potential)
|
|
||||||
- **File:** `nginx/conf.d.prod/default.conf:13`
|
|
||||||
- **Issue:** `client_max_body_size 500M;` - Way too large for API
|
|
||||||
- **Analysis:** WebRTC is P2P (videos don't go through server), API only needs small payloads
|
|
||||||
- **Required Fix:**
|
|
||||||
```nginx
|
|
||||||
client_max_body_size 10M; # Reduced from 500M
|
|
||||||
location /api { client_max_body_size 1M; }
|
|
||||||
location /socket.io { client_max_body_size 64k; }
|
|
||||||
```
|
|
||||||
- **Priority:** Prevent DoS attacks
|
|
||||||
|
|
||||||
8. **⏳ SOCKET.IO CORS CONFIGURATION**
|
|
||||||
- **Severity:** MEDIUM (6/10)
|
|
||||||
- **File:** `backend/src/socket/index.js:21`
|
|
||||||
- **Issue:** CORS_ORIGIN is comma-separated string, Socket.IO expects array
|
|
||||||
- **Required Fix:**
|
|
||||||
```javascript
|
|
||||||
const allowedOrigins = process.env.CORS_ORIGIN
|
|
||||||
? process.env.CORS_ORIGIN.split(',').map(o => o.trim())
|
|
||||||
: ['http://localhost:8080'];
|
|
||||||
io = new Server(httpServer, { cors: { origin: allowedOrigins } });
|
|
||||||
```
|
|
||||||
- **Priority:** Important for multi-origin deployments
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 🟡 MEDIUM PRIORITY RECOMMENDATIONS (Next Sprint)
|
## Future Improvements (Optional)
|
||||||
|
|
||||||
**Status:** 🔄 Implement in security hardening sprint
|
### UX Enhancements
|
||||||
|
- Activity Feed (timeline of user activities)
|
||||||
9. **🔄 BCRYPT COST FACTOR TOO LOW**
|
- Smart sort order (unread first, pending ratings)
|
||||||
- **Severity:** MEDIUM (3/10)
|
- User statistics (total matches, average rating)
|
||||||
- **File:** `backend/src/utils/auth.js:7`
|
- Sidebar filters (by nationality, division)
|
||||||
- **Issue:** `bcrypt.genSalt(10)` - Cost 10 was standard in 2010, OWASP recommends 12+
|
|
||||||
- **Recommendation:**
|
### Security Hardening
|
||||||
```javascript
|
- Increase bcrypt rounds (10 → 12)
|
||||||
const BCRYPT_ROUNDS = parseInt(process.env.BCRYPT_ROUNDS) || 12;
|
- Implement refresh token pattern
|
||||||
const salt = await bcrypt.genSalt(BCRYPT_ROUNDS);
|
- Add Socket.IO rate limiting
|
||||||
```
|
- Sanitize chat messages
|
||||||
- **Trade-off:** 4x slower hashing (400ms vs 100ms), negligible UX impact
|
|
||||||
- **Priority:** Next security update
|
|
||||||
|
|
||||||
10. **🔄 ACCOUNT LOCKOUT USER ENUMERATION**
|
|
||||||
- **Severity:** MEDIUM (2/10)
|
|
||||||
- **File:** `backend/src/controllers/auth.js:108-134`
|
|
||||||
- **Issue:** Different responses reveal if account exists (401 vs 423)
|
|
||||||
- **Recommendation:** Use same error message for locked/non-existent accounts
|
|
||||||
- **Priority:** Optional - low practical risk
|
|
||||||
|
|
||||||
11. **🔄 WEAK SESSION TIMEOUT**
|
|
||||||
- **Severity:** MEDIUM (4/10)
|
|
||||||
- **File:** `backend/src/utils/auth.js`
|
|
||||||
- **Issue:** 24-hour JWT tokens cannot be revoked, too long for stolen tokens
|
|
||||||
- **Recommendation:** Implement refresh token pattern (15min access + 7day refresh)
|
|
||||||
- **Priority:** Before scaling, acceptable for MVP
|
|
||||||
|
|
||||||
12. **🔄 NO RATE LIMITING ON SOCKET.IO EVENTS**
|
|
||||||
- **Severity:** MEDIUM (4/10)
|
|
||||||
- **File:** `backend/src/socket/index.js`
|
|
||||||
- **Issue:** Socket.IO events (messages, signaling) have no rate limiting
|
|
||||||
- **Recommendation:** Implement per-socket rate limiter (30 messages/minute)
|
|
||||||
- **Priority:** Before public launch to prevent spam
|
|
||||||
|
|
||||||
13. **🔄 MISSING INPUT SANITIZATION ON CHAT MESSAGES**
|
|
||||||
- **Severity:** MEDIUM (4/10)
|
|
||||||
- **File:** `backend/src/socket/index.js:212-268`
|
|
||||||
- **Issue:** Chat message content not sanitized before database save
|
|
||||||
- **Recommendation:**
|
|
||||||
```javascript
|
|
||||||
const sanitizedContent = sanitizeHtml(content).slice(0, 2000);
|
|
||||||
```
|
|
||||||
- **Note:** DOMPurify utility exists in `utils/sanitize.js` but not used for chat
|
|
||||||
- **Priority:** Before launch (XSS prevention)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🟢 LOW PRIORITY IMPROVEMENTS (Future Hardening)
|
|
||||||
|
|
||||||
**Status:** 📝 Optional enhancements
|
|
||||||
|
|
||||||
14. **📝 PostgreSQL Connection Security**
|
|
||||||
- **Issue:** Dev database exposes port 5432 to host
|
|
||||||
- **Recommendation:** Restrict to localhost or use pgAdmin in Docker
|
|
||||||
- **Status:** Acceptable for development
|
|
||||||
|
|
||||||
15. **📝 Docker Container Running as Root**
|
|
||||||
- **File:** `backend/Dockerfile.prod`
|
|
||||||
- **Issue:** Container doesn't specify non-root user
|
|
||||||
- **Recommendation:** Add `USER nodejs` directive
|
|
||||||
- **Priority:** Best practice, limited impact in containers
|
|
||||||
|
|
||||||
16. **📝 Missing Security Logging**
|
|
||||||
- **Issue:** Security events not systematically logged (login failures, lockouts, token failures)
|
|
||||||
- **Recommendation:** Implement structured security logging
|
|
||||||
- **Priority:** Useful for monitoring, not blocking
|
|
||||||
|
|
||||||
17. **📝 Token Verification Timing Attack**
|
|
||||||
- **Severity:** LOW (2/10)
|
|
||||||
- **File:** `backend/src/controllers/auth.js:305-309`
|
|
||||||
- **Issue:** 6-digit verification code comparison not timing-safe
|
|
||||||
- **Note:** `timingSafeEqual` utility exists, just not used here
|
|
||||||
- **Priority:** Optional - codes expire in 24h with rate limiting
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### ✅ POSITIVE SECURITY FINDINGS
|
|
||||||
|
|
||||||
**Excellent practices already implemented:**
|
|
||||||
|
|
||||||
1. ✅ **Strong Authentication:** JWT, bcrypt, email verification, password reset
|
|
||||||
2. ✅ **Comprehensive Input Validation:** express-validator throughout
|
|
||||||
3. ✅ **Security Headers:** Helmet.js with CSP, XSS protection, HSTS, noSniff
|
|
||||||
4. ✅ **Rate Limiting:** Multiple limiters (API, auth, email)
|
|
||||||
5. ✅ **CORS Configuration:** Proper origin validation
|
|
||||||
6. ✅ **Authorization:** Socket.IO auth middleware, WebRTC signaling authorization
|
|
||||||
7. ✅ **Database Security:** Prisma ORM prevents SQL injection
|
|
||||||
8. ✅ **Error Handling:** Generic messages in production, no stack traces
|
|
||||||
9. ✅ **Account Lockout:** Implemented after failed attempts
|
|
||||||
10. ✅ **Defense in Depth:** Multiple security layers
|
|
||||||
11. ✅ **WebRTC P2P:** Videos don't touch server (privacy + security)
|
|
||||||
12. ✅ **Test Coverage:** 286/286 tests passing (73% coverage)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 📋 SECURITY DEPLOYMENT CHECKLIST
|
|
||||||
|
|
||||||
**Pre-Deployment (MUST COMPLETE):**
|
|
||||||
- [ ] **CRITICAL:** Rotate AWS credentials and remove from Git history
|
|
||||||
- [ ] **CRITICAL:** Generate strong JWT_SECRET (64+ bytes)
|
|
||||||
- [ ] **CRITICAL:** Set strong PostgreSQL password (no fallback)
|
|
||||||
- [ ] **CRITICAL:** Remove .env files from Git tracking
|
|
||||||
- [ ] **HIGH:** Configure HTTPS/TLS with valid certificate
|
|
||||||
- [ ] **HIGH:** Add nginx security headers
|
|
||||||
- [ ] **HIGH:** Fix npm audit vulnerabilities
|
|
||||||
- [ ] **HIGH:** Reduce nginx body size limit (500M → 10M)
|
|
||||||
- [ ] **MEDIUM:** Update Socket.IO CORS to handle array
|
|
||||||
- [ ] **MEDIUM:** Implement Socket.IO rate limiting
|
|
||||||
|
|
||||||
**Post-Deployment (First 30 Days):**
|
|
||||||
- [ ] Monitor security logs for unusual patterns
|
|
||||||
- [ ] Test account lockout mechanism
|
|
||||||
- [ ] Verify HTTPS enforcement
|
|
||||||
- [ ] Test CSRF protection
|
|
||||||
- [ ] Review and rotate credentials on schedule
|
|
||||||
|
|
||||||
**Ongoing Maintenance:**
|
|
||||||
- [ ] Monthly: npm audit and dependency updates
|
|
||||||
- [ ] Quarterly: Rotate JWT_SECRET (requires re-auth)
|
|
||||||
- [ ] Yearly: Security penetration testing
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 📊 RISK ASSESSMENT SUMMARY
|
|
||||||
|
|
||||||
| Vulnerability | Likelihood | Impact | Risk Score | Status |
|
|
||||||
|---------------|------------|--------|------------|--------|
|
|
||||||
| AWS Credentials Exposed | VERY HIGH | CRITICAL | **10/10** | ❌ MUST FIX |
|
|
||||||
| Weak JWT Secret | HIGH | CRITICAL | **9/10** | ❌ MUST FIX |
|
|
||||||
| Default DB Password | MEDIUM | CRITICAL | **8/10** | ❌ MUST FIX |
|
|
||||||
| Missing HTTPS | HIGH | HIGH | **8/10** | ⏳ MUST FIX |
|
|
||||||
| Missing nginx Headers | MEDIUM | HIGH | **6/10** | ⏳ Should Fix |
|
|
||||||
| Excessive Body Size | LOW | MEDIUM | **4/10** | ⏳ Should Fix |
|
|
||||||
|
|
||||||
**Overall Assessment:** Application is **95% production-ready** from security perspective. The remaining 5% are critical blockers requiring 1-2 days to fix.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🔗 FULL AUDIT REPORT
|
|
||||||
|
|
||||||
For complete details including:
|
|
||||||
- Specific code examples for each fix
|
|
||||||
- Configuration templates
|
|
||||||
- OWASP Top 10 coverage analysis
|
|
||||||
- Compliance notes (GDPR)
|
|
||||||
- Detailed architecture recommendations
|
|
||||||
|
|
||||||
See the complete security audit report generated by nodejs-security-auditor agent (available in conversation history).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 📋 FUTURE UX/UI IMPROVEMENTS
|
|
||||||
|
|
||||||
**Dashboard Page - ✅ CORE COMPLETED (2025-11-21):**
|
|
||||||
- [x] ✅ `/dashboard` route as default landing page after login
|
|
||||||
- [x] ✅ Active events with quick access to chats
|
|
||||||
- [x] ✅ Active matches with video/rating status
|
|
||||||
- [x] ✅ Match requests (incoming/outgoing)
|
|
||||||
- [x] ✅ Online count per event (real-time)
|
|
||||||
- [x] ✅ Unread count per match
|
|
||||||
- [x] ✅ Toast notifications for match events
|
|
||||||
- [x] ✅ Loading skeletons
|
|
||||||
- [x] ✅ Rate Partner button
|
|
||||||
- [ ] ⏳ Activity Feed (timeline of all user activities) - Optional Phase 4
|
|
||||||
- [ ] ⏳ User statistics (total matches, average rating, events attended) - Optional Phase 4
|
|
||||||
- [ ] ⏳ Smart sort order (unread first, pending ratings, recent) - Optional Phase 4
|
|
||||||
|
|
||||||
**Event Chat Sidebar Enhancements:**
|
|
||||||
- [ ] Add competitor number display for each user in sidebar
|
|
||||||
- [ ] Show user nationality (flag + country code)
|
|
||||||
- [ ] Expand user info cards in sidebar:
|
|
||||||
- Competition heats (already implemented)
|
|
||||||
- Competitor number
|
|
||||||
- Country/nationality
|
|
||||||
- User role/level
|
|
||||||
- Years of experience (if available in profile)
|
|
||||||
- Average rating (if rated)
|
|
||||||
- [ ] Consider expandable user cards (click to see more details)
|
|
||||||
- [ ] Add filtering options:
|
|
||||||
- By nationality
|
|
||||||
- By division/level
|
|
||||||
- By competitor number range
|
|
||||||
- [ ] Improve mobile responsiveness for extended sidebar info
|
|
||||||
|
|
||||||
### ✅ Completed
|
|
||||||
- Phase 0: Frontend mockup with all views
|
|
||||||
- Phase 1: Backend Foundation
|
|
||||||
- Node.js + Express API
|
|
||||||
- PostgreSQL database with Prisma ORM
|
|
||||||
- JWT authentication (register, login)
|
|
||||||
- Socket.IO real-time chat (event & match rooms)
|
|
||||||
- Comprehensive test coverage (81%+)
|
|
||||||
- Phase 1.5: Email & WSDC & Profiles & Security
|
|
||||||
- Email verification (AWS SES with link + PIN)
|
|
||||||
- Password reset workflow
|
|
||||||
- WSDC API integration (auto-fill registration)
|
|
||||||
- User profiles (social media links, location)
|
|
||||||
- Public profiles (/{username})
|
|
||||||
- Event participation tracking (auto-save joined events)
|
|
||||||
- Event security (unique slugs, prevent ID enumeration)
|
|
||||||
- QR code event check-in system (physical presence required at venue)
|
|
||||||
- Phase 1.6: Competition Heats System
|
|
||||||
- Database schema (divisions, competition_types, event_user_heats)
|
|
||||||
- Backend API (CRUD operations, validation)
|
|
||||||
- Frontend components (HeatsBanner, forms, badges)
|
|
||||||
- Phase 2: Matches & Ratings API
|
|
||||||
- Match requests with CUID slugs
|
|
||||||
- Real-time match notifications
|
|
||||||
- Ratings system (1-5 stars, comments, preferences)
|
|
||||||
- Public profile ratings display
|
|
||||||
- Profile links from chat/matches
|
|
||||||
- Message history persistence
|
|
||||||
- Duplicate rating prevention
|
|
||||||
- **Dashboard Implementation (2025-11-21)**
|
|
||||||
- Centralized dashboard as default landing page
|
|
||||||
- Active events with heats, participants, online count
|
|
||||||
- Active matches with video/rating status, unread count
|
|
||||||
- Match requests (incoming/outgoing) management
|
|
||||||
- Toast notifications, loading skeletons
|
|
||||||
- Socket stability improvements (heartbeat, auto-reconnect)
|
|
||||||
- **Competitor Number (Bib) Support (2025-11-22)**
|
|
||||||
- New `competitorNumber` field in EventParticipant model
|
|
||||||
- Migration: `20251121210620_add_competitor_number`
|
|
||||||
- Display competitor numbers in event UI
|
|
||||||
- Used by auto-matching system to identify dancers
|
|
||||||
- **Recording Matching System (2025-11-22)**
|
|
||||||
- Auto-matching algorithm for recording partners (`backend/src/services/matching.js`)
|
|
||||||
- RecordingSuggestion model for storing match suggestions
|
|
||||||
- Schedule config for division collision groups (divisions in same slot collide)
|
|
||||||
- Heat buffer calculation (1 heat after dancing before can record)
|
|
||||||
- Location-based preference scoring (same city > same country > anyone)
|
|
||||||
- Max recordings per person limit (3)
|
|
||||||
- Frontend RecordingTab component with suggestions UI
|
|
||||||
- API endpoints for running matching and managing suggestions
|
|
||||||
- **Frontend Refactoring (2025-11-23)**
|
|
||||||
- Extracted DashboardPage into components (DashboardHeader, EventCard, MatchCard, MatchRequestCard)
|
|
||||||
- Extracted EventDetailsPage into components
|
|
||||||
- Extracted ProfilePage into ProfileForm and PasswordChangeForm
|
|
||||||
- Extracted MatchCard component from MatchesPage
|
|
||||||
- Added status constants (MATCH_STATUS, SUGGESTION_STATUS, CONNECTION_STATE, SUGGESTION_TYPE)
|
|
||||||
- Backend constants module (`backend/src/constants/`)
|
|
||||||
|
|
||||||
**See:** `docs/archive/COMPLETED.md` for full list of completed tasks
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📌 Phase 1: Backend Foundation - ✅ COMPLETED
|
|
||||||
|
|
||||||
**Completed:** 2025-11-12
|
|
||||||
**Time Spent:** ~14 hours
|
|
||||||
|
|
||||||
### ✅ Step 1: Backend Setup (COMPLETED)
|
|
||||||
- [x] Add `backend` service to docker-compose.yml
|
|
||||||
- [x] Initialize Node.js + Express project
|
|
||||||
- [x] Create folder structure (routes, controllers, middleware, etc.)
|
|
||||||
- [x] Add healthcheck endpoint: `GET /api/health`
|
|
||||||
- [x] Update nginx config to proxy `/api/*` to backend
|
|
||||||
- [x] Unit tests (7 tests passing)
|
|
||||||
|
|
||||||
### ✅ Step 2: PostgreSQL Setup (COMPLETED)
|
|
||||||
- [x] Add `db` service (PostgreSQL 15) to docker-compose.yml
|
|
||||||
- [x] Configure volumes for data persistence
|
|
||||||
- [x] Prisma ORM implementation
|
|
||||||
- [x] Create database schema (6 tables with relations)
|
|
||||||
- [x] Add indexes for performance
|
|
||||||
- [x] Create seed data (3 events, 2 users, chat rooms)
|
|
||||||
- [x] Fix OpenSSL compatibility issue for Prisma
|
|
||||||
|
|
||||||
### ✅ Step 3: Authentication API (COMPLETED)
|
|
||||||
- [x] Install dependencies: bcrypt, jsonwebtoken, express-validator
|
|
||||||
- [x] Implement password hashing with bcrypt (10 salt rounds)
|
|
||||||
- [x] Implement JWT token generation and verification
|
|
||||||
- [x] Create endpoints: register, login, /users/me
|
|
||||||
- [x] Create auth middleware for protected routes
|
|
||||||
- [x] Update frontend AuthContext to use real API
|
|
||||||
- [x] Unit tests (30 tests, 78%+ coverage)
|
|
||||||
|
|
||||||
### ✅ Step 4: WebSocket Chat (COMPLETED)
|
|
||||||
- [x] Install Socket.IO 4.8.1 on backend
|
|
||||||
- [x] Setup Socket.IO server with Express integration
|
|
||||||
- [x] JWT authentication for socket connections
|
|
||||||
- [x] Event rooms (join/leave/messages/active users)
|
|
||||||
- [x] Match rooms (private 1:1 chat)
|
|
||||||
- [x] Install socket.io-client on frontend
|
|
||||||
- [x] Update EventChatPage with real-time messaging
|
|
||||||
- [x] Update MatchChatPage with real-time chat
|
|
||||||
- [x] Unit tests (12 tests, 89% coverage for Socket.IO module)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📌 Phase 1.6: Competition Heats System - ✅ COMPLETED
|
|
||||||
|
|
||||||
**Completed:** 2025-11-14
|
|
||||||
**Time Spent:** ~8 hours
|
|
||||||
**Status:** Fully implemented and tested
|
|
||||||
|
|
||||||
### Business Logic Summary
|
|
||||||
- Users must declare their competition heats before matchmaking
|
|
||||||
- One user can compete in multiple divisions/heats (e.g., J&J Novice + Strictly Advanced)
|
|
||||||
- **Constraint:** Cannot compete in same role in same division+competition type (e.g., cannot have "J&J Novice Leader" twice)
|
|
||||||
- Role is optional (can be NULL = undeclared)
|
|
||||||
- Heat numbers: 1-9
|
|
||||||
- Format example: "J&J NOV 1 L" (Jack & Jill, Novice, Heat 1, Leader)
|
|
||||||
|
|
||||||
### Step 1: Database Schema - ✅ COMPLETED
|
|
||||||
- [x] Create migration for 3 new tables:
|
|
||||||
- `divisions` - Pre-defined competition divisions
|
|
||||||
- Columns: id, name (varchar), abbreviation (varchar 3), display_order (int)
|
|
||||||
- Seed data: Newcomer (NEW), Novice (NOV), Intermediate (INT), Advanced (ADV), All-Star (ALL), Champion (CHA)
|
|
||||||
- `competition_types` - Pre-defined competition types
|
|
||||||
- Columns: id, name (varchar), abbreviation (varchar 3)
|
|
||||||
- Seed data: Jack & Jill (J&J), Strictly (STR)
|
|
||||||
- `event_user_heats` - User's declared heats for event
|
|
||||||
- Columns: id, user_id, event_id, division_id, competition_type_id, heat_number (1-9), role (enum: Leader/Follower/NULL), created_at, updated_at
|
|
||||||
- **UNIQUE constraint:** (user_id, event_id, division_id, competition_type_id, role)
|
|
||||||
- Foreign keys: user_id → users.id, event_id → events.id, division_id → divisions.id, competition_type_id → competition_types.id
|
|
||||||
- Indexes: (user_id, event_id), (event_id)
|
|
||||||
- [x] Update Prisma schema
|
|
||||||
- [x] Run migration
|
|
||||||
- [x] Verify seed data
|
|
||||||
|
|
||||||
### Step 2: Backend API - ✅ COMPLETED
|
|
||||||
- [x] Create routes and controllers:
|
|
||||||
- `GET /api/divisions` - List all divisions (public)
|
|
||||||
- `GET /api/competition-types` - List all competition types (public)
|
|
||||||
- `POST /api/events/:slug/heats` - Add/update user's heats (authenticated)
|
|
||||||
- Input: array of { divisionId, competitionTypeId, heatNumber, role? }
|
|
||||||
- Validation: unique constraint, heat number 1-9
|
|
||||||
- Replace all existing heats (upsert pattern)
|
|
||||||
- `GET /api/events/:slug/heats/me` - Get current user's heats (authenticated)
|
|
||||||
- `GET /api/events/:slug/heats/all` - Get all users' heats for sidebar (authenticated)
|
|
||||||
- Returns: userId, username, avatar, heats[]
|
|
||||||
- `DELETE /api/events/:slug/heats/:id` - Delete specific heat (authenticated)
|
|
||||||
- [x] Validation middleware:
|
|
||||||
- Heat number 1-9
|
|
||||||
- Role enum (Leader/Follower/NULL)
|
|
||||||
- Unique constraint enforcement
|
|
||||||
- User must be event participant
|
|
||||||
- [x] Unit tests (CRUD operations, validation, constraints)
|
|
||||||
|
|
||||||
### Step 3: Socket.IO Events - ✅ COMPLETED
|
|
||||||
- [x] Add event: `heats_updated` - Broadcast when user updates heats
|
|
||||||
- Payload: { userId, username, heats[] }
|
|
||||||
- Send to all users in event room
|
|
||||||
- [x] Update active_users event to include heats data
|
|
||||||
|
|
||||||
### Step 4: Frontend Components - ✅ COMPLETED
|
|
||||||
- [x] Create HeatsBanner component (sticky between header and chat) - ✅ DONE
|
|
||||||
- [x] Show only if user has no heats declared
|
|
||||||
- [x] Form with dynamic heat entries (add/remove)
|
|
||||||
- [x] Fields per entry: Competition Type (select), Division (select), Heat Number (1-9), Role (optional: Leader/Follower)
|
|
||||||
- [x] "Save Heats" button → POST /api/events/:slug/heats
|
|
||||||
- [x] On save success: hide banner, show success message
|
|
||||||
- [x] Basic heats display in EventChatPage (⏳ Enhanced UI features remain for Phase 4)
|
|
||||||
- [x] Create frontend API methods in services/api.js - ✅ DONE
|
|
||||||
- [x] divisionsAPI.getAll()
|
|
||||||
- [x] competitionTypesAPI.getAll()
|
|
||||||
- [x] heatsAPI.saveHeats(slug, heats[])
|
|
||||||
- [x] heatsAPI.getMyHeats(slug)
|
|
||||||
- [x] heatsAPI.getAllHeats(slug)
|
|
||||||
- [x] heatsAPI.deleteHeat(slug, heatId)
|
|
||||||
- [x] Socket.IO integration - Basic support implemented
|
|
||||||
|
|
||||||
### Step 4.1: EventChatPage Integration - ⏳ OPTIONAL ENHANCEMENTS (Phase 4)
|
|
||||||
|
|
||||||
**What needs to be done:**
|
|
||||||
|
|
||||||
1. **Add state management for heats:**
|
|
||||||
```javascript
|
|
||||||
const [myHeats, setMyHeats] = useState([]);
|
|
||||||
const [userHeats, setUserHeats] = useState(new Map()); // userId → heats[]
|
|
||||||
const [showHeatsBanner, setShowHeatsBanner] = useState(false);
|
|
||||||
const [hideMyHeats, setHideMyHeats] = useState(false);
|
|
||||||
const [showHeatsModal, setShowHeatsModal] = useState(false);
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Load heats on component mount:**
|
|
||||||
```javascript
|
|
||||||
useEffect(() => {
|
|
||||||
const loadHeats = async () => {
|
|
||||||
const [myHeatsData, allHeatsData] = await Promise.all([
|
|
||||||
heatsAPI.getMyHeats(slug),
|
|
||||||
heatsAPI.getAllHeats(slug),
|
|
||||||
]);
|
|
||||||
setMyHeats(myHeatsData);
|
|
||||||
setShowHeatsBanner(myHeatsData.length === 0);
|
|
||||||
|
|
||||||
// Map userHeats
|
|
||||||
const heatsMap = new Map();
|
|
||||||
allHeatsData.forEach(userHeat => {
|
|
||||||
heatsMap.set(userHeat.userId, userHeat.heats);
|
|
||||||
});
|
|
||||||
setUserHeats(heatsMap);
|
|
||||||
};
|
|
||||||
loadHeats();
|
|
||||||
}, [slug]);
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Add HeatsBanner before chat:**
|
|
||||||
```jsx
|
|
||||||
{showHeatsBanner && (
|
|
||||||
<HeatsBanner
|
|
||||||
slug={slug}
|
|
||||||
onSave={() => {
|
|
||||||
setShowHeatsBanner(false);
|
|
||||||
// Reload heats
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Add "Edit Heats" button in header (next to "Leave Event"):**
|
|
||||||
```jsx
|
|
||||||
<button
|
|
||||||
onClick={() => setShowHeatsModal(true)}
|
|
||||||
className="flex items-center gap-2 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50"
|
|
||||||
>
|
|
||||||
<Edit size={16} />
|
|
||||||
Edit Heats
|
|
||||||
</button>
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Create modal for editing heats (reuse HeatsBanner logic)**
|
|
||||||
|
|
||||||
6. **Add heat badges to sidebar under username:**
|
|
||||||
```jsx
|
|
||||||
{activeUsers.map(activeUser => {
|
|
||||||
const userHeatsForThisUser = userHeats.get(activeUser.userId) || [];
|
|
||||||
const hasHeats = userHeatsForThisUser.length > 0;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div key={activeUser.userId}>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<img src={activeUser.avatar} />
|
|
||||||
<span>{activeUser.username}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Heat badges */}
|
|
||||||
<div className="flex flex-wrap gap-1 mt-1">
|
|
||||||
{userHeatsForThisUser.slice(0, 3).map(heat => (
|
|
||||||
<span key={heat.id} className="text-xs px-2 py-0.5 bg-blue-100 text-blue-700 rounded">
|
|
||||||
{heat.competitionType.abbreviation} {heat.division.abbreviation} {heat.heatNumber}
|
|
||||||
{heat.role && ` ${heat.role[0]}`}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
{userHeatsForThisUser.length > 3 && (
|
|
||||||
<span className="text-xs px-2 py-0.5 bg-gray-100 text-gray-600 rounded">
|
|
||||||
+{userHeatsForThisUser.length - 3}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* UserPlus button - disabled if no heats */}
|
|
||||||
<button
|
|
||||||
onClick={() => handleMatchWith(activeUser.userId)}
|
|
||||||
disabled={!hasHeats}
|
|
||||||
className="p-1 text-primary-600 hover:bg-primary-50 rounded disabled:opacity-30 disabled:cursor-not-allowed"
|
|
||||||
>
|
|
||||||
<UserPlus className="w-4 h-4" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
```
|
|
||||||
|
|
||||||
7. **Add filter checkbox above active users:**
|
|
||||||
```jsx
|
|
||||||
<label className="flex items-center gap-2 text-sm text-gray-700 mb-2">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={hideMyHeats}
|
|
||||||
onChange={(e) => setHideMyHeats(e.target.checked)}
|
|
||||||
className="rounded border-gray-300"
|
|
||||||
/>
|
|
||||||
Hide users from my heats
|
|
||||||
</label>
|
|
||||||
```
|
|
||||||
|
|
||||||
8. **Filter logic:**
|
|
||||||
```javascript
|
|
||||||
const filteredUsers = hideMyHeats
|
|
||||||
? activeUsers.filter(activeUser => {
|
|
||||||
const theirHeats = userHeats.get(activeUser.userId) || [];
|
|
||||||
return !theirHeats.some(theirHeat =>
|
|
||||||
myHeats.some(myHeat =>
|
|
||||||
myHeat.divisionId === theirHeat.divisionId &&
|
|
||||||
myHeat.competitionTypeId === theirHeat.competitionTypeId &&
|
|
||||||
myHeat.heatNumber === theirHeat.heatNumber
|
|
||||||
)
|
|
||||||
);
|
|
||||||
})
|
|
||||||
: activeUsers;
|
|
||||||
```
|
|
||||||
|
|
||||||
9. **Socket.IO heats_updated listener:**
|
|
||||||
```javascript
|
|
||||||
useEffect(() => {
|
|
||||||
const socket = getSocket();
|
|
||||||
if (!socket) return;
|
|
||||||
|
|
||||||
socket.on('heats_updated', ({ userId, username, heats }) => {
|
|
||||||
setUserHeats(prev => {
|
|
||||||
const newMap = new Map(prev);
|
|
||||||
newMap.set(userId, heats);
|
|
||||||
return newMap;
|
|
||||||
});
|
|
||||||
|
|
||||||
// If it's current user, update myHeats
|
|
||||||
if (userId === user.id) {
|
|
||||||
setMyHeats(heats);
|
|
||||||
setShowHeatsBanner(heats.length === 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
socket.off('heats_updated');
|
|
||||||
};
|
|
||||||
}, [user.id]);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 5: Styling & UX - ✅ BASIC COMPLETE
|
|
||||||
- [x] Heat badges design
|
|
||||||
- [x] Banner responsive design (mobile + desktop)
|
|
||||||
- [x] Loading states for heat operations
|
|
||||||
- [x] Error handling & validation messages
|
|
||||||
|
|
||||||
### Step 6: Testing & Edge Cases - ✅ COMPLETED
|
|
||||||
- [x] Test unique constraint violation (frontend + backend)
|
|
||||||
- [x] Backend unit tests for heats API
|
|
||||||
- [x] Test role optional (NULL) handling
|
|
||||||
|
|
||||||
### Technical Notes
|
|
||||||
- **Abbreviations:**
|
|
||||||
- Divisions: NEW, NOV, INT, ADV, ALL, CHA
|
|
||||||
- Competition Types: J&J, STR
|
|
||||||
- Roles: L (Leader), F (Follower), empty (NULL)
|
|
||||||
- **Display format:** "{CompType} {Div} {Heat} {Role?}" → "J&J NOV 1 L"
|
|
||||||
- **Future enhancement:** When Matches API is implemented, editing heats with active match requires partner confirmation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📌 Phase 2.5: WebRTC P2P File Transfer - ✅ COMPLETED
|
|
||||||
|
|
||||||
**Completed:** 2025-11-15
|
|
||||||
**Time Spent:** ~10 hours
|
|
||||||
|
|
||||||
### Step 1: WebRTC Signaling - ✅ COMPLETED
|
|
||||||
- [x] Socket.IO signaling events (offer, answer, ICE candidates)
|
|
||||||
- [x] Frontend WebRTC setup (RTCPeerConnection)
|
|
||||||
- [x] STUN server configuration
|
|
||||||
- [x] Connection state monitoring
|
|
||||||
- [x] Unit tests (7 backend tests passing)
|
|
||||||
|
|
||||||
### Step 2: WebRTC File Transfer - ✅ COMPLETED
|
|
||||||
- [x] RTCDataChannel setup (ordered, reliable)
|
|
||||||
- [x] File metadata exchange
|
|
||||||
- [x] File chunking (16KB chunks)
|
|
||||||
- [x] Progress monitoring (sender & receiver)
|
|
||||||
- [x] Error handling & reconnection
|
|
||||||
- [x] Complete P2P video transfer flow
|
|
||||||
- [x] Tested up to 700MB files
|
|
||||||
- [x] Fallback: Link sharing UI
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Future Phases (Reference)
|
|
||||||
|
|
||||||
### Phase 3: MVP Finalization - ✅ COMPLETED
|
|
||||||
- [x] ✅ Security hardening:
|
|
||||||
- Rate limiting (express-rate-limit) ✅
|
|
||||||
- Input validation & sanitization ✅
|
|
||||||
- CORS configuration ✅
|
|
||||||
- SQL injection prevention ✅
|
|
||||||
- XSS protection ✅
|
|
||||||
- CSRF protection ✅
|
|
||||||
- Account lockout ✅
|
|
||||||
- [x] ✅ Testing:
|
|
||||||
- Integration tests (API endpoints) ✅
|
|
||||||
- WebRTC connection tests ✅
|
|
||||||
- 286/286 tests passing (100%) ✅
|
|
||||||
- 73% code coverage ✅
|
|
||||||
- [x] ✅ PWA features:
|
|
||||||
- Web app manifest ✅
|
|
||||||
- Service worker (offline support) ✅
|
|
||||||
- App icons & splash screens ✅
|
|
||||||
- Install prompt ✅
|
|
||||||
- iOS support ✅
|
|
||||||
- [x] ✅ Deployment preparation:
|
|
||||||
- Production Docker images (Dockerfile.prod) ✅
|
|
||||||
- Environment configuration (.env.production) ✅
|
|
||||||
- Database backup scripts ✅
|
|
||||||
- Health check scripts ✅
|
|
||||||
- Monitoring documentation ✅
|
|
||||||
- Docker compose profiles (dev/prod) ✅
|
|
||||||
|
|
||||||
**Note:** E2E tests (Playwright/Cypress) and CI/CD pipeline are optional enhancements for Phase 4.
|
|
||||||
|
|
||||||
### Phase 5: Optional Extensions
|
|
||||||
- [ ] User badges & trust system
|
|
||||||
- [ ] Block users
|
|
||||||
- [ ] Public profiles
|
|
||||||
- [ ] Push notifications
|
|
||||||
- [ ] Video compression
|
|
||||||
- [ ] Multi-file transfer
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Active Development Tasks
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
- [x] ✅ README.md
|
|
||||||
- [x] ✅ docs/QUICKSTART.md
|
|
||||||
- [x] ✅ docs/CONTEXT.md
|
|
||||||
- [x] ✅ docs/TODO.md
|
|
||||||
- [x] ✅ docs/SESSION_CONTEXT.md
|
|
||||||
- [x] ✅ docs/ARCHITECTURE.md
|
|
||||||
- [x] ✅ docs/DEPLOYMENT.md
|
|
||||||
- [x] ✅ docs/MONITORING.md
|
|
||||||
- [x] ✅ docs/archive/COMPLETED.md
|
|
||||||
- [x] ✅ docs/archive/RESOURCES.md
|
|
||||||
- [ ] ⏳ API documentation (Swagger/OpenAPI) - after backend
|
|
||||||
- [ ] ⏳ Architecture diagrams - after backend
|
|
||||||
- [ ] ⏳ WebRTC flow diagram - after WebRTC implementation
|
|
||||||
|
|
||||||
### Infrastructure
|
### Infrastructure
|
||||||
- [x] ✅ Docker Compose (nginx, frontend, backend, db)
|
- CI/CD pipeline (GitHub Actions)
|
||||||
- [x] ✅ Production Dockerfiles (Dockerfile.prod for frontend & backend)
|
- E2E tests (Playwright)
|
||||||
- [x] ✅ Docker Compose profiles (dev/prod)
|
- Security logging
|
||||||
- [x] ✅ Production environment configuration
|
|
||||||
- [x] ✅ Operations scripts (backup, restore, health-check)
|
|
||||||
- [ ] ⏳ CI/CD pipeline (GitHub Actions) - Optional
|
|
||||||
- [ ] ⏳ HTTPS setup (Let's Encrypt) - Requires server
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
- [x] ✅ Backend tests (Jest + Supertest) - 286/286 passing, 73% coverage
|
|
||||||
- [x] ✅ WebRTC tests - 7 backend tests passing
|
|
||||||
- [x] ✅ Socket.IO tests - Complete coverage
|
|
||||||
- [x] ✅ Security tests (CSRF, rate limiting, auth)
|
|
||||||
- [ ] ⏳ Frontend tests (Vitest + React Testing Library) - Optional
|
|
||||||
- [ ] ⏳ E2E tests (Playwright / Cypress) - Optional
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Quick Commands
|
## Progress Summary
|
||||||
|
|
||||||
|
| Phase | Status | Time |
|
||||||
|
|-------|--------|------|
|
||||||
|
| Phase 0: Frontend Mockup | ✅ Done | ~8h |
|
||||||
|
| Phase 1: Backend Foundation | ✅ Done | ~14h |
|
||||||
|
| Phase 1.5: Email & WSDC & Profiles | ✅ Done | ~12h |
|
||||||
|
| Phase 1.6: Competition Heats | ✅ Done | ~8h |
|
||||||
|
| Phase 2: Matches & Ratings | ✅ Done | ~10h |
|
||||||
|
| Phase 2.5: WebRTC P2P | ✅ Done | ~10h |
|
||||||
|
| Phase 3: MVP Finalization | ✅ Done | ~20h |
|
||||||
|
| **Total MVP** | **✅ Complete** | **~82h** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Commands
|
||||||
|
|
||||||
**Start development:**
|
|
||||||
```bash
|
```bash
|
||||||
|
# Development
|
||||||
docker compose up --build
|
docker compose up --build
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
docker compose exec backend npm test
|
||||||
|
|
||||||
|
# Access
|
||||||
|
http://localhost:8080
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rebuild after changes:**
|
|
||||||
```bash
|
|
||||||
docker compose down && docker compose up --build
|
|
||||||
```
|
|
||||||
|
|
||||||
**Access:**
|
|
||||||
- Frontend: http://localhost:8080
|
|
||||||
- Backend (future): http://localhost:8080/api
|
|
||||||
|
|
||||||
**Git workflow:**
|
|
||||||
```bash
|
|
||||||
git status
|
|
||||||
git add .
|
|
||||||
git commit -m "feat: description"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Progress Tracking
|
|
||||||
|
|
||||||
| Phase | Status | Progress | Time Spent |
|
|
||||||
|-------|--------|----------|------------|
|
|
||||||
| Phase 0: Frontend Mockup | ✅ Done | 100% | ~8h |
|
|
||||||
| Phase 1: Backend Foundation | ✅ Done | 100% | ~14h |
|
|
||||||
| Phase 1.5: Email & WSDC & Profiles | ✅ Done | 100% | ~12h |
|
|
||||||
| Phase 1.6: Competition Heats | ✅ Done | 100% | ~8h |
|
|
||||||
| Phase 2: Matches & Ratings API | ✅ Done | 100% | ~10h |
|
|
||||||
| Phase 2.5: WebRTC Implementation | ✅ Done | 100% | ~10h |
|
|
||||||
| Phase 3: MVP Finalization | ✅ Done | 100% | ~20h |
|
|
||||||
| **Total MVP** | **✅ Complete** | **100%** | **~82h** |
|
|
||||||
| Phase 4: Extensions | ⏳ Optional | - | TBD |
|
|
||||||
|
|
||||||
**Overall MVP Progress:** 100% ✅ Ready for production deployment
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Notes
|
|
||||||
|
|
||||||
- ✅ All MVP features implemented and tested
|
|
||||||
- ✅ 286/286 backend tests passing (73% coverage)
|
|
||||||
- ✅ Production deployment ready (Docker configs, scripts, monitoring)
|
|
||||||
- ✅ Security hardened (CSRF, rate limiting, account lockout)
|
|
||||||
- ✅ PWA enabled (offline support, iOS compatible)
|
|
||||||
- 🚀 Ready for production deployment (requires infrastructure setup)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**For detailed task history:** See `docs/archive/COMPLETED.md`
|
|
||||||
**For learning resources:** See `docs/archive/RESOURCES.md`
|
|
||||||
**For quick session context:** See `docs/SESSION_CONTEXT.md`
|
|
||||||
**For technical details:** See `docs/ARCHITECTURE.md`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Last Updated:** 2025-11-23
|
**Last Updated:** 2025-11-23
|
||||||
|
**Full Details:** See `docs/archive/COMPLETED.md` for implementation details
|
||||||
|
|||||||
Reference in New Issue
Block a user