Enseñarle a Greenhouse a previsualizar audio del vault dentro de la app
Greenhouse es una app de escritorio que impone un ritmo de proceso creativo: capturar una idea, dejarla madurar, trabajarla, tocarla, eventualmente guardarla en el vault o publicarla. Había algo que no dejaba de molestarme: cuando una idea o proyecto tiene un bounce de audio en su carpeta, la única forma de escucharlo es hacer clic en “Show in Finder” y buscarlo manualmente. Quería algo más cercano a Quick Look de macOS: apretar un botón, escuchar el boceto, decidir.
Antes de escribir cualquier código de interfaz escribí una investigación exploratoria (spike). Greenhouse es una app de Tauri v2, y en realidad no sabía cómo se le permite a un webview de Tauri tocar archivos locales. Asumía que estaría bloqueado por defecto, pero quería averiguar exactamente cuánto bloqueado, y qué costaría abrir la puerta un poco.
La seguridad partía de cero
Resultó que la app no exponía ni un byte de archivos al webview. Sin protocolo de assets, sin plugin de sistema de archivos, y con una Content-Security-Policy fijada a default-src 'self'. Lo único que tocaba el sistema de archivos desde el frontend era un botón de “abrir esta carpeta en Finder”, que simplemente le pasa una ruta al sistema operativo, el webview en sí nunca ve el contenido de los archivos.
Eso en realidad es una buena señal para una app que se toma en serio la seguridad, pero significaba que reproducir audio dentro de la app no iba a ser un ajuste menor. Iba a necesitar ampliar el CSP, algo que se sentía incómodo justo después de haber terminado una pasada de endurecimiento de seguridad sobre esta misma app.
Probarlo antes de construirlo
En vez de debatir la concesión en abstracto, construí una prueba de concepto descartable. Tauri tiene un “protocolo de assets” incorporado: se habilita una feature de Cargo, se cambia una bandera de configuración, y el webview puede pedir archivos locales a través de un esquema de URL especial en vez de una petición de red. La parte interesante es el alcance: no conviene darle al webview acceso a todo el sistema de archivos, solo a las carpetas que realmente necesita.
Como la ubicación del vault de Greenhouse la elige la persona usuaria durante el onboarding (no es una ruta fija incrustada en el build), el enfoque habitual de “listar las carpetas permitidas en el archivo de configuración” no encaja del todo. Tauri tiene una API en tiempo de ejecución para esto: se otorga acceso a un directorio específico desde el código, justo en el momento en que se sabe cuál es ese directorio. Así que la raíz del vault queda delimitada dentro del protocolo de assets exactamente una vez, en el momento en que se define o se carga al iniciar la app, nunca más amplio que eso.
También amplié la Content-Security-Policy, pero de forma acotada: solo toqué las dos directivas que cargan contenido multimedia (img-src, media-src), y dejé la política por defecto exactamente tan estricta como estaba. Un diff pequeño y fácil de explicar.
Después de eso, hice correr la app de verdad para comprobar que funcionaba, no solo “compiló”, sino un script que abre la app real, captura una idea real a través de la misma capa de IPC que usa la interfaz, suelta un archivo WAV real en su carpeta desde afuera del webview (simulando a alguien guardando un bounce ahí), y hace clic hasta previsualizarlo. Después le pregunté al elemento de audio en vivo en qué estado estaba: completamente cargado, duración correcta, sin errores, servido a través del propio esquema de URL del protocolo de assets. Algo que solo aprendí probando sobre el build real de macOS: la URL que Tauri realmente usa en macOS (asset://localhost/...) no coincide con lo que muestra la mayoría de la documentación que encontré, que describe la forma de Windows/Linux. Es un detalle menor, pero es exactamente el tipo de cosa que no se obtiene leyendo documentación, se obtiene ejecutando la aplicación.
De la investigación exploratoria a la funcionalidad publicada
Con el enfoque ya validado, construí la versión real: un panel de “Files” en la vista de detalle de proyecto, un botón de Preview junto a cualquier cosa que parezca audio, y un reproductor liviano que se abre en un overlay. Dejé “Show in Finder” tal como estaba en vez de reemplazarlo, algunas personas van a seguir queriendo el archivo real, no una previsualización.
Un bug pequeño y satisfactorio: mi primer borrador hacía que el audio se reprodujera automáticamente en el momento en que se abría la previsualización. Mis pruebas automáticas de accesibilidad empezaron a quedarse colgadas en esa pantalla, y descubrir por qué me llevó a una regla que ya conocía a medias y nunca había terminado de internalizar: no reproducir audio automáticamente. Es una guía de accesibilidad real, no solo un inconveniente de pruebas. Quitar el autoplay arregló la prueba y mejoró la funcionalidad al mismo tiempo, el tipo de coincidencia que en realidad no es coincidencia.
Limité esta primera versión solo a audio, a propósito. Las imágenes y los PDF reutilizarían la misma cañería, pero no los había probado, y toda la razón de ser de Greenhouse es proteger el proceso creativo de las personas contra el feature creep, incluido el mío propio.
Lecturas relacionadas
El escaneo que se ofreció a importarse a sí mismo
Un escáner de importación encontró la estructura interna de la app, y volvió a ofrecer una carpeta ya importada - la misma conversación faltante entre capas.
Cuando una app no puede quitar un permiso que ya otorgó
El scope del protocolo de assets de Tauri tiene allow_directory y ningún revoke, así que cambiar de vault pasó a requerir un reinicio, cambiando velocidad por una seguridad real.
El callback que no podía decir qué había pasado
Arreglar un error de actualización del panel expuso un segundo error escondido en el mismo componente compartido, y un tercer error que resultó no existir.
También te podría ser útil
AdGuard para iOS
Bloqueo de anuncios y rastreadores en todo el sistema en iOS, sin necesidad de un servidor DNS aparte.
Como afiliado de AdGuard, obtengo ingresos por las compras que califican.
Más informaciónProton Mail
Correo electrónico cifrado de extremo a extremo, con arquitectura de acceso cero.
Como socio de Proton, obtengo ingresos por las compras que califican de los servicios de privacidad y seguridad de Proton (Pass, Mail, VPN, Drive).
Más informaciónProton Drive
Almacenamiento en la nube cifrado, del equipo detrás de Proton Mail.
Como socio de Proton, obtengo ingresos por las compras que califican de los servicios de privacidad y seguridad de Proton (Pass, Mail, VPN, Drive).
Más información