Commit Graph

200 Commits

Author SHA1 Message Date
Radosław Gierwiało
a92d7469e4 feat(webrtc): integrate Cloudflare TURN/STUN servers
- Add backend endpoint to fetch ICE server credentials from Cloudflare
- Implement dynamic ICE server configuration in frontend
- Add fallback to public STUN servers when Cloudflare unavailable
- Create comprehensive test suite for WebRTC API endpoint
- Update environment configuration with Cloudflare TURN credentials

Backend changes:
- New route: GET /api/webrtc/ice-servers (authenticated)
- Fetches temporary credentials from Cloudflare API with 24h TTL
- Returns formatted ICE servers for RTCPeerConnection
- Graceful fallback to Google STUN servers on errors

Frontend changes:
- Remove hardcoded ICE servers from useWebRTC hook
- Fetch ICE servers dynamically from backend on mount
- Store servers in ref for peer connection initialization
- Add webrtcAPI service for backend communication

Tests:
- 9 comprehensive tests covering all scenarios
- 100% coverage for webrtc.js route
- Tests authentication, success, and all fallback scenarios
2025-12-05 21:23:50 +01:00
Radosław Gierwiało
e1138c789e fix(homepage): improve responsive layout for mobile devices
Navigation:
- Reduce logo and text size on mobile (w-6 h-6 -> w-8 h-8 on sm+)
- Reduce spacing between nav items (space-x-2 -> space-x-4 on sm+)
- Hide 'Dashboard' text on mobile, show icon only
- Adjust padding and text sizes for all nav buttons
- Add whitespace-nowrap to 'Get Started' button

Hero section:
- Responsive heading sizes (text-3xl -> text-6xl)
- Responsive paragraph sizes (text-base -> text-2xl)
- Responsive padding (py-12 -> py-20)
- Responsive button sizes (px-6/py-3 -> px-8/py-4)
2025-12-05 18:42:52 +01:00
Radosław Gierwiało
00825d56b6 fix(profile): improve responsive layout for public profile
- Add flex-wrap to stats section to prevent overflow on small screens
- Make profile header flex-col on mobile, flex-row on larger screens
- Add flex-shrink-0 to icons to prevent them from shrinking
- Reduce padding on mobile (p-4) and increase on larger screens
- Add min-w-0 to prevent text overflow issues
2025-12-05 18:40:13 +01:00
Radosław Gierwiało
fb4e0bea99 refactor(profile): remove Matches count from public profile stats
- Remove Matches stat display from public profile
- Keep only Rating and Reviews stats visible
- Remove unused Users icon import
2025-12-05 18:38:14 +01:00
Radosław Gierwiało
d4dd7bac30 feat(navbar): make username clickable link to public profile
- Desktop: username and avatar link to /u/{username}
- Mobile: username section in dropdown links to public profile
- Adds hover effect to indicate clickability
2025-12-05 18:36:51 +01:00
Radosław Gierwiało
1f763d4558 refactor(footer): remove Events link from Product section 2025-12-05 18:34:51 +01:00
Radosław Gierwiało
c4372930dd feat(content): add How It Works page with markdown support
- Create HowItWorksPage component with markdown rendering
- Add how-it-works.md with Lorem Ipsum placeholder content
- Add /how-it-works route in App.jsx
- Add How It Works link to homepage footer (Product section)
2025-12-05 18:33:25 +01:00
Radosław Gierwiało
2c5689ac8e feat(content): add About Us page with markdown content support
- Create AboutUsPage component with markdown rendering
- Add react-markdown library for content rendering
- Create public/content directory for editable markdown files
- Add about-us.md with Lorem Ipsum placeholder content
- Create public/images/about directory for page images
- Add /about-us route in App.jsx
- Add About Us link to homepage footer
- Support for external links (open in new tab) and internal links
- Responsive image rendering with rounded corners and shadow
2025-12-05 18:30:44 +01:00
Radosław Gierwiało
d8085f828f feat(security): add Cloudflare Turnstile CAPTCHA to registration form
- Add Turnstile widget rendering in RegisterPage on step 2
- Implement programmatic widget initialization with callbacks
- Add token validation before form submission
- Update AuthContext and API service to pass turnstileToken
- Add backend verification via Cloudflare API in register controller
- Include client IP in verification request
- Add validation rule for turnstileToken
- Reset widget on registration error
2025-12-05 18:20:26 +01:00
Radosław Gierwiało
f3b8156557 feat(security): implement Cloudflare Turnstile CAPTCHA on contact form
- Add Turnstile script to frontend/index.html
- Implement programmatic widget rendering in ContactPage
- Add backend verification via Cloudflare API
- Include client IP in verification request
- Update CSP headers to allow Cloudflare resources
- Add environment variable configuration for site and secret keys
- Pass VITE_TURNSTILE_SITE_KEY to frontend container
- Add validation and error handling for CAPTCHA tokens
2025-12-05 18:08:05 +01:00
Radosław Gierwiało
25042d0fec feat(home): adapt homepage for authenticated users
Changes for logged-in users:
- Top navigation: Show "Dashboard" and "Logout" buttons instead of "Sign In" and "Get Started"
- Hero CTA: Change main button to "Go to Dashboard" instead of "Start Collaborating"
- Hide bottom CTA section (registration prompt) for authenticated users
- Footer Account section: Show "Dashboard" and "Logout" instead of "Sign In" and "Register"

