6 Commits
Author SHA1 Message Date
Palash Debnath 8428517d95 fix(auth): preserve local Hugging Face token paths and cleanup 2026-09-07 15:03:12 +05:30
Palash DebnathandClaude Opus 4.8 7d9338bd2d fix(dub): key per-segment WAVs by stable id, not list index (#185) (#187)
* fix(dub): key per-segment WAVs by stable id, not list index (#185)

Partial regeneration ('regenerate only changed segments') reloaded/wrote
seg_{i}.wav by LIST INDEX while the regen allow-list + fingerprints were keyed
by STABLE id. After a delete/merge/split (ids preserved, positions shifted),
unchanged segments reused a different segment's audio → silently corrupted dub
output on the default in-UI incremental path.

- core.config.dub_seg_path(job_id, seg_id): per-segment path keyed by stable
  id, sanitized to a bare filename (defends against path traversal via crafted
  ids). A numeric index sanitizes to the legacy seg_{i}.wav, so old jobs resolve
  through the same helper.
- dub_generate: write/reload per-segment WAVs by stable seg_id (deferred write,
  RVC write, regen reload) with a legacy seg_{i}.wav fallback; persist a
  job['seg_order'] manifest (index -> stable id) for index-keyed readers.
- dub_export: preview + stems-zip resolve the file via seg_order (-> stable id)
  with legacy fallback, so they keep finding the right audio.
- test: dub_seg_path id-naming, legacy-index equivalence, traversal sanitization.

Back-compatible with in-flight jobs (legacy index files still resolve). Closes #185.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dub): harden dub_seg_path with realpath containment; route all seg paths through it (CodeQL path-injection)

Both job_id and seg_id are request-derived. Sanitise both and verify the
resolved path stays inside DUB_DIR (realpath + startswith) — raises on escape.
Route the legacy index fallbacks in dub_generate/dub_export through dub_seg_path
so no raw os.path.join(DUB_DIR, job_id, ...) remains and a bare '..' component
can't traverse.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dub): assert path containment at export sinks (recognized CodeQL barrier)

dub_seg_path already validates realpath containment, but CodeQL doesn't
propagate the barrier across the call. Re-assert at the FileResponse / zf.write
sinks (realpath + startswith on the value used) so the guard is recognized
in-function — clears the py/path-injection false positives.

* fix(dub): realpath+containment guard before any path sink in export/preview

CodeQL flags os.path.exists/FileResponse/zf.write as path sinks and won't
propagate dub_seg_path's internal guard. Resolve each candidate, realpath it,
and containment-check (startswith DUB_DIR) BEFORE any filesystem access — the
guard now dominates every sink in-function, clearing py/path-injection.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 03:31:03 +05:30
Palash Debnath 0ecbf136e7 refactor: codebase cleanup & root folder reorganization (#38)
refactor: codebase cleanup & root folder reorganization
2026-05-03 03:12:07 +05:30
debpalash 901eb040a8 feat: add live bootstrap progress bars and log inspection to splash screen 2026-04-25 17:22:51 +05:30
debpalash 6f124fb175 feat: implement frontend UI components and expand research documentation for voice processing and translation workflows. 2026-04-21 04:31:08 +05:30
debpalashandClaude Opus 4.7 67328d04fe refactor: split backend into api/core/services/schemas, harden security + fd pressure, add searchable language picker, fix segment fragmentation
Backend:
- Split monolithic main.py into backend/{api/routers,core,schemas,services}
- core/db.py: allowlist-gated migrations, db_conn context manager (kills SQL injection on ALTER)
- core/tasks.py: lock-guarded listener add/remove/push, snapshot-before-iterate
- services/ffmpeg_utils.py: run_ffmpeg helper with concurrency semaphore, EAGAIN retry, guaranteed reap
- services/segmentation.py: Bengali/CJK/Arabic punctuation, ultra-short tier, stitch_adjacent_shorts,
  bounded-loop merge; public clean_up_segments API
- services/model_manager.py: robust lock.locked() handling
- api/routers/dub_core.py: job_id traversal guard, thread-safe _active_procs, timeouts on ffmpeg/demucs,
  POST /dub/cleanup-segments endpoint
- api/routers/dub_export.py: guarded SSE listener remove, ffmpeg timeouts via run_ffmpeg
- api/routers/exports.py: destination_path validation, safe source resolver, subprocess list-form
- api/routers/generation.py: contextlib.suppress on tempfile cleanup, db_conn usage, safe output-path helper
- api/routers/system.py: try/finally tmp cleanup, subprocess timeouts
- schemas/requests.py: TranslateSegment.id int->str to match hex segment IDs
- main.py: threading.Lock around crash log writes

Frontend:
- components/SearchableSelect.jsx: popover combobox with search, keyboard nav, popular+recent pins, 200-item cap
- App.jsx: wire SearchableSelect for dub language / ISO code / voice-gen language; Clean Up segments button;
  fix blob URL leak (object-shaped prev in setter, unmount cleanup via ref)
- components/WaveformTimeline.jsx: explicit <video> detach instead of innerHTML='' to release decoder
- index.css: ss-* combobox styles matching Gruvbox theme

Tests:
- tests/test_segmentation.py (26 cases), test_dub_transcribe.py, test_dub_export_unique.py, conftest.py

Chore:
- .gitignore: exclude omnivoice.zip, /research/ reference clones
- Remove tracked stray root test scripts + crash_log.txt

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:20:19 +05:30