soulsync/tests
Broque Thomas 0f24739e27 Socket.IO CORS: polish — match engineio exactly, bound dedup, validate URLs
Self-review pass on the security fix uncovered five issues, all fixed
here:

1. will_reject scheme handling. Engineio compares full {scheme}://{host}
   strings, not just hostnames. A TLS-terminating proxy can leave the
   backend seeing http while the browser's Origin is https — engineio
   rejects, but the original predictor said "allow" → no helpful log
   line. Added request_scheme + forwarded_proto params, build full
   candidate strings to match engineio.

2. EITHER-forwarded-header rule. Engineio adds the forwarded candidate
   when EITHER X-Forwarded-Proto OR X-Forwarded-Host is present (it
   falls back to HTTP_HOST for the missing one). The original predictor
   only added it when forwarded_host was set — false negative for
   misconfigs sending only X-Forwarded-Proto. Now mirrors engineio.

3. will_reject incorrectly rejected missing-Origin requests. Engineio
   (server.py:207: `if origin: validate`) skips CORS validation when
   no Origin header is sent — non-browser clients (curl etc.) are
   intentionally permitted. The original code rejected them. Test was
   asserting the wrong behavior. Both fixed.

4. RejectionLogger had unbounded dedup set growth. A hostile actor
   opening connections from many distinct fake origins would fill
   memory unboundedly. Capped at 100 unique origins (configurable);
   when cap hit, one overflow notice is emitted and further rejections
   are silently dropped until restart.

5. Lock pattern: the overflow log path called logger.warning() while
   holding the dedup lock, inconsistent with the normal path. Fixed
   to pick the message under the lock and log after release. Critical
   section is now minimal and uniform.

Plus polish:
- Stale module docstring fixed (said "empty list" instead of "None").
- settings.js validates each cors_origins line against a URL regex on
  save; toasts a one-shot warning if entries are malformed (resolver
  silently filters them, but user gets feedback now).
- web_server.py wiring passes request.scheme + X-Forwarded-Proto so
  the predictor has full proxy info.

Tests:
- 51 unit tests in tests/test_socketio_cors.py (was 45). New cases:
  * scheme comparison (5 cases including TLS-terminating proxies)
  * forwarded_proto-alone misconfig
  * missing-origin matches engineio (was asserting wrong behavior)
  * dedup cap with overflow + reset
  * default cap is reasonable (uses public DEFAULT_DEDUP_CAP constant)

Engineio behavior independently verified by reading engineio/server.py
and engineio/base_server.py source. Predictor mirrors both files.

604 tests pass.
2026-04-26 17:32:22 -07:00
..
conftest.py Remove emojis from all Python log and print statements 2026-04-11 21:11:02 -07:00
test_acoustid_scanner.py Fix null-pointer error in acoustid_scanner 2026-04-17 19:17:24 +03:00
test_album_completeness_job.py Fix Album Completeness job reporting zero findings for every album 2026-04-24 12:39:41 -07:00
test_artist_source_detail.py Extract _build_source_only_artist_detail into core/artist_source_detail.py 2026-04-23 08:09:29 -07:00
test_artist_source_lookup.py Make artist_name Optional in find_library_artist_for_source 2026-04-22 22:15:03 -07:00
test_auth_usage_throttle.py test: auth last_used_at write throttle 2026-04-19 15:22:24 -07:00
test_content_filter_regex.py Fix watchlist content filters: live false positives + auto-scan bypass 2026-04-21 19:16:25 -07:00
test_dashboard_events.py Realign test file names 2026-04-17 21:25:01 +03:00
test_discogs_track_count.py Discogs: count rows with empty type_ as real tracks too 2026-04-25 08:27:44 -07:00
test_downloads_pagination.py test: downloads endpoint pagination and filtering 2026-04-19 15:22:25 -07:00
test_enrichment_events.py Realign test file names 2026-04-17 21:25:01 +03:00
test_library_reorganize.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_library_reorganize_orchestrator.py Reorganize: fix moved-count + status/total UX issues from PR #377 review 2026-04-25 09:07:44 -07:00
test_listening_stats_batch_queries.py test: listening stats worker batched query paths 2026-04-19 15:22:25 -07:00
test_metadata_cache_batch_lookup.py test: metadata cache batch entity lookups 2026-04-19 15:22:24 -07:00
test_metadata_gap_filler.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_metadata_service_album_tracks.py Refactor album track lookup to use source priority 2026-04-20 21:29:46 +03:00
test_metadata_service_artist_image.py Fix test-order-dependent failures in new metadata_service tests 2026-04-21 11:39:56 -07:00
test_metadata_service_cache.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_metadata_service_discography.py Add regression tests for source-artist lookup + dedup_variants flag 2026-04-22 21:14:11 -07:00
test_metadata_service_musicmap.py Fix test-order-dependent failures in new metadata_service tests 2026-04-21 11:39:56 -07:00
test_missing_cover_art.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_musicbrainz_search.py MusicBrainz: Dedupe same-named homonyms in artist search results 2026-04-24 10:27:45 -07:00
test_reorganize_db_methods.py Reorganize queue: race + dedupe fixes from kettui review 2026-04-26 08:40:24 -07:00
test_reorganize_queue.py Reorganize queue: race + dedupe fixes from kettui review 2026-04-26 08:40:24 -07:00
test_reorganize_runner.py Library reorganize: FIFO queue with live status panel 2026-04-25 18:01:32 -07:00
test_repair_worker_album_fill.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_request_cleanup_timer.py test: api/request periodic cleanup timer 2026-04-19 15:22:25 -07:00
test_script_split_integrity.py Unify artist detail: route source artists to standalone page, retire inline Artists page 2026-04-22 17:00:52 -07:00
test_socketio_cors.py Socket.IO CORS: polish — match engineio exactly, bound dedup, validate URLs 2026-04-26 17:32:22 -07:00
test_spa_deep_linking.py Rename Search page id from 'downloads' to 'search', bump to 2.43 2026-04-22 13:22:49 -07:00
test_sync_discovery_scan_events.py Realign test file names 2026-04-17 21:25:01 +03:00
test_tidal_search_shortening.py Reject Tidal streams that silently downgrade from the requested quality 2026-04-24 13:12:30 -07:00
test_tidal_stream_tier_verification.py Reject Tidal streams that silently downgrade from the requested quality 2026-04-24 13:12:30 -07:00
test_tool_progress_events.py Realign test file names 2026-04-17 21:25:01 +03:00
test_track_number_repair.py Fix CI test failures from incomplete dummy config and encoding 2026-04-19 13:04:55 -07:00
test_track_search_single_query.py test: api_search_tracks single-query track search 2026-04-19 15:22:24 -07:00
test_unknown_artist_fixer.py Fix test using old deezer_track_id column name 2026-04-20 21:11:45 -07:00
test_watchlist_scanner_scan.py Fix date-dependent watchlist scanner tests failing on CI 2026-04-22 20:56:10 -07:00
test_websocket_client_transport.py Repoint websocket transport test to core.js after split 2026-04-22 11:30:39 -07:00
test_websocket_infrastructure.py Realign test file names 2026-04-17 21:25:01 +03:00
test_wishlist_pagination.py test: wishlist SQL pagination and category filter 2026-04-19 15:22:24 -07:00
test_worker_existing_id_marks_matched.py test: enrichment worker re-processing fix and migration backfill 2026-04-19 15:22:24 -07:00
test_worker_utils_album_track_count.py Fix Album Completeness job reporting zero findings for every album 2026-04-24 12:39:41 -07:00