Commit Graph
332 Commits
Author SHA1 Message Date
DorianandClaude Opus 4.6 5799ff60d3 test: auth & registration edge cases — unicode names, shared URLs
8 new tests: unicode/emoji/diacritics in bot names rejected, special
chars rejected, same webhook URL allowed, pubkey hex validation,
missing required fields rejected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:11:12 +00:00
DorianandClaude Opus 4.6 2dd09fb954 test: add simultaneous KO and negative ELO edge cases
Adds tests for both-bots-at-0-HP tiebreaker asymmetry (botA penalized
first) and verifies ELO can go negative when 0-rated bot loses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:10:49 +00:00
DorianandClaude Opus 4.6 ffad432e5b test: 10-round double timeout simulation — draw, equal HP, no loops
Simulates both bots timing out every round for 10 rounds. Verifies
zero damage per round, HP unchanged at 200, draw outcome.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:10:15 +00:00
DorianandClaude Opus 4.6 9346b6b260 test: add ELO extremes and challenge rotation edge cases
ELO: 0v0, 9999v1 upset, 9999v1 expected, NaN/Infinity check.
Challenge rotation: 16 unique types, reset after exhaustion,
filter exclusion works. Total: 24 edge case tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:09:36 +00:00
DorianandClaude Opus 4.6 135bf644fa test: add 17 fight engine edge case tests
Covers: identical answers (speed tiebreaker), 2000-char answers,
null/empty/whitespace answers, unicode/emoji, HTTP errors, double
timeout/error, both-wrong draws, correct-beats-wrong regardless of
speed, speed advantage margin, arena modifier damage, combo stacks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:07:20 +00:00
DorianandClaude Opus 4.6 08437cdf5c test: add static analysis tests for memory leak destroy contracts
Verifies FightScene.destroy(), FightViewer.vue onUnmounted, and audio
module cleanup invariants via source-code scanning — ensures future
changes don't silently break resource cleanup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:06:42 +00:00
DorianandClaude Opus 4.6 854b1cd1df fix: prevent memory leaks on consecutive fight replays
- FightViewer: store canvas event handlers and remove them before
  replacing canvas elements, preventing detached DOM/closure leaks