Other improvements:
- Removed "Explore Events" button from hero section
- Cleaned up footer: removed empty placeholder links (Features, How It Works, About, Privacy, Terms)
- Added "Support" section in footer with "Contact Us" link to /contact
- Simplified footer to 3 columns: Product (Events), Support (Contact Us), Account (dynamic based on auth)
2025-12-05 17:21:55 +01:00
Radosław Gierwiało
34f18b3b50 feat(contact): add contact form with admin panel and navbar dropdown
Database changes:
- Added ContactMessage model to Prisma schema
- Fields: userId, username, firstName, lastName, email, subject, message, status, ipAddress
- Status enum: new, read, resolved
- Relation to User model

Backend changes:
- Added POST /api/public/contact endpoint for form submissions
- Works for both authenticated and non-authenticated users
- Validation for email, subject (3-255 chars), message (10-5000 chars)
- Activity logging for submissions
- Added admin endpoints:
  - GET /api/admin/contact-messages - list with filtering by status
  - GET /api/admin/contact-messages/:id - view single message (auto-marks as read)
  - PATCH /api/admin/contact-messages/:id/status - update status
  - DELETE /api/admin/contact-messages/:id - delete message

Frontend changes:
- Created ContactPage at /contact route
- For non-logged-in users: firstName, lastName, email, subject, message fields
- For logged-in users: auto-fills username, shows only email, subject, message
- Character counter for message (max 5000)
- Success screen with auto-redirect to homepage
- Created ContactMessagesPage at /admin/contact-messages
- Two-column layout: message list + detail view
- Filter by status (all, new, read, resolved)
- View message details with sender info and IP address
- Update status and delete messages
- Added admin dropdown menu to Navbar
  - Desktop: dropdown with Activity Logs and Contact Messages
  - Mobile: expandable submenu
  - Click outside to close on desktop
  - ChevronDown icon rotates when open

Note: CAPTCHA integration planned for future enhancement
2025-12-05 17:15:25 +01:00
Radosław Gierwiało
f90945aa47 fix(profiles): make public profiles accessible without authentication and unify 404 behavior
Backend changes:
- Removed authentication requirement from GET /api/users/:username endpoint
- Removed authentication requirement from GET /api/users/:username/ratings endpoint
- These are public profile endpoints and should be accessible to all users

Frontend changes:
- PublicProfilePage now shows NotFoundPage component when user doesn't exist
- Unified 404 behavior: both invalid URLs and non-existent users show the same 404 page
- NotFoundPage "Requested URL" box now only shows in dev mode (import.meta.env.DEV)
- Removed unused AlertCircle icon import from PublicProfilePage
2025-12-05 16:54:38 +01:00
Radosław Gierwiało
948c694ed6 feat(system): implement 404 page with activity logging and change profile route format
Backend Changes:
- Added public API endpoint /api/public/log-404 (no auth required)
- Created backend/src/routes/public.js for public endpoints
- Added ACTIONS.SYSTEM_404 and CATEGORIES.system to activity log service
- Registered public routes in app.js

Frontend Changes:
- Created NotFoundPage.jsx with standalone layout (no auth required)
- Added publicAPI.log404() to log 404 access attempts
- Logs both authenticated and anonymous users
- Changed profile route from /@:username to /u/:username
- Made profile route public (removed ProtectedRoute wrapper)
- Updated all profile links from /@${username} to /u/${username} in:
  - ChatMessage.jsx
  - DashboardMatchCard.jsx
  - MatchRequestCards.jsx
  - MatchCard.jsx
  - UserListItem.jsx
  - MatchChatPage.jsx
  - PublicProfilePage.jsx

