Skip to content

feat: Peer Challenge (SP Wager System) — P2P competitive challenges with escrow & settlement - #99

Open
nit1914 wants to merge 8 commits into
vicharanashala:mainfrom
nit1914:feature/peer-challenge
Open

feat: Peer Challenge (SP Wager System) — P2P competitive challenges with escrow & settlement#99
nit1914 wants to merge 8 commits into
vicharanashala:mainfrom
nit1914:feature/peer-challenge

Conversation

@nit1914

@nit1914 nit1914 commented Jul 19, 2026

Copy link
Copy Markdown

Summary

Implements the Peer Challenge feature — a student-vs-student SP wager system where classmates can challenge each other on tracked topics (Vibe Course Progress, Matrix Questions, Poll Accuracy), lock SP in escrow, and have outcomes settled automatically.

What's Included

Backend (server/)

  • Challenge Model (models/Challenge.js): Mongoose schema with full lifecycle (pending → active → settled/expired/cancelled/declined), escrow tracking, audit trail, and progress snapshots
  • Challenge Routes (routes/challenges.js): Complete REST API for challenge CRUD:
    • GET /topics — available challenge topics
    • GET /peers?q= — peer search with concurrent-challenge limit checks
    • POST / — create challenge with SP validation & escrow
    • GET /mine — fetch all challenges for the logged-in student (categorized into sent/received/active/history)
    • GET /:id — single challenge detail with live progress
    • POST /:id/accept — accept with opponent SP verification
    • POST /:id/decline — decline a pending challenge
    • POST /:id/cancel — cancel own pending challenge
  • Challenge Middleware (middleware/challengeMiddleware.js): Auth & access control for challenge routes
  • Settlement Job (jobs/settleChallenges.js): Background job (runs every 5 min) that auto-expires timed-out pending challenges and settles completed active challenges with SP transfers
  • Offline/Demo Mode: Full in-memory mock database fallback — all routes work without MongoDB for local development & demos

Frontend (client/src/)

  • Challenge Tab in the student dashboard with:
    • SP wallet display (total / available / locked)
    • "Challenge a Peer" creation flow with topic selection, peer search, wager slider, and duration picker
    • Sent/Received pending challenge cards with countdown timers
    • Active challenge cards with live progress bars
    • Challenge history with outcome badges (Won/Lost/Draw)
    • Challenge detail view with full audit trail
  • Explainer Page (/spurti/challenges): Public-facing page explaining how challenges work

Guardrails & Validation

  • Max 3 concurrent active/pending challenges per student
  • Self-challenge prevention
  • Wager capped at available SP (total minus locked)
  • Excused students filtered from peer search
  • 2-hour respond timeout on pending challenges
  • Deterministic simulated progress (seeded by challengeId + studentId)

Testing

  • All API endpoints verified via direct HTTP calls in Offline/Demo mode
  • Challenge creation, acceptance, decline, cancel flows all tested end-to-end
  • Settlement logic verified for SP transfers on completion

No Changes to Existing Data Model

This PR does not modify the existing Student schema or any upstream collections. The Challenge model is a new, additive collection. SP transfers on settlement use the existing SpTransaction model.

- Resolve B1: Default Express ADMIN_EMAIL and ADMIN_TOKEN to empty strings.
- Resolve B2: Eliminate XSS vulnerability in Needs Attention card by replacing dangerouslySetInnerHTML with structured safe JSX.
- Resolve B3: Rewrite spLedger.js service layer to match correct SPTransaction schema fields.
- Resolve B4: Correct sp.js service layer field names and add fallback safety defaults.
- Address non-blocking improvements:
  * N5: Wrap search/confirm API routes in try-catch to prevent MongoDB crashes.
  * N6: Wrap AdminView fetch requests in try-catch blocks to prevent UI hangs.
  * N7: Evict stale liveViewers entries every 5 minutes to prevent memory bloat.
  * N9: Eliminate duplicate .metric class in stylesheet.
  * N10: Add aria-label='Close' and × character to close buttons.
  * N14: Fix admin ping useEffect to track [auth] credentials.
  * N17: Remove invalid '.chart-dot:hover { r: 5 }' rule.
- Revert studentEmailFromRequest() to return a plain email string to prevent Mongo query failures across survey/status and ping routes. vibeData is now attached directly to req.vibeData.
- Default ADMIN_EMAIL and ADMIN_TOKEN to null (instead of ''). Update isAdmin() to block unconfigured blank-header authorization requests.
- Restructure appendTransaction() in spLedger.js to perform an atomic findOneAndUpdate update on student SP, guaranteeing consistency of balanceAfter.
- Remove redundant duplicate formatDate() declaration in SpTrendChart.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants