mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-10-18 06:41:27 +02:00
feat: admin dashboard, alert service, and docs reorganization
- Add alertService.js with Resend email alerts for low balance, disconnects, failed payouts - Update admin.html with full dashboard UI (stats, charts, tables, payout retry) - Add wallet balance to /health endpoint - Add getBalance() and checkTransactionStatus() to walletRPCService - Fix payoutRetryService query and add alert integration - Update .env.example with alert config (RESEND_API_KEY, ADMIN_EMAIL, etc) - Reorganize docs: move TODO.md, LOGS_AND_BACKUP.md to docs/ - Extract deployment guide from README to docs/DEPLOY.md - Consolidate TEMP_TODO.md into docs/TODO.md
This commit is contained in:
+402
@@ -0,0 +1,402 @@
|
||||
# Production Deployment Guide
|
||||
|
||||
This guide covers deploying Wownerogue to a production environment.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 22.x LTS or later
|
||||
- PostgreSQL 12+
|
||||
- Wownero or Monero wallet-rpc running and synced
|
||||
- A domain with SSL certificate (via reverse proxy)
|
||||
|
||||
---
|
||||
|
||||
## Deployment Checklist
|
||||
|
||||
- [ ] Set `NODE_ENV=production`
|
||||
- [ ] Configure TLS via reverse proxy (Nginx/Caddy)
|
||||
- [ ] Set secure database credentials
|
||||
- [ ] Configure wallet-rpc with authentication
|
||||
- [ ] Set `ADMIN_API_KEY` for admin endpoints
|
||||
- [ ] Firewall: expose only 80/443
|
||||
- [ ] Protect `/admin.html` with basic auth
|
||||
- [ ] Set up database backups (see [LOGS_AND_BACKUP.md](./LOGS_AND_BACKUP.md))
|
||||
- [ ] Configure log rotation
|
||||
- [ ] Run database migrations
|
||||
|
||||
---
|
||||
|
||||
## Create Dedicated User
|
||||
|
||||
Create an isolated system user for security:
|
||||
|
||||
```bash
|
||||
# Create system user with no login shell and dedicated home
|
||||
sudo useradd --system --shell /usr/sbin/nologin --home-dir /var/www/wownerogue --create-home wownerogue
|
||||
|
||||
# Create .ssh directory for deploy key
|
||||
sudo mkdir -p /var/www/wownerogue/.ssh
|
||||
sudo chmod 700 /var/www/wownerogue/.ssh
|
||||
sudo chown wownerogue:wownerogue /var/www/wownerogue/.ssh
|
||||
|
||||
# Create log directory
|
||||
sudo mkdir -p /var/log/wownerogue
|
||||
sudo chown wownerogue:wownerogue /var/log/wownerogue
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Setup Deploy Key and Clone Repository
|
||||
|
||||
Generate an SSH deploy key for the wownerogue user:
|
||||
|
||||
```bash
|
||||
# Generate deploy key (as root, since user has no shell)
|
||||
sudo ssh-keygen -t ed25519 -C "wownerogue-deploy" -f /var/www/wownerogue/.ssh/id_ed25519 -N ""
|
||||
|
||||
# Set correct ownership and permissions
|
||||
sudo chown wownerogue:wownerogue /var/www/wownerogue/.ssh/id_ed25519*
|
||||
sudo chmod 600 /var/www/wownerogue/.ssh/id_ed25519
|
||||
sudo chmod 644 /var/www/wownerogue/.ssh/id_ed25519.pub
|
||||
|
||||
# Display the public key
|
||||
sudo cat /var/www/wownerogue/.ssh/id_ed25519.pub
|
||||
```
|
||||
|
||||
Add the deploy key to GitHub:
|
||||
1. Go to your repository → **Settings** → **Deploy keys**
|
||||
2. Click **Add deploy key**
|
||||
3. Paste the public key from the command above
|
||||
4. Leave "Allow write access" unchecked (read-only is sufficient)
|
||||
5. Click **Add key**
|
||||
|
||||
Configure SSH for GitHub:
|
||||
|
||||
```bash
|
||||
# Create SSH config for the wownerogue user
|
||||
sudo tee /var/www/wownerogue/.ssh/config << 'EOF'
|
||||
Host github.com
|
||||
HostName github.com
|
||||
User git
|
||||
IdentityFile ~/.ssh/id_ed25519
|
||||
IdentitiesOnly yes
|
||||
StrictHostKeyChecking accept-new
|
||||
EOF
|
||||
|
||||
sudo chown wownerogue:wownerogue /var/www/wownerogue/.ssh/config
|
||||
sudo chmod 600 /var/www/wownerogue/.ssh/config
|
||||
```
|
||||
|
||||
Clone the repository:
|
||||
|
||||
```bash
|
||||
# Clone as the wownerogue user (replace YOUR_USERNAME with your GitHub username)
|
||||
sudo -u wownerogue git clone git@github.com:YOUR_USERNAME/wownerogue.git /var/www/wownerogue/app
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Install Node.js
|
||||
|
||||
Install Node.js LTS using NodeSource (run as root):
|
||||
|
||||
```bash
|
||||
# Install Node.js 22.x LTS (or check https://nodejs.org for current LTS)
|
||||
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
||||
apt-get install -y nodejs
|
||||
|
||||
# Verify installation
|
||||
node --version
|
||||
npm --version
|
||||
```
|
||||
|
||||
Install dependencies and audit for vulnerabilities:
|
||||
|
||||
```bash
|
||||
cd /var/www/wownerogue/app/src
|
||||
sudo -u wownerogue npm install
|
||||
|
||||
# Check for known vulnerabilities
|
||||
sudo -u wownerogue npm audit
|
||||
|
||||
# Auto-fix vulnerabilities where possible
|
||||
sudo -u wownerogue npm audit fix
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Set File Permissions
|
||||
|
||||
```bash
|
||||
# Set ownership of application files
|
||||
sudo chown -R wownerogue:wownerogue /var/www/wownerogue
|
||||
|
||||
# Restrict permissions (owner only, no world access)
|
||||
sudo chmod 750 /var/www/wownerogue
|
||||
sudo chmod 640 /var/www/wownerogue/app/src/.env
|
||||
```
|
||||
|
||||
**Database permissions** - create a restricted PostgreSQL role:
|
||||
|
||||
```sql
|
||||
-- Create role with minimal privileges
|
||||
CREATE USER wownerogue WITH PASSWORD 'secure-password-here';
|
||||
CREATE DATABASE wownerogue OWNER wownerogue;
|
||||
|
||||
-- Revoke dangerous permissions
|
||||
REVOKE CREATE ON SCHEMA public FROM wownerogue;
|
||||
|
||||
-- Grant only what's needed
|
||||
GRANT CONNECT ON DATABASE wownerogue TO wownerogue;
|
||||
GRANT USAGE ON SCHEMA public TO wownerogue;
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO wownerogue;
|
||||
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO wownerogue;
|
||||
```
|
||||
|
||||
**Filesystem isolation** (optional, for extra hardening):
|
||||
|
||||
```bash
|
||||
# Prevent the user from accessing other users' home directories
|
||||
sudo chmod 700 /home/*
|
||||
|
||||
# Mount application directory with noexec for uploads (if applicable)
|
||||
# Add to /etc/fstab if using separate partition
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Setup
|
||||
|
||||
### Run Migrations
|
||||
|
||||
Database migrations run automatically on server start (via `databaseManager.runMigrations()`), but you can also run them manually:
|
||||
|
||||
```bash
|
||||
cd /var/www/wownerogue/app/src
|
||||
|
||||
# Source environment variables
|
||||
source .env
|
||||
|
||||
# Run migrations manually if needed
|
||||
psql -h $DB_HOST -U $DB_USER -d $DB_NAME -f migrations/001_initial_schema.sql
|
||||
# ... repeat for each migration file in order
|
||||
```
|
||||
|
||||
### Database Reset (Development Only)
|
||||
|
||||
```bash
|
||||
npm run db:drop # Drop all tables
|
||||
npm run db:create # Recreate schema
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## systemd Service
|
||||
|
||||
Save to `/etc/systemd/system/wownerogue.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Wownerogue Game Server
|
||||
After=network.target postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=wownerogue
|
||||
Group=wownerogue
|
||||
# Adjust paths if you cloned to a different location
|
||||
WorkingDirectory=/var/www/wownerogue/app/src
|
||||
EnvironmentFile=/var/www/wownerogue/app/src/.env
|
||||
ExecStart=/usr/bin/node index.js
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
# Security hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=strict
|
||||
ProtectHome=yes
|
||||
PrivateTmp=yes
|
||||
ReadWritePaths=/var/www/wownerogue /var/log/wownerogue
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Enable and start:
|
||||
|
||||
```bash
|
||||
# Create .env from example first!
|
||||
sudo -u wownerogue cp /var/www/wownerogue/app/src/.env.example /var/www/wownerogue/app/src/.env
|
||||
sudo vim /var/www/wownerogue/app/src/.env # Edit with your settings
|
||||
|
||||
# Enable and start service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable wownerogue
|
||||
sudo systemctl start wownerogue
|
||||
sudo systemctl status wownerogue
|
||||
```
|
||||
|
||||
The systemd hardening options:
|
||||
- `NoNewPrivileges` - prevents privilege escalation
|
||||
- `ProtectSystem=strict` - mounts filesystem read-only except allowed paths
|
||||
- `ProtectHome=yes` - hides /home, /root, /run/user
|
||||
- `PrivateTmp=yes` - isolates /tmp
|
||||
- `ReadWritePaths` - whitelists writable directories
|
||||
|
||||
---
|
||||
|
||||
## Reverse Proxy (Nginx Proxy Manager)
|
||||
|
||||
If using Nginx Proxy Manager:
|
||||
|
||||
1. **Add Proxy Host**
|
||||
- Domain Names: `yourdomain.com`
|
||||
- Scheme: `http`
|
||||
- Forward Hostname/IP: Your server's LAN IP (e.g., `192.168.1.100`)
|
||||
- Forward Port: `3000`
|
||||
- Enable "Websockets Support" toggle
|
||||
|
||||
2. **SSL Tab**
|
||||
- Request a new SSL certificate
|
||||
- Enable "Force SSL"
|
||||
|
||||
3. **Advanced Tab** - Paste this config for WebSocket support:
|
||||
|
||||
```nginx
|
||||
location /socket.io/ {
|
||||
proxy_pass http://192.168.1.100:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 86400s;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Updating the Deployment
|
||||
|
||||
```bash
|
||||
cd /var/www/wownerogue/app
|
||||
sudo -u wownerogue git pull
|
||||
cd src && sudo -u wownerogue npm install
|
||||
sudo -u wownerogue npm audit fix
|
||||
sudo systemctl restart wownerogue
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Multi-Instance Deployment
|
||||
|
||||
To run multiple instances (e.g., Wownero on port 3000 and Monero stagenet on port 3001):
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
/var/www/
|
||||
├── wownerogue/ # Wownero instance (port 3000)
|
||||
│ └── app/src/.env
|
||||
└── monerogue/ # Monero instance (port 3001)
|
||||
└── app/src/.env
|
||||
```
|
||||
|
||||
### Configuration Differences
|
||||
|
||||
| Setting | Wownero Instance | Monero Instance |
|
||||
|---------|------------------|-----------------|
|
||||
| `PORT` | 3000 | 3001 |
|
||||
| `CRYPTO_TYPE` | WOW | XMR |
|
||||
| `MONERO_NETWORK` | mainnet | stagenet |
|
||||
| `DB_NAME` | wownerogue | monerogue_stagenet |
|
||||
| `PRIMARY_WALLET_ENDPOINT` | http://127.0.0.1:34570 | http://127.0.0.1:38070 |
|
||||
| `PRIMARY_RPC_ENDPOINT` | http://127.0.0.1:34568 | http://127.0.0.1:38081 |
|
||||
|
||||
### Separate systemd Service
|
||||
|
||||
Create `/etc/systemd/system/monerogue.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Monerogue Game Server (Stagenet)
|
||||
After=network.target postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=monerogue
|
||||
WorkingDirectory=/var/www/monerogue/app/src
|
||||
EnvironmentFile=/var/www/monerogue/app/src/.env
|
||||
ExecStart=/usr/bin/node index.js
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Check Service Status
|
||||
|
||||
```bash
|
||||
systemctl status wownerogue
|
||||
journalctl -u wownerogue -f # Follow logs
|
||||
```
|
||||
|
||||
### Health Endpoint
|
||||
|
||||
```bash
|
||||
curl http://localhost:3000/health
|
||||
```
|
||||
|
||||
Returns server uptime, memory usage, wallet status, and balance.
|
||||
|
||||
### Admin Dashboard
|
||||
|
||||
Access `/admin.html` with your `ADMIN_API_KEY` for:
|
||||
- Wallet balance and connection status
|
||||
- Pending/failed payouts
|
||||
- Game statistics
|
||||
- User search
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Server Won't Start
|
||||
|
||||
```bash
|
||||
# Check logs for errors
|
||||
journalctl -u wownerogue -n 50
|
||||
|
||||
# Verify environment file
|
||||
sudo -u wownerogue cat /var/www/wownerogue/app/src/.env
|
||||
|
||||
# Test database connection
|
||||
psql -h localhost -U wownerogue -d wownerogue -c "SELECT 1;"
|
||||
```
|
||||
|
||||
### Wallet RPC Issues
|
||||
|
||||
```bash
|
||||
# Test wallet RPC directly
|
||||
curl -u user:password -X POST http://127.0.0.1:34570/json_rpc \
|
||||
-d '{"jsonrpc":"2.0","id":"0","method":"get_balance"}' \
|
||||
-H 'Content-Type: application/json'
|
||||
```
|
||||
|
||||
### Database Migrations
|
||||
|
||||
If migrations fail, check the `migrations` table:
|
||||
|
||||
```sql
|
||||
SELECT * FROM migrations ORDER BY id;
|
||||
```
|
||||
|
||||
Migrations are tracked by name to prevent duplicate execution.
|
||||
@@ -0,0 +1,185 @@
|
||||
# Logs and Backup Configuration
|
||||
|
||||
This document covers log management and database backup strategies for production deployment.
|
||||
|
||||
---
|
||||
|
||||
## Log Management with systemd/journald
|
||||
|
||||
When running as a systemd service, logs automatically go to journald which handles rotation. Configure retention limits as needed.
|
||||
|
||||
### Configure Journal Limits
|
||||
|
||||
Create `/etc/systemd/journald.conf.d/wownerogue.conf`:
|
||||
|
||||
```ini
|
||||
[Journal]
|
||||
# Max disk usage for all journals
|
||||
SystemMaxUse=500M
|
||||
# Max size per journal file
|
||||
SystemMaxFileSize=50M
|
||||
# Keep logs for 30 days max
|
||||
MaxRetentionSec=30day
|
||||
# Compress older entries
|
||||
Compress=yes
|
||||
```
|
||||
|
||||
Apply the configuration:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/systemd/journald.conf.d/
|
||||
sudo nano /etc/systemd/journald.conf.d/wownerogue.conf
|
||||
# paste the config above
|
||||
sudo systemctl restart systemd-journald
|
||||
```
|
||||
|
||||
### Viewing Logs
|
||||
|
||||
```bash
|
||||
# All logs for the service
|
||||
journalctl -u wownerogue
|
||||
|
||||
# Follow live (like tail -f)
|
||||
journalctl -u wownerogue -f
|
||||
|
||||
# Last 100 lines
|
||||
journalctl -u wownerogue -n 100
|
||||
|
||||
# Logs since today
|
||||
journalctl -u wownerogue --since today
|
||||
|
||||
# Logs from a specific time range
|
||||
journalctl -u wownerogue --since "2025-12-01" --until "2025-12-15"
|
||||
|
||||
# Export to file for analysis
|
||||
journalctl -u wownerogue --since "2025-12-01" > wownerogue-dec.log
|
||||
|
||||
# Show only errors
|
||||
journalctl -u wownerogue -p err
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PostgreSQL Automated Backups
|
||||
|
||||
### Backup Script
|
||||
|
||||
The backup script is located at `scripts/backup_db.sh`. It reads database credentials from environment variables (same as your `.env` file).
|
||||
|
||||
**Required environment variables:**
|
||||
- `DB_NAME` - Database name (default: `wownerogue`)
|
||||
- `DB_USER` - Database user
|
||||
- `DB_HOST` - Database host (default: `localhost`)
|
||||
- `BACKUP_DIR` - Where to store backups (default: `/var/backups/wownerogue`)
|
||||
- `RETENTION_DAYS` - How long to keep backups (default: `30`)
|
||||
|
||||
### systemd Timer (Recommended)
|
||||
|
||||
Use systemd timers for scheduled backups. Copy the service files to `/etc/systemd/system/`:
|
||||
|
||||
1. **Service file** (`wownerogue-backup.service`):
|
||||
- Located at `scripts/wownerogue-backup.service`
|
||||
- Runs the backup script with environment from your `.env` file
|
||||
|
||||
2. **Timer file** (`wownerogue-backup.timer`):
|
||||
- Located at `scripts/wownerogue-backup.timer`
|
||||
- Runs daily at 3 AM with random delay up to 15 minutes
|
||||
|
||||
### Setup Commands
|
||||
|
||||
```bash
|
||||
# Create backup directory
|
||||
sudo mkdir -p /var/backups/wownerogue
|
||||
sudo chown $(whoami):$(whoami) /var/backups/wownerogue
|
||||
|
||||
# Make backup script executable
|
||||
chmod +x scripts/backup_db.sh
|
||||
|
||||
# Copy systemd files
|
||||
sudo cp scripts/wownerogue-backup.service /etc/systemd/system/
|
||||
sudo cp scripts/wownerogue-backup.timer /etc/systemd/system/
|
||||
|
||||
# Edit the service file to point to your installation path
|
||||
sudo nano /etc/systemd/system/wownerogue-backup.service
|
||||
# Update WorkingDirectory and EnvironmentFile paths
|
||||
|
||||
# Reload systemd and enable timer
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable wownerogue-backup.timer
|
||||
sudo systemctl start wownerogue-backup.timer
|
||||
|
||||
# Verify timer is scheduled
|
||||
systemctl list-timers | grep wownerogue
|
||||
```
|
||||
|
||||
### Manual Backup
|
||||
|
||||
```bash
|
||||
# Run backup manually
|
||||
cd /path/to/wownerogue/src
|
||||
source .env
|
||||
../scripts/backup_db.sh
|
||||
|
||||
# Or via systemd
|
||||
sudo systemctl start wownerogue-backup.service
|
||||
journalctl -u wownerogue-backup.service -n 20
|
||||
```
|
||||
|
||||
### Restore from Backup
|
||||
|
||||
```bash
|
||||
# List available backups
|
||||
ls -lh /var/backups/wownerogue/
|
||||
|
||||
# Restore a specific backup (replace filename with actual backup)
|
||||
gunzip -c /var/backups/wownerogue/wownerogue_20251222_030000.sql.gz | psql -h $DB_HOST -U $DB_USER -d $DB_NAME
|
||||
|
||||
# Or with explicit values
|
||||
gunzip -c /var/backups/wownerogue/wownerogue_20251222_030000.sql.gz | psql -h localhost -U your_user -d wownerogue
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Alternative: Cron-based Backups
|
||||
|
||||
If you prefer cron over systemd timers:
|
||||
|
||||
```bash
|
||||
# Edit crontab
|
||||
crontab -e
|
||||
|
||||
# Add this line (runs daily at 3 AM)
|
||||
0 3 * * * cd /path/to/wownerogue/src && source .env && ../scripts/backup_db.sh >> /var/log/wownerogue-backup.log 2>&1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backup Verification
|
||||
|
||||
Periodically verify your backups work:
|
||||
|
||||
```bash
|
||||
# Create a test database
|
||||
createdb -h localhost -U $DB_USER wownerogue_test
|
||||
|
||||
# Restore backup to test database
|
||||
gunzip -c /var/backups/wownerogue/wownerogue_LATEST.sql.gz | psql -h localhost -U $DB_USER -d wownerogue_test
|
||||
|
||||
# Verify data
|
||||
psql -h localhost -U $DB_USER -d wownerogue_test -c "SELECT COUNT(*) FROM users;"
|
||||
|
||||
# Drop test database
|
||||
dropdb -h localhost -U $DB_USER wownerogue_test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Monitoring Backup Health
|
||||
|
||||
Add to your monitoring checklist:
|
||||
|
||||
- [ ] Check backup timer is active: `systemctl status wownerogue-backup.timer`
|
||||
- [ ] Verify recent backups exist: `ls -la /var/backups/wownerogue/ | tail -5`
|
||||
- [ ] Check backup sizes are reasonable (not 0 bytes)
|
||||
- [ ] Periodically test restore process
|
||||
- [ ] Monitor disk space: `df -h /var/backups`
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
# Wownerogue Development Todo
|
||||
|
||||
## High Priority
|
||||
- [x] **Verify Server Startup**: Server starts cleanly with `npm run dev` ✅
|
||||
- [x] **Test Payment Flow**: Fixed critical bug where payment confirmation wasn't updating DB status ✅
|
||||
- [x] **Test Payouts**: Payout flow verified with duplicate prevention and proper mode tracking ✅
|
||||
- [x] **Address Persistence**: Verify that payout addresses persist across server restarts via session tokens. ✅
|
||||
- [x] **Mixed Mode Logic**: Per-user mode determination based on credits balance ✅
|
||||
- [x] **Credits Package Bug**: Credits correctly parsed from package info on confirmation ✅
|
||||
- [x] **Stagenet Support**: Added MONERO_NETWORK config with UI warnings for non-mainnet ✅
|
||||
- [x] **Difficulty Tuning**: Configurable presets (easy/normal/hard/casino) for house edge control ✅
|
||||
- [x] **Provably Fair**: SHA-256 commitment scheme for verifiable game generation ✅
|
||||
|
||||
## Recent Fixes (Jan 2026)
|
||||
- [x] **Payment DB Status Bug**: Fixed critical issue where single_game payments weren't marked 'confirmed' in DB, causing game start to fail ✅
|
||||
- [x] **TileMap Character Error**: Fixed '●' character not in tileMap causing tile mode rendering failures ✅
|
||||
- [x] **Test Suite Fixes**: All 106 tests now pass (10 test suites) ✅
|
||||
- [x] **Credit Deduction Bug**: Fixed race condition where credits could go negative - now uses `WHERE credits >= $1` ✅
|
||||
- [x] **Payout Mode Bug**: Fixed `completeGame` using global `gameMode` instead of recorded `payment_mode` from game record ✅
|
||||
- [x] **Duplicate Payout Prevention**: Added check for existing payout before processing to prevent double-payouts ✅
|
||||
- [x] **Dead Code Cleanup**: Removed unused MoneroPayService (was never used, WalletRPCService is the actual service) ✅
|
||||
- [x] **Game Reconnection/Resume**: Added `SuspendedGameManager` to preserve and restore games when users disconnect and reconnect. Users in dungeon or awaiting payment can now resume seamlessly ✅
|
||||
|
||||
## New Features (Just Added)
|
||||
- [x] **Chat History Persistence**: `ChatHistoryManager` stores messages in PostgreSQL with 30-day retention ✅
|
||||
- [x] **Chat History on Connect**: New users receive last 50 messages on connect via `chat_history` event ✅
|
||||
- [x] **Spectator System**: Full spectator mode with `SpectatorManager` for watching live games ✅
|
||||
- [x] **Active Games List**: Real-time game list with pagination, sorting, and auto-refresh ✅
|
||||
- [x] **Spectate UI**: "Watch Games" button, live game panel, and spectator controls ✅
|
||||
- [x] **Spectator Broadcasts**: Game updates broadcast to spectators via Socket.IO rooms ✅
|
||||
- [x] **Help Modal**: Added instructions modal with game rules, controls, and payment mode info ✅
|
||||
- [x] **Dynamic Treasure Icon**: Treasure tile now shows $W (Wownero) or $M (Monero) based on crypto type ✅
|
||||
- [x] **Address Status Indicator**: Payout address button shows warning when no address is set ✅
|
||||
|
||||
## User Feedback (Beta Tester - Dec 2025)
|
||||
- [ ] **History Panel Bug**: User reported payout not showing in History after winning with treasure (needs investigation - may be timing/status issue with "confirmed" vs "pending" payouts)
|
||||
- [x] **Early Dungeon Entry**: Allow credits/free mode users to enter dungeon immediately without waiting for next block (risky - they die if block found before escape). Toggleable via config. ✅
|
||||
|
||||
## Improvements / Refactoring
|
||||
- [x] **Error Handling**: Extended `normalizeError` to queueHandler, queueManager, sessionManager ✅
|
||||
- [x] **Configuration Persistence**: Added `configPersistence.js` for hot-reloadable DB-backed config ✅
|
||||
- [x] **Monitoring Dashboard**: Created `/admin.html` with live metrics (games, queue, memory, wallet) ✅
|
||||
- [x] **Frontend Cleanup**: Removed rot.js (using minified), game1.mid (unused), .DS_Store, moved tiles.xcf ✅
|
||||
- [x] **Provably Fair UI**: Hash commitment shown at game start, seed revealed with verification link at game end ✅
|
||||
- [x] **Verification Endpoint**: `/verify/:gameId` HTML page + `/api/verify` JSON endpoint for public verification ✅
|
||||
|
||||
## Documentation
|
||||
- [x] **API Documentation**: README updated with accurate API surface including health check and Socket.IO events ✅
|
||||
- [x] **Session Persistence**: README documents session token behavior and localStorage requirements ✅
|
||||
- [x] **Difficulty System**: README documents difficulty presets and house edge tuning ✅
|
||||
- [x] **Provably Fair**: README documents cryptographic verification system ✅
|
||||
- [x] **Deployment Guide**: README includes production deployment with Nginx/Caddy configs and systemd ✅
|
||||
|
||||
## Pre-Beta Checklist
|
||||
- [x] All 106 tests pass (10 test suites) ✅
|
||||
- [x] Health check endpoint available at `/health` ✅
|
||||
- [x] REST endpoints implemented: `/api/user/:socketId/credits`, `/api/user/:socketId/mode`, `/api/user/:socketId/address` ✅
|
||||
- [x] Payout eligibility shown per payment mode in UI ✅
|
||||
- [x] Session persistence tooltip and localStorage warning added ✅
|
||||
- [x] Stagenet/testnet warning banner for Monero non-mainnet ✅
|
||||
- [x] Chat history persisted and sent to new users ✅
|
||||
- [x] Spectator system functional with live game viewing ✅
|
||||
- [ ] **TLS/HTTPS**: Configure reverse proxy (Nginx/Caddy) with SSL certificates before exposing to real users.
|
||||
- [x] **Database Backups**: `scripts/backup_db.sh` + systemd timer for daily backups with 30-day retention (see `LOGS_AND_BACKUP.md`) ✅
|
||||
- [ ] **Manual Integration Test**: Run full payment flow with real `wownero-wallet-rpc` (not mocked).
|
||||
- [x] **Rate Limit Tuning**: Current defaults (60 games/hour, 100 payouts/day) suitable for launch ✅
|
||||
- [x] **Log Rotation**: Using systemd journald with configurable retention (see `LOGS_AND_BACKUP.md`) ✅
|
||||
|
||||
## Security Audit Fixes (Jan 2026)
|
||||
- [x] **XSS Vulnerability**: Complete HTML entity escaping in chat handler (`&`, `<`, `>`, `"`, `'`)
|
||||
- [x] **tx_hash Idempotency**: UNIQUE partial indexes on payments/payouts tables (migration 008)
|
||||
- [x] **Timing-Safe Auth**: Admin API uses `crypto.timingSafeEqual()` for key comparison
|
||||
- [x] **Transactional Payouts**: Payout flow creates pending record first, updates atomically
|
||||
- [x] **Payout Retry Service**: Auto-retries failed payouts (max 3 attempts, 5-min interval)
|
||||
- [x] **Address Validation**: `validateAddress()` called before every payout attempt
|
||||
- [x] **Transaction Status Check**: `checkTransactionStatus()` verifies blockchain before retry
|
||||
|
||||
## Smirk Wallet Integration (Jan 2026)
|
||||
- [x] **Database Schema**: `smirk_public_key` column, `smirk_challenges` table (migration 009)
|
||||
- [x] **Auth Endpoints**: `/api/auth/smirk/challenge`, `/verify`, `/status`
|
||||
- [x] **Frontend Module**: `smirkAuth.js` with extension detection and login flow
|
||||
- [x] **Address Modal**: Shows Smirk connect button or install link
|
||||
|
||||
## Admin Dashboard (Jan 2026)
|
||||
- [x] **Alert Service**: Email alerts via Resend for low balance, disconnects, failed payouts
|
||||
- [x] **Stats Endpoints**: `/api/admin/stats/overview`, `/payouts`, `/games`, `/users`
|
||||
- [x] **Admin UI**: Full dashboard at `/admin.html` with charts and tables
|
||||
- [x] **Payout Retry**: Manual retry button in admin dashboard
|
||||
|
||||
## Pre-Production Testing Checklist
|
||||
|
||||
### Security Verification
|
||||
- [ ] Chat XSS: `<script>` and `"onclick=` render as plain text
|
||||
- [ ] Duplicate tx_hash insertion fails with constraint error
|
||||
- [ ] Payout creates pending record before RPC call
|
||||
- [ ] Failed payouts have records for retry
|
||||
- [ ] Retry service processes failed payouts (check logs)
|
||||
|
||||
### Smirk Integration Verification
|
||||
- [ ] "Connect Smirk" button appears when extension installed
|
||||
- [ ] "Get Smirk Wallet" link appears when extension NOT installed
|
||||
- [ ] Challenge generated and stored in DB
|
||||
- [ ] Signature verification links public key to user
|
||||
- [ ] Payout address auto-populated from wallet
|
||||
- [ ] Anonymous sessions still work (backwards compatible)
|
||||
|
||||
### End-to-End Testing
|
||||
- [ ] Play full game with Smirk login
|
||||
- [ ] Win and receive payout to Smirk address
|
||||
- [ ] Verify payout recorded in transaction history
|
||||
- [ ] Manual integration test with real wallet-rpc
|
||||
|
||||
---
|
||||
|
||||
## Known Issues / Future Improvements
|
||||
|
||||
### Backend
|
||||
- [x] **Database Transactions**: `withTransaction()` helper for atomic financial operations ✅
|
||||
- [ ] **Payment Idempotency**: Replace in-memory Set with database-backed idempotency keys for payment confirmation
|
||||
- [x] **Payout Retry Queue**: Automatic retry mechanism via `payoutRetryService.js` ✅
|
||||
- [x] **Address Validation**: Wallet RPC `validate_address` method ✅
|
||||
- [ ] **Redis Rate Limiting**: Replace in-memory rate limiter with Redis for persistence across restarts
|
||||
|
||||
### Frontend
|
||||
- [ ] **Socket Reconnection**: Add `reconnect` and `disconnect` handlers to restore state after connection loss
|
||||
- [ ] **Payment Timeout UI**: Show countdown timer for payment expiration, auto-clean expired payment UI
|
||||
- [ ] **Event Cleanup**: Add proper cleanup for event listeners when modules are re-initialized
|
||||
- [ ] **Connection Status Indicator**: Show real-time socket connection state in UI
|
||||
Reference in New Issue
Block a user