Fixes:
- React Router doesn't support @ in path segments
- 404 page now accessible to non-authenticated users without redirect
- Profile route no longer catches all unmatched routes
2025-12-03 20:27:51 +01:00
Radosław Gierwiało
eb5aacd797 refactor(admin): move event details page to admin section
- Moved EventDetailsPage from /events/:slug/details to /admin/events/:slug/details
- Added admin authentication check with redirect to login/home
- Updated all navigation links across the app:
  - EventsPage: "View details (admin)" button
  - EventChatPage: "View QR Code (admin)" link
  - EventCard: handleViewDetails navigation
- Fixed relative imports after moving to admin folder

This page contains admin-only features (QR codes, participants list,
matching config, scheduler config, matching runs) and should only be
accessible to administrators.
2025-12-03 19:52:00 +01:00
Radosław Gierwiało
179aaa8f16 fix(admin): activity logs empty success filter showing no results
- Fixed issue where empty string success filter was interpreted as false
- Backend was filtering for only failed logs when success='' was sent
- Added check to skip sending success parameter when empty string
- Activity logs page now shows all logs when filters are set to 'All'

Bug: When user selected 'All' for success filter, frontend sent success='',
backend parsed this as success=false, showing only failed logs (usually none).
2025-12-03 19:39:16 +01:00
Radosław Gierwiało
6562db1518 fix(backend): enable trust proxy for correct client IP detection
- Added app.set('trust proxy', 1) to allow Express to read proxy headers
- Enables proper client IP detection behind nginx reverse proxy
- Added /api/debug/ip endpoint for IP forwarding verification

Without trust proxy, Express ignores X-Forwarded-For and X-Real-IP headers,
causing all requests to appear from nginx container IP (172.x.x.x).

This fix ensures:
- Activity logs record correct client IPs
- Rate limiting works per actual client IP
- Security features function properly
2025-12-03 19:30:58 +01:00
Radosław Gierwiało
d8d04adfc6 fix(nginx): allow Vite dev dependencies in development mode
- Changed regex /\. to /\.(git|svn|htaccess|htpasswd|env) to allow .vite directory
- Removed node_modules from nginx blocked paths for Vite dependency serving
- Set VITE_ALLOWED_HOSTS=all in development mode for Docker networking

Fixes issue where nginx was blocking Vite's pre-bundled dependencies in
/node_modules/.vite/deps/, causing 404 errors for React and other imports.
2025-12-03 19:21:52 +01:00
Radosław Gierwiało
f6fd983c68 docs: update documentation with chat enhancements
Document three recent chat improvements:

1. Real-time Active Users Fix (dd31761)
   - Fixed bug where users list didn't update when new users joined
   - Rewrote getAllDisplayUsers() to prioritize Socket.IO data

2. Message Length Limits (4a91a10)
   - Added 2000 character limit with visual counter
   - Backend + frontend validation

3. Spam Protection System (ace3311)
   - Rate limiting: 10 messages per minute
   - Duplicate detection within 60 second window
   - Profanity filter with Polish + English words

Updated:
- README.md: Added chat features to Events & Chat section
- SESSION_CONTEXT.md: New "Chat Enhancements" section
- COMPLETED.md: Comprehensive entry with problem/solution/impact
- Last updated dates: 2025-12-03
2025-12-03 00:03:37 +01:00
Radosław Gierwiało
ace33111a4 feat(chat): implement spam protection and profanity filter
Add comprehensive message validation with three protection mechanisms:

1. Rate Limiting: 10 messages per minute per user
2. Duplicate Detection: Prevents sending identical messages within 1 minute
3. Profanity Filter: Blocks inappropriate language (English + Polish)

Implementation:
- New messageValidation.js middleware with validateMessage() function
- Integrated into both event chat and match chat handlers
- Uses bad-words library (v2.0.0 for CommonJS compatibility)
- In-memory tracking with automatic cleanup every 5 minutes
- User-friendly error messages for each validation type

Technical details:
- Rate limit: 10 msg/min sliding window
- Duplicate check: Last 5 messages within 60s window
- Profanity: bad-words + 11 Polish words
- Memory management: Periodic cleanup of expired data
2025-12-02 23:59:16 +01:00
Radosław Gierwiało
4a91a10aff feat(chat): add 2000 character limit for messages
Added message length validation to prevent spam and improve UX with
character counter feedback.

Backend:
- Added MESSAGE_MAX_LENGTH constant (2000 characters)
- Validation in send_event_message handler:
  - Check if content is string
  - Check if not empty after trim
  - Check if not exceeding max length
- Validation in send_match_message handler (same checks)
- Returns error message if validation fails

Frontend:
- Added MESSAGE_MAX_LENGTH constant (2000 characters)
- ChatInput component enhancements:
  - maxLength attribute on input (hard limit)
  - Character counter shows when >80% of limit
  - Counter turns red when at limit
  - Submit button disabled when at limit
  - Counter format: "X/2000"