- FightViewer: clean up canvas listeners on unmount
- tts.ts: clear _staticLoading dedup map after precache completes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:04:03 +00:00
DorianandClaude Opus 4.6 aa263ec8ae test: verify TTS cache uses LRU eviction, not FIFO (BUG-8)
Cache already uses lastAccess timestamps and LRU eviction. Added
test-only exports and 6 tests verifying: timestamp tracking, access
updates, LRU eviction of oldest entry, recently accessed entries
survive eviction, and eviction is not FIFO.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:00:59 +00:00
DorianandClaude Opus 4.6 8afdc2d898 fix: replace raw setTimeout with tracked timers in game audio (BUG-4)
Added audioTimeout() to audio/context.ts — tracked timer set cleared on
scene destroy via clearAllAudioTimers(). Converted 20 sfx.ts + 3 voice.ts
raw setTimeout calls to audioTimeout. Converted FightScene playEntrance
timeout to trackedTimeout. Remaining setTimeout in tts.ts worker layer
and music.ts (already tracked via setMusicTimeout) are self-managing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:59:16 +00:00
DorianandClaude Opus 4.6 3c5c6c6b95 fix: improve graceful shutdown — stop loop, drain fights, clear all state
Shutdown now: stops background fight loop, waits up to 15s for active
fights to drain (polling every 500ms), clears human + poll pending
challenges, clears bet escrow. Added clearEscrow() to betting.ts and
5 tests verifying cleanup functions and correct shutdown order.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:54:10 +00:00
DorianandClaude Opus 4.6 4134a27ea6 feat: improve graceful shutdown — stop bg loop, drain fights, clear state
Shutdown now: 1) stops background fight loop, 2) waits up to 15s for
active fights to finish, 3) cancels pending human + poll challenges,
4) clears bet escrow. Added clearEscrow() to betting.ts. Tests verify
each cleanup function and shutdown sequence ordering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:53:39 +00:00
DorianandClaude Opus 4.6 023a1a58a9 test: verify orphaned fight cleanup cancels stale live fights
Add 3 tests for cleanupOrphanedFights: verifies db.update sets
status='cancelled' with endedAt on stale live fights, returns 0
on success, and propagates DB errors correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:49:27 +00:00
DorianandClaude Opus 4.6 9b0d251d1c fix: sanitize error responses to prevent internal detail leakage
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>
2026-03-13 09:46:38 +00:00
DorianandClaude Opus 4.6 1b1f9eb2d7 chore: add composite (is_active, elo_rating) index for leaderboard queries
All individual indexes from plan already existed. Added missing composite
index that covers WHERE is_active=1 ORDER BY elo_rating DESC pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:41:30 +00:00
DorianandClaude Opus 4.6 d3bb00c5c8 feat: add per-phase timing instrumentation to fight orchestration
Log timing for each round phase: webhook calls, scoring, DB operations,
and total round time. Also log finalize transaction time. Uses logger
with 'perf' category for easy filtering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:35:42 +00:00
DorianandClaude Opus 4.6 dc9884e27e test: verify wallet disconnect wipes connection data from DB
Add test confirming disconnect-wallet deletes walletConnections rows
and sets hasWallet=false on the bot record.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:33:50 +00:00
DorianandClaude Opus 4.6 b1e86843a7 test: audit AES-256-GCM crypto with 7 test cases
Verify random IV (same plaintext encrypts differently), ciphertext
format (iv:authTag:encrypted), auth tag tamper detection, encrypted
data tamper detection, empty string handling, and unicode support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:33:08 +00:00
DorianandClaude Opus 4.6 c5744f5984 test: pentest payment edge cases with 10 attack vector tests
Cover amount=0, over-max (999999999), zap non-winner, zap unfinished
fight, invalid wallet method, empty cashu token, claim nonexistent
payment, confirm already-confirmed, confirm outbound payment, claim
payment with no token.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:32:19 +00:00
DorianandClaude Opus 4.6 2fea2bf8c9 test: verify error responses never leak stack traces or file paths
Add tests confirming production error handler sanitizes all internal
errors (ENOENT, stack traces, file paths). Add static analysis test
verifying no route file passes err.stack to c.json() responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:30:55 +00:00
DorianandClaude Opus 4.6 21bb46c1b0 test: verify admin endpoints require creator pubkey on all routes
Test all 7 admin endpoints (stats, bots, deactivate, activate,
reset-elo, fights, backup) reject non-creator pubkeys and missing
pubkeys with 403. Verifies global middleware guard works correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:29:08 +00:00
DorianandClaude Opus 4.6 d4c51f0aac fix: tighten auth rate limits to 10/min and add rate limit tests
Reduce login and nostr/session rate limits from 30 to 10 requests per
minute per IP to prevent brute-force attacks. Add tests verifying 429
response after exceeding the limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:28:38 +00:00
DorianandClaude Opus 4.6 9de47fd760 test: add timing attack tests for bot-auth and use timingSafeEqual
Replace manual XOR loop with Node's native crypto.timingSafeEqual for
constant-time secret comparison. Add tests verifying identical error
messages for wrong secrets and <1ms response time variance across 100
requests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:26:39 +00:00
DorianandClaude Opus 4.6 5bf557ba6a fix: only trust proxy headers in rate-limit when TRUSTED_PROXY is set
X-Forwarded-For, X-Real-IP, and CF-Connecting-IP headers were
blindly trusted, allowing attackers to bypass rate limiting by
spoofing different IPs. Now only trusted when TRUSTED_PROXY env
var is configured. Falls back to Node.js socket remoteAddress.

Add tests verifying proxy headers are ignored without TRUSTED_PROXY
and respected when it is set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:23:10 +00:00
DorianandClaude Opus 4.6 0131949643 fix: harden SSRF protection and add comprehensive tests
Fix gaps in isAllowedWebhookUrl: IPv6 bracket stripping for [::1],
[fe80::], [::ffff:7f00:1]; block 0.0.0.0 and [::] (IPv6 all-zeros);
handle URL-parser normalized ::ffff:7fxx IPv6-mapped localhost.

Add 20 SSRF test cases covering: file://, gopher://, data: schemes,
localhost, 127.0.0.1, 10.x, 172.16-31.x, 192.168.x, IPv6 ::1,
fe80::, fc00::/fd00::, octal/decimal IP bypass, metadata IP
169.254.169.254, .localhost TLD, overly long URLs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:21:16 +00:00
DorianandClaude Opus 4.6 2051a95e13 refactor: add centralized Zod validators for all API inputs
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>
2026-03-13 09:16:04 +00:00
DorianandClaude Opus 4.6 55d0f84251 chore: pin all dependency versions for reproducible builds
Remove ^ prefix from all 33 dependencies across root, server, and
frontend package.json files. Lockfile regenerated and verified with
pnpm install --frozen-lockfile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 06:21:16 +00:00
DorianandClaude Opus 4.6 e2dc2bbd70 feat: add eslint-plugin-security rules for static analysis
Adds 12 security-focused ESLint rules (unsafe-regex, eval, timing
attacks, child-process, bidi-characters, etc). One legitimate
non-literal RegExp in answers.ts suppressed with inline comment.
CI already runs pnpm lint + pnpm audit for SAST coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:26:10 +00:00
DorianandClaude Opus 4.6 abc081487c fix: pass archetype/customization to human morph sprite generation (BUG-10)
Human morph sprites were generated without archetype and customization
params, causing fallback to generic sprites instead of the bot's actual
appearance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:23:53 +00:00
DorianandClaude Opus 4.6 7698d560d6 fix: webhook verify shows loading spinner and better error on failure
Added isVerifyingWebhook state with spinner and disabled button during
webhook test. Improved error message to guide user on retry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:20:14 +00:00
DorianandClaude Opus 4.6 642da1e477 fix: polling backoff escalates on errors — 1.5s → 3s → 6s → 8s max
Changed from fixed 1.5s setInterval to recursive setTimeout with
exponential backoff on consecutive errors. Resets to 1.5s on success.
Added 2 tests verifying backoff escalation and reset behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:18:00 +00:00
DorianandClaude Opus 4.6 5bc8932d25 test: E2E specs for signup, fight replay, and leaderboard flows
Bot registration (3 tests), human registration (1 test), fight replay
(2 tests for JS error checking), and leaderboard (3 tests for rendering).
All use Playwright with text-based selectors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:15:46 +00:00
DorianandClaude Opus 4.6 a7520be0e7 test: add Playwright E2E infrastructure with smoke test
Set up Playwright with Chromium, dev server auto-start, test helpers
for seeding bots and programmatic auth. Added smoke spec that verifies
homepage and leaderboard load without crashes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:14:15 +00:00
DorianandClaude Opus 4.6 5e40221a2f test: SSE, polling, human, and concurrent fight integration tests
14 integration tests covering full fight lifecycle with real in-memory
DB: SSE event ordering, polling bot challenge/response flow, human
player response submission, and 3 concurrent fights without interference.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:10:27 +00:00
DorianandClaude Opus 4.6 41c66d7732 test: full fight flow integration test with real in-memory DB
8 tests covering: complete fight lifecycle, HP progression, ELO
updates, concurrent fight prevention, round data validity, ELO
conservation, status transitions, and win streak tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 05:00:25 +00:00
DorianandClaude Opus 4.6 fc00490d61 test: speed meta analysis — 50ms gap wins 95.4% when both correct
Critical finding: when all bots answer correctly, even a 50ms speed
advantage wins 95.4% of fights. At 100ms+ gap it's 100% deterministic.
ELO separation reaches 450+ after just 50 fights. Speed completely
dominates the "all correct" meta.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:56:01 +00:00
DorianandClaude Opus 4.6 9c55850b70 test: tier balance analysis — system well-balanced across all tiers
Same-tier: ~50/50 win rates. Adjacent tiers: 70-93% higher-tier wins.
2-tier gap: 87-99% higher wins. K=32 ELO factor appropriate.
Legend vs Platinum: 99% win rate confirms clear skill separation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:54:37 +00:00
DorianandClaude Opus 4.6 929758ed1b test: combo snowball analysis — 60.4% rate, under 70% threshold
Simulated 1000 fights with 80% accuracy and equal speed. First-to-lead
wins 60.4% of decided fights, confirming combo system is balanced.
No decay or comeback mechanics needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:50:52 +00:00
DorianandClaude Opus 4.6 9ad8f1f1eb fix: both-wrong partial credit + tiebreaker
When both bots answer wrong, the one with higher checkAnswer confidence
(closer to correct) gets +1 point advantage. Rewards trying over
timing out. Equally wrong remains a pure draw.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:47:04 +00:00
DorianandClaude Opus 4.6 c6c792dd9e feat: add answer confidence differential as scoring factor
When both bots are correct, the one with higher checkAnswer confidence
(exact match 1.0 vs fuzzy match 0.8) gets up to +1.0 bonus points.
This rewards precise answers over approximate ones, adding another
competitive dimension beyond pure speed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:45:53 +00:00
DorianandClaude Opus 4.6 cb8a45cfb3 fix: lower critical hit threshold from 4 to 3
Both-correct fights could almost never produce critical hits because
max margin at typical speed differences was ~2.2, far below threshold
of 4. Lowering to 3 yields ~15% critical hit rate (target 10-20%),
making speed differences produce more exciting fight dynamics.

