Two pieces, both user-directed, completing what 7341ca0 only configured:
1. WalletConnect.vue: Cashu token paste is now the PRIMARY entry-fee path
(submitCashuToken() already existed in useWallet.ts but was never called
from any UI — added the missing wiring). Lightning/NWC is now secondary,
behind an explicit "or connect a Lightning wallet instead" toggle.
Emits `cashu-paid` with the redeemed paymentId; JoinBoutPage.vue's
fightRanked() uses it directly instead of calling payEntryFee()
(Lightning-only) when present — no duplicate invoice/charge.
2. queue.ts's POST /join-ranked/:botId required a nostr pubkey for
ownership verification, full stop. Confirmed live during testing:
anonymous poll-mode bots (the primary registration path for AI agents
per BOTFIGHTS.md) have publicKey: null — staked fights were completely
unusable for that entire audience, silently. Now accepts EITHER a
pubkey OR Authorization: Bot <id>:<secret> (same bot-auth every other
anonymous-bot endpoint already uses) as proof of ownership.
Verified: full server typecheck clean; payments.test.ts (23) and
queue.test.ts (8) unchanged and passing; full frontend suite (101 tests,
13 files) passing, including useWallet.test.ts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add sanitizeError() helper that strips file paths, stack traces, SQLite
errors, and system errors from messages before returning them to clients.
Applied to all route-level catch blocks in payments, queue, fights, and
admin routes. Includes 12 tests for the sanitizer and static analysis
test verifying no route files leak raw err.message.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create server/src/lib/validators.ts with reusable schemas for all API
inputs (auth, fights, bets, payments, tournaments, queue, docs).
Import and use in all route handlers, replacing inline validation.
Add formatZodError helper for user-friendly error messages.
77 test cases in validators.test.ts cover valid, invalid, boundary,
and attack inputs (SQL injection, XSS, prototype pollution).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Track active fight IDs per bot in orchestrator (Set → Map)
- Return fightId in "already in fight" error responses (409)
- Frontend shows "REJOIN FIGHT" link instead of generic error
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add /api/payments router (connect-wallet, wallet-status, create-invoice,
check, submit-cashu, winnings, claim, disconnect-wallet). Add ranked
queue endpoints to /api/queue. Mount payments router in app.ts with
orphan payment recovery on startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>