UX:
- User sees counter at 1600+ characters (80% of limit)
- Hard limit prevents typing beyond 2000 chars
- Clear visual feedback (red text) when at limit
- Consistent validation on both event and match chats

Security:
- Prevents spam with extremely long messages
- Protects against potential DoS via message size
- Database already uses TEXT type (supports limit)
2025-12-02 23:46:54 +01:00
Radosław Gierwiało
dd3176196e fix(chat): real-time active users list updates
Fixed issue where active users list in event chat did not update in
real-time when new users joined. Users had to refresh the page to see
newly joined participants.

Root Cause:
- getAllDisplayUsers() used checkedInUsers (loaded once from API) as
  base list, with activeUsers (Socket.IO real-time) only for isOnline flag
- When new user joined chat, they appeared in activeUsers but not in
  checkedInUsers, so they were not displayed

Solution:
- Rewrote getAllDisplayUsers() to prioritize activeUsers (real-time data)
- Merges activeUsers (online) with checkedInUsers (offline checked-in users)
- Uses Socket.IO data as source of truth for online users
- Enriches with database data when available (firstName, lastName, etc)
- Sorts online users first, offline second

Changes:
- EventChatPage.jsx: Rewrote getAllDisplayUsers() to merge activeUsers
  with checkedInUsers, prioritizing real-time Socket.IO data
- useEventChat.js: Added debug logging for active_users events
- socket/index.js: Added debug logging for active_users emissions

Testing:
- User A in chat sees User B appear immediately when B joins
- No page refresh required
- Online/offline status updates in real-time
2025-12-02 23:38:46 +01:00
Radosław Gierwiało
a8fcb5e6eb docs: update documentation with Activity Log System implementation
Updated all major documentation files to reflect the completed Activity
Log System (Phase 3.5) implementation.

Changes:
- README.md: Added Admin & Monitoring section, updated database schema
  to 12 tables, added Activity Log System to completed phases, updated
  project structure to show admin pages and services
- SESSION_CONTEXT.md: Updated recent work, added activity log system to
  core features, updated database schema, added comprehensive Phase 3.5
  overview with all implementation details
- COMPLETED.md: Added full Activity Log System entry with all 8 phases,
  implementation details, git commits, and access information

Updated dates to 2025-12-02.
2025-12-02 23:24:38 +01:00
Radosław Gierwiało
1051cc6754 feat(admin): implement activity logs frontend page (Phase 6-7)
Complete implementation of admin activity logs dashboard with real-time
streaming capabilities. Admin users can now monitor all system activity
through a comprehensive web interface.

Features:
- Stats dashboard with 4 key metrics (total logs, unique users, failures, 24h activity)
- Category breakdown visualization with color-coded badges
- Advanced filtering (date range, category, action type, username, success/failure)
- Paginated log table (50 entries per page) with sort by timestamp
- Real-time streaming toggle using Socket.IO
- Color-coded action badges (blue=auth, green=event, purple=match, red=admin, yellow=chat)
- Admin-only access with automatic redirect for non-admin users
- Responsive design for mobile and desktop

Frontend Changes:
- Created ActivityLogsPage.jsx (600+ lines) with complete UI implementation
- Added 3 admin API methods to api.js (getActivityLogs, getActivityLogActions, getActivityLogStats)
- Added /admin/activity-logs route to App.jsx
- Added admin navigation link to Navbar (desktop & mobile) with Shield icon
- Only visible to users with isAdmin flag

Implementation Details:
- Uses getSocket() from socket service for real-time updates
- Joins 'admin_activity_logs' Socket.IO room on streaming enable
- Receives 'activity_log_entry' events and prepends to table (first page only)
- Comprehensive error handling and loading states
- Empty states for no data
- Clean disconnect handling when streaming disabled

Testing:
- Build successful (no errors)
- Ready for manual testing and verification

Phase 8 (Testing) remains for manual verification of all features.
2025-12-02 23:17:19 +01:00
Radosław Gierwiało
08845704cf docs: update TODO with Activity Log System Phase 1-5 completion 2025-12-02 20:12:10 +01:00
Radosław Gierwiało
d641e3f059 feat(activity-log): add Socket.IO real-time streaming (Phase 5)
Added socket handlers for admin activity log streaming:

Socket Events:
- join_admin_activity_logs: Admin joins streaming room
  - Verifies isAdmin flag from database
  - Rejects non-admin users with warning log
  - Emits confirmation: admin_activity_logs_joined

- leave_admin_activity_logs: Admin leaves streaming room
  - Clean disconnect from room

Real-time Flow:
1. Admin connects and emits join_admin_activity_logs
2. Server verifies admin status (fresh DB check)
3. Admin joins 'admin_activity_logs' Socket.IO room
4. activityLog.log() emits activity_log_entry to room
5. Admin receives real-time log entries as they happen

The activityLog service (Phase 2) already emits events,
so streaming is fully functional with these handlers.
2025-12-02 20:10:47 +01:00
Radosław Gierwiało
4dd6603018 feat(activity-log): add admin API endpoints (Phase 4)
Added 3 admin-only endpoints for activity log management:

1. GET /api/admin/activity-logs
   - Query logs with comprehensive filtering
   - Supports: date range, action, category, username, userId, success
   - Pagination with limit/offset
   - Logs ADMIN_VIEW_LOGS action
   - Returns: logs array, total count, pagination info

2. GET /api/admin/activity-logs/actions
   - Get list of unique action types
   - Returns: action names and categories
   - Useful for filter dropdowns in UI

3. GET /api/admin/activity-logs/stats
   - Dashboard statistics
   - Returns: total logs, unique users, failed actions,
     success rate, logs by category, recent activity (24h)

All endpoints protected with authenticate + requireAdmin middleware.
2025-12-02 20:09:49 +01:00
Radosław Gierwiało
d83e4163e5 feat(activity-log): integrate logging across all endpoints (Phase 3)
Added comprehensive activity logging to 14 integration points:

Auth Controller (4 actions):
- AUTH_REGISTER: User registration
- AUTH_LOGIN: User login
- AUTH_VERIFY_EMAIL: Email verification (token & code)
- AUTH_PASSWORD_RESET: Password reset

Events Routes (2 actions):
- EVENT_CHECKIN: User checks into event
- EVENT_LEAVE: User leaves event

Socket Handlers (3 actions):
- EVENT_JOIN_CHAT: User joins event chat room
- EVENT_LEAVE_CHAT: User leaves event chat room
- CHAT_JOIN_ROOM: User joins private match chat

Matches Routes (3 actions):
- MATCH_CREATE: Match request created
- MATCH_ACCEPT: Match request accepted
- MATCH_REJECT: Match request rejected/cancelled

Admin Routes (1 action + security):
- ADMIN_MATCHING_RUN: Admin runs matching algorithm
- Added requireAdmin middleware to all admin routes

All logs include:
- User ID and username (denormalized)
- IP address (X-Forwarded-For aware)
- Action type and resource ID
- HTTP method and path (or SOCKET for WebSocket)
- Contextual metadata (event slugs, match IDs, etc.)

Fire-and-forget pattern ensures logging never blocks requests.
2025-12-02 20:07:10 +01:00
Radosław Gierwiało
0466ef9e5c security(nginx): block access to sensitive files and directories
Added comprehensive security rules to all nginx configurations:

Dev proxy (nginx/conf.d/default.conf):
- Block dotfiles and .git directory
- Block .env* files and config files
- Block node_modules, docker configs, package files
- Block backup files (.bak, .swp, ~)

Prod proxy (nginx/conf.d.prod/default.conf):
- All dev security rules
- Added security headers (X-Frame-Options, CSP, etc.)
- Strict CSP with frame-ancestors 'none'

Frontend container (frontend/nginx.conf):
- Block dotfiles and sensitive config files
- Block node_modules and build configs
- Added security headers

All blocked paths return 404 and disable logging to avoid log spam.

Blocks: .env*, .git, node_modules, docker*, package*.json,
prisma, backup*, *.bak, *.swp, tsconfig.json, and more.
2025-12-02 19:55:08 +01:00
Radosław Gierwiało
c9beee9a4e feat(admin): add Activity Log backend services (Phase 2)
Core services for activity logging system:

1. ActivityLog Service (backend/src/services/activityLog.js)
   - Centralized logging with fire-and-forget pattern
   - 18 action constants (auth, event, match, admin, chat)
   - Query interface with filtering (date, action, user, category)
   - Socket.IO emission for real-time streaming
   - Statistics and action types endpoints
   - Never throws - logging cannot crash app

2. Request Utility (backend/src/utils/request.js)
   - getClientIP() - Extract client IP from headers/socket
   - Handles X-Forwarded-For and X-Real-IP proxy headers
   - IPv6-mapped IPv4 conversion

3. Admin Middleware (backend/src/middleware/admin.js)
   - requireAdmin() - Protect admin routes
   - Fresh DB check of isAdmin flag
   - Returns 403 for non-admin users
   - Use after authenticate middleware

