Skip to content

Latest commit

 

History

History
242 lines (186 loc) · 11.8 KB

File metadata and controls

242 lines (186 loc) · 11.8 KB

Estado Cero — La Realidad Arquitectónica de Syncify

Generado: 2026-03-07 | Auditor: Antigravity (modo forense)


1. Propósito Real Actual

Syncify hoy es una aplicación de escritorio Tauri v2 que puede:

Capacidad Estado Real Evidencia
Importar bibliotecas de Spotify, Qobuz, Tidal, Deezer, SoundCloud, Apple Music ✅ Funcional vía API + Python bridges src-tauri/src/commands/service.rs (67 KB, ~1700 líneas)
Almacenar tracks/albums/artists en SQLite ✅ Funcional src-tauri/src/db.rs:34 — 19 migraciones ejecutadas automáticamente
Autenticación OAuth para Spotify ✅ Funcional (flujo nativo Rust) src-tauri/src/commands/auth.rs
Autenticación para otros servicios ⚠️ Python subprocess scripts/auth_bridge.py (13 KB) — depende de Python instalado en el sistema
Sistema de cola de descargas con worker ✅ Worker background funcional src-tauri/src/worker.rs (14 KB), main.rs:53-74
Descargar tracks (Qobuz, Tidal, Amazon) ⚠️ Descargadores existen pero dependen de credenciales/tokens válidos src-tauri/src/download/qobuz.rs, tidal.rs, amazon.rs
Enriquecimiento de metadatos (MusicBrainz, Spotify Audio Features, Last.fm genres) ✅ Worker background automático main.rs:78-346 — loop infinito con 5 min de espera
UI completa con 13 vistas ⚠️ Renderiza pero con datos hardcodeados en múltiples widgets Ver Archivo 2
Persistir configuración desde UI Parcial — múltiples secciones son cosméticas Ver Archivo 2

Resumen brutal: El backend Rust tiene una profundidad real (186 comandos Tauri registrados, 12 servicios de streaming, 9 módulos de descarga). La UI renderiza datos reales en Library, Queue, y Accounts. Sin embargo, grandes secciones de Settings, Dashboard, y StatusBar muestran datos falsos pintados directamente en el template.


2. Stack Tecnológico y Dependencias Reales

Backend (Rust / Tauri)

Dependencia Versión Propósito
tauri 2.x Framework desktop
tauri-plugin-shell 2.x Ejecutar Python subprocesses
tauri-plugin-dialog 2.x Diálogos nativos
sqlx 0.8 SQLite async con migraciones
tokio 1.x Runtime async
reqwest 0.12 HTTP client (APIs streaming)
aes-gcm 0.10 Cifrado de credenciales
lofty 0.18 Lectura/escritura de tags de audio
serde / serde_json 1.x Serialización
uuid 1.x (v4) IDs únicos
sha2 0.10 Hashing para derivar clave de cifrado
dotenvy 0.15 Variables de entorno
futures / futures-util 0.3 Utilidades async

Fuente: src-tauri/Cargo.toml

Frontend (Vue / Vite)

Dependencia Versión Propósito
vue ^3.4.0 Framework UI
vue-router ^4.2.0 Routing
@tauri-apps/api ^2.0.0 IPC con Rust
tailwindcss ^4.1.18 CSS framework
vite ^5.4.0 Build tool
vitest ^4.0.16 Testing
typescript ^5.3.0 Tipado

Fuente: ui/package.json

Dependencias Externas (Runtime)

Herramienta Requerido Propósito
Python 3.x Sí (para auth, lyrics, metadata, fingerprinting, download bridges) 13+ scripts en scripts/
FFmpeg Condicional Conversión de audio (scripts/conversion_bridge.py)
fpcalc (Chromaprint) Condicional Audio fingerprinting (scripts/fingerprint_bridge.py)

3. Mapa Topológico del Codebase

