mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-07-23 05:11:34 +00:00
|
Some checks are pending
ship-ci / ci (push) Waiting to run
* feat(career): extract the whole setlist before the gig starts
A feedpak is a zip, and the first play of one pays for its extraction into
sloppak_cache. Inside a set that cost landed BETWEEN songs: the player finished
a number and then sat there waiting for the next one to unpack, mid-gig.
A setlist is a known list up front, so unpack it all while the poster is still on
screen. New POST /gigs/prepare walks the set through resolve_source_dir; the
poster's Play button shows "Preparing set…" while it runs.
Best-effort by design, at every level:
- a corrupt pak in the set does not sink the prepare (it is reported in
`failed`; the play itself surfaces the error exactly as it does outside a
gig — slow beats blocked)
- a host without the library resolvers degrades to a no-op rather than 500
- a failed request just falls through to the old lazy extraction
Ordering matters and is pinned: the set is unpacked BEFORE the stage is borrowed
(venue/viz overwritten) and before the queue starts, so a proposal cancelled
while unpacking leaves nothing half-applied to unwind.
Tests unpack REAL zips rather than mocking the extractor: every song of the set
lands on disk before the first note, a re-prepare does not duplicate the unpack,
one bad pak still leaves the good one prepared, and no-library / empty-setlist
degrade cleanly. 18/18.
NB the other half of the gig report — the per-song results popup interrupting
the set (and worse, claimAutoExit'ing so the queue would not advance until it was
dismissed) — is fixed in the note_detect plugin repo, which is not part of this
checkout.
* fix(career): bound the prepare request; validate the setlist (PR #971 review)
Both CodeRabbit findings were right.
1. A HUNG PREPARE COULD BLOCK THE GIG FOREVER.
`await fetch(...)` only rejects on a network ERROR. A server that accepts the
connection and then never answers hangs indefinitely — and the gig would never
start. That makes this optimisation the exact thing the PR promises it can
never be: the reason you cannot play.
The request is now bounded by an AbortController (PREPARE_TIMEOUT_MS, generous
because unpacking a setlist is real work — but a CEILING, not a wait). Past it
we start the gig and let the first play extract lazily, as it always did. The
Play button is restored in a `finally`, so a timeout cannot strand the poster
on "Preparing set…" with Play disabled — which would have been the same bug
wearing a different hat.
2. THE `songs` BODY WAS UNVALIDATED.
A str is iterable: "abc" would have prepared three one-character "songs". And
the endpoint unpacks zips, so an arbitrary caller could ask for unbounded work.
Now list-only, string entries, blanks dropped, capped at MAX_GIG_SONGS.
Tests: the fetch is abortable and the button is re-enabled on EVERY path
including the abort; non-list bodies, non-string/blank entries, and an
oversized setlist. 50 career tests, JS 5/5, eslint clean.
* fix(career): path-traversal guard on prepare; a cap test that actually tests the cap
CodeRabbit again, and the first one is a real hole I put there.
1. PATH TRAVERSAL. sloppak.resolve_source_dir() does a bare `dlc_root / filename`
with NO containment guard — so `../../x` walks straight out of the library, and
my new endpoint handed it attacker-supplied filenames. Every filename now goes
through _resolve_dlc_path first, the same check every other filename-bound
handler applies. Pinned: `..`, backslash traversal, an absolute POSIX path and
a Windows drive path are all refused, and nothing outside the library is
unpacked.
2. THE CAP TEST WAS VACUOUS. It asserted `prepared == 0` against a fixture with no
library — where the endpoint exits before extraction — so it passed whether or
not MAX_GIG_SONGS existed. It now runs against a real library and asserts the
endpoint CONSIDERED at most MAX_GIG_SONGS of the 82 it was handed. Verified to
fail when the cap is removed.
Same class of mistake as the notedetect gigBlock: a test that passes for the
wrong reason. Worth saying out loud since it is twice in one day.
3. E702 — semicolon-joined statements in the new tests, split.
51 career tests; full suite green.
|
||
|---|---|---|
| .. | ||
| browser | ||
| fixtures | ||
| js | ||
| plugins | ||
| __init__.py | ||
| conftest.py | ||
| test_acoustid_match.py | ||
| test_albums_view.py | ||
| test_appstate.py | ||
| test_art_candidates.py | ||
| test_art_layer.py | ||
| test_artist_alias.py | ||
| test_artist_page.py | ||
| test_artist_sort_title_order.py | ||
| test_audio_bundled.py | ||
| test_audio_effect_mappings.py | ||
| test_audio_local_path.py | ||
| test_audio.py | ||
| test_batch_user_meta.py | ||
| test_builtin_diagnostic_seed.py | ||
| test_builtin_starter_seed.py | ||
| test_collections_api.py | ||
| test_context_menu_api.py | ||
| test_correlation_id.py | ||
| test_curated_album.py | ||
| test_demo_mode.py | ||
| test_diagnostics_bundle.py | ||
| test_diagnostics_hardware.py | ||
| test_diagnostics_redact.py | ||
| test_dlc_junction.py | ||
| test_drums_lib.py | ||
| test_enrichment_plumbing.py | ||
| test_env_compat.py | ||
| test_feedpak_extension.py | ||
| test_field_overrides.py | ||
| test_gap_fill.py | ||
| test_gp2midi.py | ||
| test_gp2notation.py | ||
| test_gp2rs_drums.py | ||
| test_gp2rs_gpx.py | ||
| test_gp2rs.py | ||
| test_gp_audio_sync.py | ||
| test_gp_autosync_warp.py | ||
| test_group_filter_law.py | ||
| test_highway_3d_routes.py | ||
| test_highway_ws_authors.py | ||
| test_highway_ws_instrument_routing.py | ||
| test_highway_ws_notation.py | ||
| test_library_filters.py | ||
| test_library_keyset.py | ||
| test_library_providers.py | ||
| test_lift_keys_notation.py | ||
| test_logging_setup.py | ||
| test_loops_concurrency.py | ||
| test_loose_traversal.py | ||
| test_loosefolder.py | ||
| test_lyrics_transcribe_remote.py | ||
| test_lyrics_transcribe.py | ||
| test_mb_enrichment.py | ||
| test_mb_match.py | ||
| test_midi_import_drums.py | ||
| test_midi_import.py | ||
| test_midi_tempo_map.py | ||
| test_migrate_full_mix_stem.py | ||
| test_minigames_routes.py | ||
| test_notation_lib.py | ||
| test_notation_lift.py | ||
| test_notation_to_notes.py | ||
| test_packaging.py | ||
| test_parse_arrangement.py | ||
| test_playlist_cover_errors.py | ||
| test_playlists_api.py | ||
| test_plugin_context_contract.py | ||
| test_plugin_manifest_contract.py | ||
| test_plugin_runtime_idempotence.py | ||
| test_plugin_src_route.py | ||
| test_plugins.py | ||
| test_practice_suggestions.py | ||
| test_profile_api.py | ||
| test_profile_domains.py | ||
| test_progression_api.py | ||
| test_progression.py | ||
| test_resolved_root_cache.py | ||
| test_safepath.py | ||
| test_scraper_options.py | ||
| test_settings_api.py | ||
| test_settings_export_library_db.py | ||
| test_settings_export.py | ||
| test_settings_instrument.py | ||
| test_sloppak_cent_offset.py | ||
| test_sloppak_cover_art.py | ||
| test_sloppak_drumtab_load.py | ||
| test_sloppak_feedpak_version.py | ||
| test_sloppak_file_traversal.py | ||
| test_sloppak_full_mix_load.py | ||
| test_sloppak_jsonc_load.py | ||
| test_sloppak_keys_load.py | ||
| test_sloppak_notation_load.py | ||
| test_sloppak_song_timeline_load.py | ||
| test_sloppak_unpack_cache.py | ||
| test_song_info_stems.py | ||
| test_song_score.py | ||
| test_song_stats_api.py | ||
| test_song_user_meta.py | ||
| test_song.py | ||
| test_songmeta.py | ||
| test_spec_gate.py | ||
| test_starter_suggestions.py | ||
| test_startup_status.py | ||
| test_tailwind_rebuild.py | ||
| test_tailwind_runtime_path.py | ||
| test_tones.py | ||
| test_tuning_provider_isolation.py | ||
| test_tunings.py | ||
| test_version_endpoint.py | ||
| test_vocal_pitch.py | ||
| test_wanted_api.py | ||
| test_work_charts_api.py | ||
| test_work_grouping.py | ||
| test_ws_highway_disconnect.py | ||
| test_xp.py | ||