Next phases: logging integration points, API endpoints, frontend UI
2025-12-02 19:47:47 +01:00
Radosław Gierwiało
f9cdf2aa98 feat(admin): add ActivityLog schema and isAdmin flag
Database changes:
- Add ActivityLog model for comprehensive activity tracking
  - Track all user actions (auth, events, matches, admin)
  - Denormalized username for query performance
  - JSON metadata for flexibility
  - Multiple indexes for common filter patterns
- Add isAdmin flag to User model for admin access control
- Add activityLogs relation to User

Schema pushed to database with prisma db push
Created initial admin user: spotlight@radziel.com

This is Phase 1 of Activity Log System implementation.
Next phases: backend service, middleware, API endpoints, frontend UI.
2025-12-02 19:42:24 +01:00
Radosław Gierwiało
b77ccab9d4 refactor(emails): restructure email system and add recording notifications
- Move email templates to separate files in src/emails/templates/
- Create new email service architecture (service.js, index.js)
- Add recording suggestions email template for matching notifications
- Integrate email notifications with matching system (sends when suggestions created)
- Update controllers (auth.js, user.js) to use new email module
- Update tests to use new email module path
- Remove deprecated src/utils/email.js

Features:
- Template-based email system for easy editing
- Automatic email notifications when recording assignments are made
- Clean separation between template logic and sending logic
- Graceful error handling for AWS SES failures
2025-12-02 19:19:22 +01:00
Radosław Gierwiało
231d3d177c docs: update TODO and COMPLETED with spam protection and notifications
- Mark S15.1-15.2 (Rate Limiting & Spam Protection) as implemented
- Mark S16.1 (Socket Notifications) as implemented
- Update test count: 342 → 350 tests
- Add implementation details to COMPLETED.md
- Update recent work timeline
2025-12-01 00:07:24 +01:00
Radosław Gierwiało
ec659d83e8 feat(matches): implement spam protection and socket notifications
S15.1-15.2: Rate Limiting & Spam Protection
- Add max 20 pending outgoing match requests limit
- Implement rate limiter: 10 match requests per minute per user
- Return 429 status with clear error messages

S16.1: Socket Notifications for New Suggestions
- Emit 'recording_suggestions_created' event when matching creates suggestions
- Notify only assigned recorders (not NOT_FOUND status)
- Group suggestions by recorder for efficiency
- Include event details and suggestion count

Implementation:
- backend/src/routes/matches.js: Rate limiter + pending limit check
- backend/src/services/matching.js: Socket notifications in saveMatchingResults
- backend/src/__tests__/spam-protection-notifications.test.js: 8 test cases

Test coverage:
- TC1-TC3: Max pending requests (spam protection)
- TC4-TC5: Rate limiting (10/min)
- TC6-TC8: Socket notifications for new suggestions
2025-12-01 00:03:46 +01:00
Radosław Gierwiało
964897bdc0 docs: move completed tasks to archive and update TODO status
- Add recent completions to COMPLETED.md:
  - 3-Tier Account System & Fairness Algorithm (2025-11-29)
  - Mobile-first Design Improvements (2025-11-29)
  - Test Bot for Automated Testing (2025-11-29)
  - Ratings & Stats System (2025-11-30, 9 E2E tests)
  - Matching Runs Audit & origin_run_id Tracking (2025-11-30, 30 tests)
  - Documentation Reorganization (2025-11-30)
- Update TODO.md current status (342/342 tests passing - 100%)
- Remove "Recently Completed" sections from TODO.md
- Update implemented scenarios list
2025-11-30 20:22:07 +01:00
Radosław Gierwiało
913d685721 docs: streamline README and update SESSION_CONTEXT, archive outdated docs
- Streamline README.md from 645 to 365 lines (43% reduction)
- Remove duplicate content with other documentation files
- Focus README on quick start, features overview, and links to detailed docs
- Update SESSION_CONTEXT.md with recent changes (342/342 tests, matching runs audit)
- Archive outdated documentation:
  - CONTEXT.md (duplicated in README)
  - QUICKSTART.md (mentions mock auth, outdated)
  - QUICK_TEST.md (outdated)