Syncify/
├── src-tauri/                    # BACKEND RUST (Tauri v2)
│   ├── src/
│   │   ├── main.rs               # Entry point + enrichment worker INLINE (541 líneas)
│   │   ├── db.rs                 # SQLite pool init + migraciones (46 líneas)
│   │   ├── crypto.rs             # AES-256-GCM credential encryption (123 líneas)
│   │   ├── models.rs             # Structs SQLx (16 KB)
│   │   ├── worker.rs             # Download worker background (14 KB)
│   │   ├── downloader.rs         # Download orchestration (11 KB)
│   │   ├── import_cache.rs       # Dedup imports (6 KB)
│   │   ├── commands/             # 16 archivos Tauri commands (~300 KB total)
│   │   │   ├── service.rs        # 67 KB — el archivo más grande del proyecto
│   │   │   ├── settings.rs       # 26 KB — 7 sprints de settings
│   │   │   ├── migration.rs      # 34 KB — migración entre servicios
│   │   │   ├── library.rs        # 25 KB — CRUD biblioteca
│   │   │   ├── lyrics.rs         # 23 KB — fetch, save, embed lyrics
│   │   │   ├── enrichment.rs     # 17 KB — MusicBrainz, Spotify, Last.fm
│   │   │   ├── dashboard.rs      # 16 KB — stats, health checks
│   │   │   ├── accounts.rs       # 15 KB — CRUD cuentas
│   │   │   ├── metadata.rs       # 14 KB — metadata editing
│   │   │   ├── tools.rs          # 28 KB — scanner, organizer, converter, fingerprinter
│   │   │   └── queue.rs          # 10 KB — cola de descargas
│   │   ├── services/             # 12 archivos — conectores de streaming
│   │   │   ├── spotify.rs        # 41 KB — el conector más completo
│   │   │   ├── deezer.rs         # 21 KB
│   │   │   ├── qobuz.rs          # 18 KB
│   │   │   ├── tidal.rs          # 16 KB
│   │   │   ├── soundcloud.rs     # 13 KB
│   │   │   ├── apple_music.rs    # 13 KB
│   │   │   ├── musicbrainz.rs    # 10 KB
│   │   │   ├── rate_limiter.rs   # 7 KB
│   │   │   └── lastfm.rs         # 5 KB
│   │   └── download/             # 9 archivos — descargadores por servicio
│   │       ├── tidal.rs          # 17 KB
│   │       ├── qobuz.rs          # 16 KB
│   │       ├── lyrics.rs         # 11 KB (lyrics downloader)
│   │       ├── amazon.rs         # 8 KB
│   │       └── orchestrator.rs   # 6 KB
│   └── tauri.conf.json           # Configuración Tauri
│
├── ui/                           # FRONTEND VUE 3
│   └── src/
│       ├── App.vue               # 16 KB — layout, nav, routing
│       ├── views/                # 13 vistas (~600 KB total)
│       │   ├── MetadataView.vue  # 92 KB — la vista más grande
│       │   ├── SettingsView.vue  # 90 KB
│       │   ├── LibraryView.vue   # 78 KB
│       │   ├── MigrationView.vue # 73 KB
│       │   ├── AccountsView.vue  # 61 KB
│       │   ├── LyricsView.vue    # 60 KB
│       │   ├── DownloadsView.vue # 47 KB
│       │   ├── PlaylistView.vue  # 37 KB
│       │   ├── DashboardView.vue # 27 KB
│       │   ├── QueueView.vue     # 11 KB
│       │   ├── ArtistDetailView  # 10 KB
│       │   ├── AlbumDetailView   # 8 KB
│       │   └── LogsView.vue      # 4 KB
│       ├── components/           # 26 componentes
│       ├── api/                  # 11 módulos API — solo 4 exportados en index.ts
│       ├── composables/          # 14 composables para estado reactivo
│       └── __tests__/            # 6 archivos de tests
│
├── scripts/                      # 26 Python bridge scripts
├── migrations/                   # 19 SQL migrations (0001-0019)
├── conductor/                    # Documentación del producto y estilos
└── Cargo.toml                    # Crate raíz "syncify-core" (sin ejecutable real)

4. Vulnerabilidades y Atajos

🔴 CRÍTICO: Content Security Policy Deshabilitada

Archivo: src-tauri/tauri.conf.json:23

"security": {
  "csp": null
}

Impacto: Cualquier XSS en el webview puede ejecutar código arbitrario. La CSP nula desactiva toda protección contra inyección de scripts.


