Files
dwroller/database/routes/sessionRoutes.js
Alex cdfd147f02 feat: Mission Tab — 11 playthrough fixes + 4 follow-up findings
All 11 issues from 4-player simulation of The Hunt for Fabius Bile:
1. Roll feed visible to all players (no GM auth guard)
2. Scene text gated by revealed flag; GM explicit reveal per scene
3. GM can add NPC/enemy entries to initiative tracker
4. Round counter synced to Dice Roller via localStorage + custom event
5. Check reward text hidden until player has rolled
6. Checks assignable to specific player via Scene Secrets ⚙ options
7. Fear test quick-roll panel with WP input appears when fearRating > 0
8. Decision checks show textarea/Declare instead of d100 roll button
9. Fate point re-roll: one per check per scene, resets on scene advance
10. Player poll reduced from 8s to 4s, combined mission + roll feed poll
11. Mission complete banner with scene stats and GM outcome notes field

4 follow-up findings from second simulation run:
- Finding #1: Activate mission now initialises revealed:false on all scenes
  so players never see scene text before the GM narrates
- Finding #2: Fear penalty auto-applied to WP display; button shows
  effective (penalised) target rather than raw WP input
- Finding #3: RollFeedRow moved outside component to avoid re-mount on
  every render; onDelete passed as prop
- Finding #4: Removed duplicate "Open for Players" quick-button from
  Scene Checks left panel — Scene Secrets is the sole entry point

New files:
- src/tests/missionPlaythrough.test.js — full GM+4-player simulation
  test suite covering all 11 issues and 4 findings (39 test cases)
- src/tests/missionTab.test.js — player/GM view isolation tests
- src/utils/diceRoller.js — shared d100/degrees/clampTarget utilities
- tests/missionRoutes.test.js — backend mission route unit tests
- tests/playerRoutesLogin.test.js — player login route tests
- tests/sessionRoutes.test.js — session validation tests

Note: React unit tests require jsdom; segfaults on ARM64 (Raspberry Pi)
due to a known jsdom/Node 20 incompatibility on aarch64. Tests pass on
x86 CI. Backend integration tests (tests/) run normally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 00:25:51 +02:00

53 lines
1.5 KiB
JavaScript

const express = require('express');
const { logToFile } = require('../mariadb');
const { validateSession, deleteSession } = require('../sessionModel');
const router = express.Router();
// Simple session validation endpoint
router.post('/validate', async (req, res) => {
try {
const { sessionId } = req.body;
if (!sessionId) {
logToFile('SESSION: Validate missing sessionId');
return res.status(400).json({ error: 'sessionId required' });
}
const session = await validateSession(sessionId);
if (!session || !session.data || !session.data.playerName) {
logToFile('SESSION: Invalid or expired session', sessionId);
return res.status(401).json({ error: 'Invalid or expired session' });
}
const playerName = session.data.playerName;
logToFile('SESSION: Session validation successful', playerName);
res.json({
valid: true,
playerName
});
} catch (error) {
console.error('Session validation error:', error);
logToFile('SESSION: Failed to validate session', error);
res.status(500).json({ error: String(error) });
}
});
// Logout endpoint
router.post('/logout', async (req, res) => {
try {
const { sessionId } = req.body;
if (sessionId) {
await deleteSession(sessionId);
logToFile('SESSION: Logout', sessionId);
}
res.json({ success: true });
} catch (error) {
logToFile('SESSION: Logout error', error);
res.status(500).json({ error: String(error) });
}
});
console.log('Session routes registered');
module.exports = router;