- Keep SESSION_CONTEXT.md active for context restoration
2025-11-30 20:17:27 +01:00
Radosław Gierwiało
9af4447e1d docs: update documentation with matching runs audit and complete test coverage
- Update README.md with current test statistics (342/342 tests passing)
- Add detailed breakdown of all matching/ratings test suites
- Create comprehensive TESTING_MATCHING_RATINGS.md guide covering all 45 tests
- Document matching runs audit, incremental matching, and scheduler features
- Add code coverage highlights and test scenarios
2025-11-30 20:10:25 +01:00
Radosław Gierwiało
bd7212a599 feat(matching): implement origin_run_id tracking and audit tests
- Updated run-matching endpoint to create MatchingRun records
- Added trigger tracking (manual vs scheduler)
- Fixed saveMatchingResults to accept runId parameter
- Added comprehensive audit tests (matching-runs-audit.test.js):
  * TC1: origin_run_id assigned correctly
  * TC2: Sequential runs create separate run IDs
  * TC3: Accepted suggestions preserve origin_run_id
  * TC4: Filter parameters (onlyAssigned, includeNotFound)
  * TC5: Manual vs scheduler trigger differentiation
  * TC6: Failed runs recorded in audit trail
- All 6 audit tests passing
2025-11-30 20:01:10 +01:00
Radosław Gierwiało
f13853c300 fix(tests): correct socket test to use nested user.username field
- Updated event_message test to expect message.user.username
- Matches current socket.io implementation which nests user data
- All 342 tests now passing (100%)
2025-11-30 19:44:32 +01:00
Radosław Gierwiało
72275835f1 test(matching): add comprehensive integration tests for matching algorithm
- Implement all 19 test scenarios from matching-scenarios.md
- Phase 1: Fundamentals (TC1-3) - basic flow and NOT_FOUND cases
- Phase 2: Collision Detection (TC4-9) - heat buffers and slot mapping
- Phase 3: Limits & Workload (TC10-11) - MAX_RECORDINGS and collision bugs
- Phase 4: Fairness & Tiers (TC12-16) - debt calculation and tier penalties
- Phase 5: Edge Cases (TC17-19) - multiple heats and incremental matching
- All 19 tests passing with 76.92% coverage on matching.js
2025-11-30 19:37:36 +01:00
Radosław Gierwiało
065e77fd4e test(ratings): add comprehensive E2E test for ratings & stats flow
Add end-to-end test verifying the complete ratings and stats update flow:
- Auto match creation from suggestion acceptance
- Both users rating each other
- Stats updated exactly once (recordingsDone/recordingsReceived)
- Manual matches do NOT update stats
- Double-rating prevention (idempotency)

Test coverage (9 scenarios):
- STEP 1-3: Event creation, user enrollment, heat declaration
- STEP 4: Matching algorithm execution + saveMatchingResults fix
- STEP 5: Suggestion acceptance creates auto match (source='auto')
- STEP 6a: First rating (no stats update yet)
- STEP 6b: Second rating triggers stats update + match completion
- STEP 7: Verify duplicate rating prevention
- STEP 8: Verify manual matches don't affect fairness stats

Infrastructure:
- Add jest.setup.js to load .env.development for all tests
- Update package.json to use setupFilesAfterEnv

Documentation:
- Mark S10 (Ratings & Stats) as  IMPLEMENTED in TODO.md
- Remove from Critical Gaps section
- Add detailed implementation references

All tests passing 
2025-11-30 19:18:09 +01:00
Radosław Gierwiało
25236222de feat(matching): prevent auto suggestions when manual match exists + comprehensive test scenarios
Matching Service:
- Fetch manual matches at start of runMatching() (suggestionId: null)
- Build manualBlockedPairs set with both directions (A:B and B:A)
- Skip recorder candidates if manual match exists between dancer and recorder
- Ensures no duplicate matches on /matches page
- Manual match = user-controlled, algorithm respects user decisions

Documentation (docs/TODO.md):
- Add comprehensive matching system test scenarios (S1-S16)
- Document 4 critical gaps (P0): ratings/stats, admin middleware, participant validation
- Document 3 high priority items (P1): cleanup conflicts, rate limiting, notifications
- Document 6 medium priority items (P2): audit endpoints, zombie cleanup, reminders
- List 11 edge cases for team discussion (E1-E11)
- Clear priority ranking and questions for team

Critical Findings:
- recordingsDone/recordingsReceived fields exist but NEVER updated (fairness broken!)
- Admin endpoints lack security middleware
- Inconsistent event participant validation across endpoints

Test Coverage:
- S1-S7: Implemented (basic flow, collisions, limits, manual vs auto)
- S10: NOT IMPLEMENTED - ratings/stats system (CRITICAL!)
- S11: Partially implemented - audit trail exists, API endpoints missing
- S14: Partially implemented - recorder-only auth works, admin middleware missing
- S15-S16: NOT IMPLEMENTED - security, notifications
2025-11-30 15:53:00 +01:00
Radosław Gierwiało
f45cadae7d feat(matches): show both manual match requests and auto recording suggestions
Backend:
- Extend GET /api/matches to include RecordingSuggestions alongside Match objects
- Add 'type' field: 'manual' for user-created matches, 'auto' for algorithm suggestions
- Fetch suggestions where user is dancer (to be recorded) or recorder (recording others)
- Transform suggestions to match format with partner info
- Support status filtering for both types

