tts-voice-creator-clone-and.../core/registry.py
mARTin-B78 c7a1e35539 Security audit, modular refactor, and container-name field
Security fixes:
- Block /proc /sys /dev /run /boot in /api/browse-dirs (path traversal)
- Verify yt-dlp output stays inside TEMP_DIR before registration
- Remove Access-Control-Allow-Origin: * from /api/proxy-audio
- TTL-based temp file registry (default 2h) to prevent disk fill

Performance:
- Cache settings + routing rules in memory (mtime-checked); eliminates
  per-request disk reads on every TTS call

UI:
- Add container name (optional) field to Docker stack TTS/STT engine
  cards (Qwen3 Voice Clone, Voice Design, Custom Voice, Streaming,
  NVIDIA Magpie, Parakeet) — enables Stop/Start/Restart buttons on
  all engine cards, matching the existing Other Local TTS/STT cards

Refactor — backend:
- server.py: 5560 lines → 43-line entry point
- core/ package: constants, registry, validation, docker_client,
  config, routing, audio, voice, presets, tts_helpers
- routes/ package: admin, settings, library, stt, sources, docker,
  tts, conversation (FastAPI APIRouter modules)
- Dockerfile + docker-compose.yml updated to include core/ and routes/

Refactor — frontend:
- static/app.js: 8744 lines → 16 modules in static/js/
  utils, voice-inspector, voice-sources, integrations, routing,
  settings, voice-clone, voice-library, tts-preview, benchmark,
  stt, init, engines, ai-backends, generation, conversation
- static/loader.js updated to load modules sequentially

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 12:13:07 +02:00

32 lines
859 B
Python

"""Temp-file registry with TTL-based GC."""
from __future__ import annotations
import contextlib
import os
import tempfile
import time
from pathlib import Path
TEMP_DIR = Path(tempfile.mkdtemp(prefix="vcf_"))
_REGISTRY_TTL = float(os.environ.get("TEMP_FILE_TTL_SECONDS", "7200")) # 2 h default
_registry: dict[str, tuple[Path, float]] = {}
def _registry_put(fid: str, path: Path) -> None:
_registry[fid] = (path, time.monotonic())
_registry_gc()
def _registry_get(fid: str) -> Path | None:
entry = _registry.get(fid)
return entry[0] if entry else None
def _registry_gc() -> None:
cutoff = time.monotonic() - _REGISTRY_TTL
stale = [k for k, (_, ts) in _registry.items() if ts < cutoff]
for k in stale:
path, _ = _registry.pop(k)
with contextlib.suppress(Exception):
path.unlink(missing_ok=True)