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:
jwinterm
2026-01-31 20:21:28 -05:00
parent 7573c300cd
commit a81c19c936
11 changed files with 1846 additions and 548 deletions
+402
View File
@@ -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.
+185
View File
@@ -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
View File
@@ -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