Plan musical domain redesign

codex/redisenio-dominio-musical
dev 4 weeks ago
parent fa4de8b2f6
commit 5889fad361

@ -0,0 +1,369 @@
# Plan de implementación del dominio musical
## Propósito
Este documento convierte el análisis del catálogo en un programa de cambios
ejecutable. La aplicación mantendrá una sola tabla `cancion` para la grabación
principal y sus versiones musicales, pero dejará de confundir:
- una obra y sus datos comunes;
- una versión musical o grabación concreta;
- un intérprete y su ficha pública;
- una representación técnica de audio para escucha, descarga o archivo.
El trabajo será incremental. Las migraciones serán aditivas hasta que las
lecturas nuevas estén verificadas; ninguna columna ni relación actual se
retirará en la misma entrega que introduce su sustituta.
## Decisiones cerradas
### Canción y versiones
Cada fila de `cancion` es una versión musical reproducible. La principal tiene
`version_de_id = null`; una versión alternativa apunta directamente a la
principal.
La base debe garantizar que:
- una versión no apunta a sí misma;
- una versión solo apunta a una principal;
- no hay cadenas de versiones ni ciclos;
- solo una principal puede ponerse a la venta;
- comprar la principal da derecho a descargar sus versiones publicadas;
- `version_codigo` es único dentro de una principal.
Los datos comunes de la composición —ISWC, autoría y reparto— se asocian a la
principal. Los datos de grabación —ISRC, intérpretes, audio, duración y fecha—
pertenecen a cada fila concreta.
### Persona y artista
`persona` seguirá representando personas físicas, autoría, datos legales e IPI.
No representará grupos ni proyectos artísticos.
Se añadirá `artista`, que representa la identidad pública acreditada. Puede ser
una persona, un grupo o un proyecto. Una persona puede tener más de una
identidad artística y un grupo puede relacionarse con varias personas.
El identificador interno, el código de negocio y la URL tienen funciones
distintas:
- `id`: UUID opaco usado por claves foráneas;
- `codigo`: identificador estable de negocio, por ejemplo `ART-000123`;
- `slug`: dirección pública modificable.
### Versiones musicales y calidades de audio
Una versión orquestal, una maqueta y una toma en directo son filas distintas de
`cancion`. MP3 a 128 kbps, MP3 a 320 kbps y WAV son representaciones técnicas de
la misma fila y no crean canciones nuevas.
La escucha pública será completa en calidad web. La compra entregará archivos
de mayor calidad y, cuando corresponda, todas las versiones incluidas. No se
intentará presentar el streaming público como un archivo imposible de copiar:
la autorización protege la descarga de alta calidad, no el contenido que el
navegador necesariamente recibe para reproducir.
## Modelo de datos objetivo
### `artista`
| Columna | Regla |
| ------------------- | -------------------------------------------------------- |
| `id` | UUID, clave primaria |
| `codigo` | Único, inmutable |
| `slug` | Único, usado en URL |
| `tipo` | `persona`, `grupo` o `proyecto` |
| `nombre` | Nombre artístico visible |
| `descripcion_corta` | Texto para tarjetas y resultados |
| `biografia` | Markdown para la ficha |
| `imagen_id` | FK a `medio`, borrado con `set null` |
| `pais_codigo` | FK opcional a `pais` |
| `lugar_origen` | Texto opcional |
| `fecha_inicio` | Fecha o año, por decidir tras inventariar los datos |
| `fecha_fin` | Opcional |
| `sitio_web` | URL opcional |
| `estado` | `borrador`, `publicado` o `retirado` |
| auditoría | procedencia, revisión, creación y actualización actuales |
No se añadirá `nombre_legal` ni `ipi` a `artista`; esos datos pertenecen a
`persona`.
### `artista_persona`
Relaciona una identidad artística con personas físicas.
| Columna | Regla |
| ------------ | ----------------------------------- |
| `artista_id` | FK a `artista` |
| `persona_id` | FK a `persona` |
| `relacion` | `identidad`, `miembro` o `fundador` |
| `desde` | Fecha o año opcional |
| `hasta` | Fecha o año opcional |
| `orden` | Orden visible |
La clave primaria incluirá artista, persona y relación. Una guarda comprobará
que el período no termina antes de empezar.
### `artista_identificador`
Guarda identificadores externos sin crear una columna nueva por plataforma.
| Columna | Regla |
| ------------ | ----------------------------------------------------- |
| `artista_id` | FK a `artista` |
| `sistema` | `spotify`, `apple_music`, `musicbrainz`, `isni`, etc. |
| `valor` | Identificador en ese sistema |
Serán únicos tanto `(artista_id, sistema)` como `(sistema, valor)` cuando el
sistema garantice unicidad global.
### `cancion_interprete`
Relaciona un artista con una versión musical concreta.
| Columna | Regla |
| ----------------- | --------------------------------------------------- |
| `cancion_id` | FK a la fila concreta de `cancion` |
| `artista_id` | FK a `artista` |
| `rol` | `principal`, `invitado`, `coros` o `instrumentista` |
| `instrumento` | Opcional |
| `acreditado_como` | Nombre histórico de ese crédito, opcional |
| `principal` | Marca de presentación |
| `orden` | Orden del crédito |
La relación actual `cancion_persona` conservará temporalmente letra, música,
arreglos y producción. El rol `interprete` se retirará solo después de comprobar
la paridad de datos.
### `cancion_audio`
Relaciona cada versión con sus representaciones técnicas.
| Columna | Regla |
| --------------- | ----------------------------------------- |
| `cancion_id` | FK a `cancion` |
| `medio_id` | FK a `medio` |
| `uso` | `stream`, `descarga` o `master` |
| `formato` | `mp3`, `aac`, `opus`, `flac`, `wav`, etc. |
| `bitrate_kbps` | Opcional para formatos con pérdida |
| `frecuencia_hz` | Opcional |
| `bits_muestra` | Opcional |
| `canales` | Opcional |
| `orden` | Preferencia dentro de un mismo uso |
`medio.publico` y `uso` deben ser coherentes:
- `stream`: medio público y cacheable;
- `descarga`: medio privado, entregado solo con autorización;
- `master`: medio privado y nunca entregado por la web pública.
Una restricción impedirá repetir la misma combinación de canción, uso y
formato. Si se necesitan dos codificaciones equivalentes, el modelo se ampliará
con un identificador de perfil explícito, no relajando la unicidad sin motivo.
### Ajustes en `cancion`
Se añadirá `codigo`, único e inmutable. Se revisarán las columnas actuales con
estas reglas:
- `isrc` pertenece a cada versión;
- `iswc`, autoría y reparto pertenecen a la principal;
- `audio_id` y `muestra_id` quedan obsoletos tras poblar `cancion_audio`;
- `ala_venta` solo puede ser cierto en una principal;
- una versión puede tener intérpretes, audio, portada y duración propios;
- una versión sin letra propia puede usar la de la principal en el read model,
sin copiarla al guardar.
No se moverá todavía `album_id` a una tabla puente. Se documenta como evolución
posterior si una misma grabación debe aparecer en varias ediciones.
## Contratos de aplicación
Los intérpretes dejan de ser `string[]`. Las lecturas públicas usarán objetos
tipados:
```ts
interface InterpreteResumen {
id: string;
codigo: string;
slug: string;
nombre: string;
tipo: 'persona' | 'grupo' | 'proyecto';
imagen?: string;
rol: 'principal' | 'invitado' | 'coros' | 'instrumentista';
instrumento?: string;
}
```
Se crearán read models independientes:
- `CancionPublicaReadModel`;
- `FichaArtistaReadModel`;
- `ListadoArtistasReadModel`;
- `AudioReproducibleReadModel`;
- `DescargaCompradaReadModel`.
La ficha de canción no resolverá biografías completas. Solo recibe el resumen y
enlaza a `/interpretes/[slug]`; la ficha del artista carga biografía,
identificadores públicos y discografía.
## Programa de entregas
### PR 1 · Guardas de publicación
1. Centralizar el predicado de contenido público.
2. Aplicarlo a catálogo, canciones, álbumes, estilos, géneros, sitemap y SEO.
3. Separar lectura pública de lectura autorizada para canciones retiradas.
4. Añadir integración PostgreSQL para borrador, publicado y retirado.
No depende del nuevo modelo y evita publicar accidentalmente datos durante la
migración.
### PR 2 · Autenticación y comercio atómicos
1. Hacer atómicos el límite de peticiones y el consumo de OTP.
2. Añadir unicidad de carrito por usuario, fusionando duplicados existentes.
3. Crear pedido y líneas en una transacción.
4. Finalizar pedidos con transición condicional pendiente → pagado.
5. Registrar el inicio autorizado de una descarga o ajustar su semántica.
### PR 3 · Esquema aditivo de artistas y audio
1. Sincronizar primero el journal de Drizzle con `0011` y `0012`.
2. Añadir `artista`, `artista_persona`, `artista_identificador`,
`cancion_interprete` y `cancion_audio`.
3. Añadir `cancion.codigo` y las restricciones de versiones.
4. Añadir `CHECK` reales para los vocabularios cerrados.
5. Mantener intactas las columnas y relaciones antiguas.
La migración debe ejecutarse sobre una copia de producción antes de aplicarse al
entorno real.
### PR 4 · Inventario y migración de datos
El script de migración será repetible y producirá un informe antes de escribir.
1. Inventariar nombres usados como intérprete.
2. Normalizar mayúsculas, espacios y variantes obvias sin fusionar por heurística.
3. Presentar colisiones para decisión manual.
4. Crear un `artista` por identidad confirmada.
5. Relacionar personas físicas conocidas mediante `artista_persona`.
6. Migrar `cancion_persona(rol = interprete)` a `cancion_interprete`.
7. Crear códigos estables para canciones y artistas.
8. Convertir el audio completo actual en representación `master` o `descarga`
según el formato real.
9. Marcar las muestras recortadas como legado; no confundirlas con el nuevo
streaming completo.
El informe debe comparar canciones, versiones, intérpretes y archivos antes y
después, y detenerse ante cualquier huérfano.
### PR 5 · Pipeline de audio completo
1. Recibir o localizar el master privado.
2. Obtener duración, códec, frecuencia y canales mediante `ffprobe`.
3. Calcular la huella antes de generar derivados.
4. Generar la calidad web completa con un perfil versionado.
5. Generar las calidades de descarga acordadas.
6. Insertar todos los medios y relaciones en una transacción.
7. No permitir publicar una canción sin una representación `stream` válida.
8. Servir audio con `Range`, tipo MIME, `ETag` y caché coherentes.
El perfil inicial se decidirá escuchando material real. Como punto de partida:
stream MP3/AAC entre 96 y 128 kbps y descarga MP3 320 kbps; WAV o FLAC se
conservarán como master y solo se ofrecerán si forman parte del producto.
### PR 6 · Panel de artistas, créditos y audio
1. CRUD de artistas con imagen, descripción, biografía, país y estado.
2. Selector de intérpretes en cada versión musical.
3. Edición de rol, instrumento, acreditación y orden.
4. Vista de las representaciones de audio y su estado de procesamiento.
5. Acción explícita para regenerar derivados desde el master.
6. Bloqueo de publicación con errores accionables.
El panel no aceptará nombres libres como intérpretes. Permitirá crear un artista
desde el selector sin abandonar la canción.
### PR 7 · Lecturas públicas y fichas
1. Cambiar `Cancion.interpretes` de nombres a objetos.
2. Crear `/interpretes` y `/interpretes/[slug]`.
3. Mostrar imagen, descripción, biografía y discografía.
4. Enlazar los créditos de canciones y álbumes con la ficha correspondiente.
5. Incluir únicamente artistas publicados en rutas públicas y sitemap.
6. Mantener acreditaciones históricas aunque cambie el nombre actual del artista.
### PR 8 · Reproductor y compra
1. Sustituir la muestra recortada por la representación `stream` completa.
2. Actualizar cola, duración, textos y estados de error.
3. Autorizar descargas de representaciones `descarga` de la principal y sus
versiones publicadas incluidas.
4. Impedir que URLs privadas viajen en los datos de página.
5. Actualizar condiciones de venta y privacidad antes de producción.
### PR 9 · Consultas, caché y layout
1. Eliminar el catálogo entero del layout raíz.
2. Crear read models específicos por ruta.
3. Paralelizar las consultas transversales restantes.
4. Retirar la invalidación de memoria entre panel y sitio.
5. Medir antes de introducir una caché compartida.
### PR 10 · Retirada del legado y división de UI
1. Retirar `cancion_persona.rol = interprete` tras comprobar paridad.
2. Retirar `audio_id` y `muestra_id` tras comprobar todos los medios.
3. Mover el código Markdown restante a importadores o eliminarlo.
4. Actualizar README, `.env.example` y modelo de datos.
5. Dividir `Capitulo.svelte` y los editores grandes del panel por responsabilidad.
6. Centralizar plataformas, formatos, etiquetas y políticas duplicadas.
## Estrategia de despliegue y reversión
1. Copia de seguridad y restauración ensayada antes de migrar datos.
2. Migraciones aditivas compatibles con la versión anterior del servidor.
3. Backfill separado, repetible y con modo de solo informe.
4. Activación de lecturas nuevas mediante una única configuración temporal.
5. Comparación de lecturas antigua y nueva en pruebas y entorno de ensayo.
6. Despliegue del código nuevo antes de retirar columnas antiguas.
7. Retirada destructiva en una migración posterior, con respaldo confirmado.
La reversión durante la fase aditiva consiste en volver al servidor anterior;
las tablas nuevas pueden permanecer. Después de la retirada destructiva, la
reversión requiere restaurar la copia, por lo que esa entrega tendrá una ventana
de despliegue explícita.
## Verificación mínima por entrega
```text
npm run check
npm run lint
npm run test:unit -- --run
npm run build
npm run build:panel
pruebas de integración contra PostgreSQL aislado
E2E de los flujos modificados
```
Pruebas específicas obligatorias:
- un borrador nunca aparece públicamente;
- dos consumos simultáneos de OTP solo producen un éxito;
- dos confirmaciones de Stripe solo finalizan un pedido una vez;
- cada versión devuelve sus propios intérpretes;
- una compra de la principal autoriza las versiones incluidas;
- el streaming reproduce la duración completa;
- el navegador nunca recibe la clave del master o de la descarga privada;
- un artista retirado conserva los créditos históricos sin tener ficha pública;
- el backfill conserva el número de canciones, versiones y relaciones válidas.
## Criterio de finalización
El programa se considera cerrado cuando el catálogo público usa exclusivamente
los nuevos read models, los intérpretes son entidades administrables y
enlazables, el streaming completo se genera desde masters privados, las compras
entregan representaciones de alta calidad, no quedan lecturas productivas del
modelo legado y todos los checks, integración y E2E pasan en CI.
Loading…
Cancel
Save

Powered by TurnKey Linux.