🔴 CRÍTICO: Clave de Cifrado Determinística y Reproducible

Archivo: src-tauri/src/crypto.rs:23-51

La clave AES-256 se deriva de SHA256("syncify-music-library-v1" + USERNAME + HOME_DIR + HOSTNAME). Todos estos valores son públicos o fácilmente adivinables. Un atacante con acceso al sistema puede derivar la misma clave y descifrar todas las credenciales de streaming almacenadas en la base de datos.

No se usa Keychain/Credential Store del sistema operativo.


🔴 CRÍTICO: Qobuz Secrets Se Leen con unwrap() Sin Fallback

Archivo: src-tauri/src/commands/service.rs:1704-1705

std::env::var("QOBUZ_APP_ID").unwrap(),
std::env::var("QOBUZ_APP_SECRET").unwrap(),

Impacto: Si las variables de entorno no están definidas, la aplicación crashea en panic sin ningún mensaje de error manejado.


🟠 ALTO: 47+ unwrap() en Backend Producción

Archivos afectados con unwrap() fuera de tests:

  • commands/service.rs — 5 instancias (líneas 80, 162, 322, 1378, 1551)
  • commands/accounts.rs — 4 instancias (líneas 338, 351, 390, 498)
  • commands/settings.rs — 3 instancias (líneas 799, 807, 814)
  • commands/dashboard.rs — 3 instancias (líneas 424, 443, 448)
  • services/spotify.rs — 1 instancia (línea 827)
  • services/musicbrainz.rs — 2 instancias (líneas 75, 83)
  • download/tidal.rs — 2 instancias (líneas 142, 182)
  • download/progress.rs — 7 instancias (líneas 172-200)
  • download/http_client.rs — 5 instancias (líneas 80-139)
  • download/lyrics.rs — 2 instancias (líneas 77, 89)

Impacto: Cada unwrap() es un potencial panic que mata la aplicación sin posibilidad de recuperación.


🟠 ALTO: Worker de Enriquecimiento Inline en main.rs

Archivo: src-tauri/src/main.rs:78-346 (268 líneas)

Un loop infinito de enriquecimiento (MusicBrainz + Spotify Audio Features + Last.fm Genres) está embebido directamente en el closure de .setup() de Tauri. No es un servicio separado ni un módulo testeable. Si cualquier panic ocurre dentro de este loop, no hay recovery.


🟠 ALTO: commands/service.rs — 67 KB / ~1700 Líneas en UN Solo Archivo

Este archivo contiene toda la lógica de importación de 6 servicios de streaming. No hay separación por servicio. Difícil de mantener, testear, o razonar sobre.


🟡 MEDIO: Base de Datos Relativa al CWD

Archivo: src-tauri/src/db.rs:43-44

let project_root = std::env::current_dir().unwrap_or_default();
project_root.join("data").join("syncify.db")

La ruta de la DB depende del directorio de trabajo actual. Si la app se ejecuta desde un shortcut con un CWD diferente, creará/usará una base de datos diferente. Debería usar dirs::data_dir() para producción.


🟡 MEDIO: include!() Macro para Todos los Comandos

Archivo: src-tauri/src/commands/mod.rs:12-25

Todos los archivos de comandos se importan via include!() en vez de mod. Esto significa que comparten el mismo scope de imports, no son módulos independientes, y el IDE no puede proveer aislamiento de nombres. Es un antipatrón en Rust.


🟡 MEDIO: Crate Raíz syncify-core Sin Uso

Archivo: Cargo.toml (raíz) y src/main.rs (3 líneas: fn main() { println!("placeholder") })

El crate raíz fue creado durante bootstrap pero nunca se integró con src-tauri. No comparte código con el backend Tauri. Es peso muerto.


🟡 MEDIO: Dependencia de Python Sin Verificación al Inicio

La app depende de python en PATH para autenticación de 5 servicios, lyrics, fingerprinting, conversión, y organización. No hay verificación al inicio de que Python esté instalado ni que los paquetes (spotipy, etc.) estén disponibles. Si Python no existe, los comandos fallan silenciosamente retornando errores genéricos.