Research findings: simulated 1000 fights with both bots answering
correctly. Critical rate went from 0% to 15.3% with new threshold.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:44:29 +00:00
DorianandClaude Opus 4.6 0f8057f6e0 feat: add 10 sophisticated trap_card injection attempts
Multi-turn simulation, authority impersonation, encoding tricks
(Base64, ROT13), fake JSON system prompts, red team framing,
reward manipulation, inverted instruction logic. All difficulty: hard.
Zero audit failures after addition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:43:01 +00:00
DorianandClaude Opus 4.6 631ace3727 feat: add 15 genuinely hard prompts for trivial challenge types
- speed_blitz: genesis block nonce, embedded headline, first halving
  block height, first pizza transaction value, OP_RETURN payload size
- math_blitz: difficulty adjustment period, sum formula, cross product
  magnitude, log2 calculation, secp256k1 field size
- animal_kingdom: octopus hearts, hummingbird flight, shark bones,
  giraffe blood pressure, cow stomach count
All tagged difficulty: 'hard' for round 5+ difficulty filtering

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:41:47 +00:00
DorianandClaude Opus 4.6 6c6981bea8 test: difficulty distribution audit + roundToDifficulty tests
- Test roundToDifficulty: rounds 1-2 easy, 3-4 medium, 5+ hard
- Test pickChallenge difficulty filtering works with round numbers
- Audit prompt difficulty tags across all 16 challenge types
- 8 types lack hard prompts, 3 lack medium prompts
- 82.7% of prompts are untagged (no difficulty attribute)
- Report written to loop/difficulty-distribution.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:39:33 +00:00
DorianandClaude Opus 4.6 ab1fa6e302 test: scoring competitiveness analysis — speed, accuracy, duration
Simulated 1000+ fights with controlled conditions:
- Speed dominance: faster bot (1.0s) wins 100% vs slower (1.5s)
- Accuracy impact: 90% correct wins 84% vs 70% correct at equal speed
- Both-correct max margin: 4.30 at extreme speed diff, barely crosses
  critical hit threshold (4)
- Fight duration: avg 11.2 rounds equal speed, 7.4 when speed diff

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:38:31 +00:00
DorianandClaude Opus 4.6 4d6e50d988 fix: checkAnswer best-match + decimal preservation + prompt data fixes
- checkAnswer now returns highest score across all accepted answers
  instead of first match, fixing 95 false-low-confidence results
- Skip string containment for purely numeric strings to prevent
  false positives like "1000" matching inside "10000"
- Preserve decimal points in normalize() (42.0 no longer becomes 420)
- Use word-boundary regex for number matching in responses
- Fix 47 wrong choices scoring too high (comma-formatted numbers,
  verbose choices matching terse answers)
- Fix 17 prompts where no choice matched any accepted answer
- Challenge audit now reports zero failures across all 1472 prompts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:35:54 +00:00
DorianandClaude Opus 4.6 6314861513 test: challenge difficulty + ambiguous prompts audits
Run heuristic LLM difficulty classification on all 1472 prompts:
- 43.6% TRIVIAL, 27.9% MODERATE, 21.4% HARD, 7.1% TRICK
- Hypothesis "80%+ TRIVIAL" rejected — distribution more varied

Ambiguous prompts audit found 517 issues:
- 22 rejected alternatives (single-char answers fail with prefixes)
- 368 substring conflicts between accepted answers
- 127 first-match-not-best scoring issues

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 04:07:29 +00:00
DorianandClaude Opus 4.6 b8acc1c95b test: comprehensive challenge audit — 1472 prompts, 176 issues found
Audit covers all factual prompts through checkAnswer. Findings:
- 95 low-confidence correct answers (substring collision at 0.8)
- 64 false-positive wrong choices (normalization strips commas)
- 17 choices missing correct answer (paraphrasing mismatch)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:16:49 +00:00
DorianandClaude Opus 4.6 39b8504157 test: add checkAnswer edge case tests with findings (15 cases)
Documents: unicode accent stripping not supported, 3-char reverse
containment false positives, first-match-not-best-match ordering,
yes/true equivalence in boolean checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:12:49 +00:00
DorianandClaude Opus 4.6 8b72bef22e fix: query all 3 Nostr relays in parallel, pick latest profile (BUG-F8)
fetchNostrProfile now uses Promise.allSettled to query all relays
concurrently. Aggregates results with latest-created_at-wins strategy
instead of stopping at the first relay that responds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:10:11 +00:00
DorianandClaude Opus 4.6 c288b23c13 fix: persist autoRestoreRan on globalThis to survive Vite HMR (BUG-F7)
Module re-evaluation during HMR reset autoRestoreRan to false, causing
duplicate auth-restore API calls. Now persists flag on globalThis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:09:20 +00:00