Frontend:
- Display 'Auto' (purple) or 'Manual' (gray) badge on match cards
- For pending auto suggestions: show 'Go to Records' button instead of Accept/Reject
- For accepted auto suggestions without slug: show 'Chat not available yet'
- Only allow Accept/Reject actions on manual match requests
2025-11-30 15:30:49 +01:00
Radosław Gierwiało
d8799d03af feat(dashboard): add Recording Assignments section
- Extend dashboard API to include recordingSuggestions for each event
- Add toBeRecorded and toRecord arrays with heat and user details
- Export RecordingSummaryCard component
- Add Recording Assignments section to DashboardPage
- Filter and display events with recording suggestions
- Show up to 2 suggestions per event with View Details link
2025-11-30 15:14:06 +01:00
Radosław Gierwiało
6ce3111cdd feat(dashboard): improve RecordingSummaryCard styling and fix tab navigation
- Increase font size from xs to sm for better readability
- Reduce avatar size from xs to 24px for better proportions
- Add proper layout with heat names in separate line
- Add truncate for long usernames to prevent overflow
- Style status badges with colored backgrounds and icons (pending/accepted)
- Fix EventChatPage to read and handle ?tab=records URL parameter
- Map 'records' query param to 'recording' tab for proper navigation
2025-11-30 15:13:50 +01:00
Radosław Gierwiało
2e49fa5c62 feat(recordings): only recorder can accept/reject suggestions in MVP
Backend changes:
- Restrict suggestion status updates to recorder only
- Dancers can now only view who is assigned to record them
- Return 403 error if non-recorder tries to update status

Frontend changes:
- Remove Accept/Reject buttons from dancer view (TO_BE_RECORDED)
- Add "Pending" status badge with clock icon for pending suggestions
- Keep Accept/Reject buttons for recorder view (TO_RECORD)
- Dancers see only status badge and optional chat button

UX flow:
- Dancer sees: "Recording you: @username [Pending]"
- Recorder sees: "You record: @username [Accept] [Reject]"
- Only recorder's action creates the Match
2025-11-30 14:54:09 +01:00
Radosław Gierwiało
560ff1edc1 fix(scheduler): implement deadline-based matching with 5-run limit and fix security issues
Security fixes:
- Replace $queryRawUnsafe with parameterized $queryRaw in admin.js to prevent SQL injection
- Use PostgreSQL ANY() operator for safe array parameter handling

Scheduler improvements:
- Add registrationDeadline support - scheduler now waits until deadline before running
- Implement 5-run limit after deadline (runs exactly 5 times with 5-minute intervals)
- Add countScheduledRunsAfterDeadline() to track post-deadline runs
- Add environment variable validation with sensible min/max ranges
- Fix Prisma query syntax (remove invalid endDate null check for non-nullable field)

UI improvements:
- Fix colspan mismatch in MatchingRunsSection (6 → 8 columns)
- Remove duplicate "Uruchom Matching" button, keep only "Run now" with audit tracking
- Simplify MatchingConfigSection to focus on deadline configuration

Logging enhancements:
- Add detailed scheduler logs showing run progress (e.g., "Running post-deadline matching (3/5)")
- Log wait times before deadline and between runs
- Show completion status after 5 runs
2025-11-30 14:42:08 +01:00
Radosław Gierwiało
752d65035a fix(scheduler): use equals: null filter for endDate to satisfy Prisma where syntax and stop log spam 2025-11-30 13:50:48 +01:00
Radosław Gierwiało
621511fccf feat(matching-runs): add per-run aggregate stats and UI display
- Admin list endpoint returns totalSuggestions, assignedCount, aggregatedNotFoundCount per run
- UI: show Total/Matched/Not found columns using fresh aggregates
- Add anchor link Run #ID and wording 'Pairs created in this run'
2025-11-30 13:43:05 +01:00
Radosław Gierwiało
a9ad25eb38 feat(matching-runs): attach origin_run_id to new suggestions and expose pairs-per-run API
- Extend saveMatchingResults(eventId, suggestions, runId) and set originRunId
- Scheduler/Admin run-now: always pass runId
- Admin API: GET /api/admin/events/:slug/matching-runs/:runId/suggestions
- Prisma: add compound index on (origin_run_id, status)
- Frontend: add getRunSuggestions, expand row in MatchingRunsSection with 'Pairs created in this run' wording
2025-11-30 13:37:32 +01:00