Acceso editorial
Los usuarios editoriales se crean en el dashboard de Supabase
(Authentication → Users) y reciben roles con bootstrap-roles.sql
o desde la pestaña Roles (admin).
Estado de la plataforma
De un vistazo: qué hay publicado, qué está esperando aprobación y dónde quedan huecos por llenar.
Somos comunidad · lo mismo que ve la app en Hoy
Totales históricos desde el primer día: cada rezo completado suma en el servidor y nada resta, ni siquiera borrar la cuenta. Las cifras de actividad (Rosarios, Coronillas…) empiezan a moverse cuando el 1.0.0+31 llegue a los teléfonos.
Cola de moderación
Lo que está esperando a que alguien lo mire. Cada número lleva a su pestaña.
Cargando…
Mapa de contenido — cobertura de lecturas
Cada celda es un mes. Cuanto más oscura, más completo; las punteadas están vacías. El número es el porcentaje del mes cubierto. Pasa el cursor por una celda para ver el detalle.
Directorio parroquial
Qué tan completa está la ficha de cada parroquia. Las barras cortas son el trabajo pendiente.
Cargando…
Comunidad y recursos
Eventos, recursos externos y biblioteca.
Cargando…
Encuesta de Donaciones
El piloto sale apagado en la 1.0.0; esto es lo que decide si se enciende. Solo agregados — las sugerencias y la ciudad son texto de una persona y se leen en su pestaña, no aquí.
Cargando…
IA católica
Va detrás de una bandera compilada, apagada en la 1.0.0. Aquí se ve si el corpus estaría listo el día que se encienda.
Cargando…
Resumen de contenido
Cuánto contenido hay cargado, mes a mes. Cobertura = días del mes con Evangelio en español (mismo criterio que la tabla de abajo); Lecturas cuenta todas las lenguas. Reflexiones y oraciones son las programadas con fecha; ✓ = todas aprobadas, si no se indica cuántas siguen sin aprobar (borrador/revisión).
| Mes | Cobertura | Lecturas | Reflexiones | Oraciones | Santos | Estado |
|---|---|---|---|---|---|---|
| Cargando… | ||||||
Cobertura diaria — próximos 30 días
Lo que el tab "Hoy" del app necesita cada día. La reflexión y la oración guiada se programan publicándolas con fecha (pestaña Contenido → Publicar); aquí se ve qué días quedan descubiertos. El botón ➕ de un día sin pieza abre "Nuevo borrador" ya preparado para ese día.
🎙 Catálogo de voces (generación bajo demanda)
Los Voice ID están en elevenlabs.io → My Voices → ⋮ → Copy
Voice ID. Requisito del servidor (una sola vez, en tu terminal):
supabase secrets set ELEVENLABS_API_KEY=sk_… y
supabase functions deploy generate-audio
| Voz | Idioma | Género | Voice ID | Estado | Acciones |
|---|
| Fecha | Día litúrgico | Santo | Lecturas (es) | Reflexión | Oración |
|---|
Editar día
Lecturas de este día
| Tipo | Idioma | Contenido | Audio |
|---|
Nueva lectura
Cargar día completo (JSON)
Pega el arreglo JSON con todas las lecturas del día. Campos por
lectura: tipo (primera / salmo / segunda / evangelio),
idioma (es / en), fuente (título exacto o id de una
fuente ya existente), cita (pasaje, ej. «Mt 13, 24-43») y
texto o enlace (al menos uno; enlace = contingencia
de licencia). Si el día ya tiene una lectura del mismo tipo e idioma, se
reemplaza.
IA católica confiable cargando…
Un buscador que cita, no un oráculo: responde solo con el corpus
publicado y aprobado, cita cada afirmación o dice que no tiene fuente (spec 50).
Esta pestaña es el muestreo continuo del Advisor (guardrail 4) y el
interruptor de emergencia. La app además lleva la bandera compilada
kCatholicAiEnabled: apagar aquí es inmediato; encender aquí no
basta si el binario la trae apagada.
Corpus
Solo entra lo published de los tipos habilitados; los que exigen
dictamen necesitan además la firma del admin en cada pieza (Contenido → «Dictamen doctrinal»).
Salir de published saca la pieza del corpus en el acto.
| Tipo | Habilitado | Exige dictamen | Fragmentos (es / en) | Nota |
|---|
Cola de revisión del Advisor
| Fecha | Usuario | Pregunta y respuesta | Modo | Señales | Veredicto |
|---|
Métricas (14 días)
| Día | Preguntas | Respondidas | Sin fuente | Sensibles | Reportadas | Tokens in/out | p50 / p95 ms |
|---|
Configuración (solo admin)
IA de testimonios cargando…
Redacta el borrador guiado y traduce al enviar (mig. 0056). Genera texto, nunca doctrina — moderación editorial siempre antes de publicarse.
Síntesis de voz · gasto cargando…
ElevenLabs cobra por carácter, así que el tope va en caracteres, que es lo que factura el proveedor. Al llegar al tope se apaga solo y deja de sintetizar: los audios ya cacheados siguen sonando, solo se detiene lo nuevo. Volver a encenderlo es manual y deliberado.
El contenido del día (Evangelio, reflexión, oración, santo) cuesta ~2.500 caracteres al día por cada voz que lo pida; con una voz por idioma cabe en el plan. Los clips fijos siguen en las cuatro voces. Un capítulo de la Biblia en voz cuesta 8-9k: apagado, lo ya cacheado sigue sonando.
Editor IA de intenciones cargando…
Aprueba peticiones de oración evidentes y escala el resto a esta cola (mig. 0059, ADR-011). Solo aprueba: rechazar es siempre humano. Si se apaga, se queda sin presupuesto o falla, todo vuelve a la cola manual — ese es el modo degradado, no un error.
Estado del desarrollo · corte al 12-sep-2026 · PUBLICADA EN GOOGLE PLAY · GOOGLE PLAY: 31 PUBLICADO (13-sep) · APP STORE: EN REVISIÓN (reenviada el 12 y el 14-sep)
Instantánea estática del avance del proyecto; se actualiza con cada entrega. La versión completa e interactiva vive en el dashboard visual (requiere la cuenta del dueño).
main · 128 PRs fusionados · CI verdeLanzamiento v1.0 — Google Play y App Store
main antes del bump y ASC no admite repetir el 30 · Reenviada el 12-sep a las 16:50 (Waiting for Review): build 31, 9 capturas reales del iPhone 15 Pro Max en Spanish (Mexico), Notes con el vídeo del borrado (enlace de Drive y adjunto) y respuesta a App Review con el vídeo · ASC no dejó guardar la ficha en English (U.S.): el inglés pasa a la 1.0.1 · 13-sep, Google Play: el 31 enviado a Producción a las 18:20 y publicado esa misma noche, con la declaración de Foreground service (Media playback, con vídeo del Samsung) y el formulario de Seguridad de los datos reenviado, ya coherente con el borrado en la app; la verificación de desarrollador Android estaba registrada desde el 28-jul · 14-sep, segundo veredicto de Apple: un solo motivo, 2.1 «Information Needed» por China continental (la Biblia y el Catecismo cuentan como «contenido de libros» y exigen el Internet Publishing License de la NPPA); 2.3.10 y 5.1.1(v) ya no aparecen. Salida: China mainland fuera de la disponibilidad (174 países), respuesta a App Review y Resubmit a las 14:16 (ficha §11.5) · falta: el veredicto de Apple
90%
delete_my_account() SECURITY DEFINER (mig. 0064, en producción el 11-sep) borra auth.users y todo lo que cuelga, cede los grupos al miembro más antiguo y saca el MP3 del testimonio de Storage —el trigger de storage-api exige storage.allow_delete_query en la transacción, y eso solo salió al ejecutarlo— · en la app, Yo → Cuenta → Eliminar cuenta con doble confirmación, también en sesión anónima; humo en producción con una sesión anónima desechable (RPC 204, usuario inexistente después) · «Desvincular» se retiró: sin inicio de sesión por correo dejaba cuentas huérfanas con el correo quemado, y «Cancelar y usar otro correo» también borra la cuenta porque el enlace ya enviado seguía vivo una hora · «Ya confirmé» y «Reiniciar la sesión» quedan plegados bajo «¿Problemas para vincular?» · páginas web de borrado y política reescritas
✓
community_counters que solo suma, triggers para personas, intenciones, oraciones, testimonios y parroquias, y RPC community_event(kind, n) que la app llama al completar cada rezo (19 claves; nunca confesión ni examen; Rosario suma además 7 Padrenuestros, 56 Avemarías y 6 Glorias) · public_stats() lee la tabla: 16 cifras, 12 en la tarjeta de Hoy y todas en el Panel de este CMS · semilla: 248 personas y 378 parroquias; el resto arranca en 0 y se llena cuando el 31 llegue a los teléfonos · test RLS en el CI
✓
generate-audio era la ÚNICA función de IA sin presupuesto —las tres de texto sí lo tenían, y la de voz es la cara porque cobra por carácter— y la llave del caché incluía voice_label, una etiqueta editable: cada texto se había pagado 5 veces en español y 6 en inglés · El catálogo tenía ocho entradas para cuatro voces, cada par apuntando al mismo provider_voice_id · Arreglado (migs. 0060 y 0061): tope diario en caracteres con apagado automático y tarjeta en el CMS, y la llave pasa a provider_voice_id — renombrar o duplicar voces ya no cuesta nada. 112 filas duplicadas eliminadas; la clave primaria impide que vuelvan · 11/12-sep: el tope mensual se alcanzó (109.956 de 120.000 caracteres) y la voz se apagó sola en los builds 28 y 30 —el usuario veía «82 % consumido» porque la tarjeta muestra el diario— · se subió a 128.000 y reset_day pasa al 30, que es cuando renueva ElevenLabs · segunda causa encontrada de paso: cada voz sintetizaba en los dos idiomas (Jack leyendo español), y generate-audio ahora cambia la voz por la del idioma del texto y mismo género (vozParaIdioma, desplegada y verificada) · 13-sep: segundo apagado mensual (125.960 de 128.000) con el 31 en revisión; tope subido a 350.000 y síntesis probada · 14-sep, decisión del dueño: no se sube de plan. Medido del 6 al 13-sep: ~9.000 car./día (≈270k/mes); el contenido del día cuesta ~2.500/día por cada voz que lo pida y cada capítulo de la Biblia 8-9k · Frenos en producción (mig. 0066): el contenido del día se lee con una voz por idioma (Antonio / Jack) pida lo que pida el usuario, y la Biblia deja de sintetizarse en la nube (lo cacheado sigue sonando); el CMS muestra el consumo del periodo y edita voces, topes y el interruptor de la Biblia. Verificado con sesión desechable: Evangelio pedido con Carolina → Antonio cacheado; capítulo nuevo → 403 · falta: calibrar nuestro contador con el % del panel de ElevenLabs y, en la 1.0.1, voz del dispositivo para la Biblia
✓
docs/ficha-tiendas.md · Donaciones no se anuncia como función (sale apagada) · categorías, bundle com.oravia.app, soporte y URLs legales fijados
✓
FLAG_SECURE) · 8-sep: Apple rechazó las de iOS (2.3.10) porque llevan la barra de estado del emulador Android; se regeneran sin barra con tool/capturas/quitar_barra_android.py (carpetas ios-es-sin-barra / ios-en-sin-barra) y el juego inglés cargado en ASC tenía tres veces el Evangelio · las 20 sin barra están generadas y comprobadas píxel a píxel (verificar_sin_barra.py); las inglesas repetidas se retomaron en el AVD con la app en inglés · 12-sep: al final se cargaron 9 capturas reales tomadas en el iPhone 15 Pro Max con el 31 (ios-es-build31/), con la barra de iOS auténtica; las del emulador sin barra quedan de reserva. Lección: pasarlas por WhatsApp las reduce y ASC las rechaza por medida
✓
cuenta-confirmada.html es bilingüe (idioma del navegador o ?lang=) y avisa cuando el enlace caducó en vez de decir «confirmado» a todo · falta: revisión legal del texto y mover el CMS fuera de la raíz
85%
estudiovia.com): el DNS publica DKIM, SPF y DMARC. Era el bloqueador real — con el de fábrica había usuarios que nunca reciben el enlace · Plantilla «Change Email» bilingüe (11/12-sep, PRs #138–#140): dos botones, cada uno con su enlace de verificación y su página de aterrizaje en ese idioma; el pie conserva .ConfirmationURL de respaldo · «Reenviar correo» nunca enviaba para sesiones anónimas: GoTrue busca el usuario por el correo actual y responde 200 vacío; en el 31 reenviar vuelve a pedir la vinculación (y 429 = «espera un momento») · Gmail agrupa los correos de OraVia en una conversación: abrir siempre el más reciente · la plantilla final ya está pegada en Supabase: el correo del vídeo del 12-sep salió bilingüe, con los dos botones, y el inglés aterrizó en su página · para la 1.0.1, guardar el idioma del usuario para mandar un solo idioma
✓
db push --linked; antes hubo que meter al repo las 0062/0063 de audio, que estaban en producción desde el 31-ago pero solo existían como ficheros sueltos (PR #136). Seis Edge Functions desplegadas: ai-ask, ai-index, ai-testimony, ai-moderate-intention, generate-audio y send-push · Site URL puesta y SMTP propio (Resend sobre estudiovia.com), las dos verificadas desde fuera sin entrar al panel · calendario 417/417 y santoral 228/228 bilingües; contenido diario es+en programado hasta fin de 2028
✓
oravia-dist, perfil oravia_app_store, integración oravia-appstore, app creada en ASC y grupo externo de 12 testers aprobado. El 1.0.0 (27) pasó por TestFlight y se probó en dispositivo · Google Play Console abierta, y la prueba cerrada ya superada (29-ago): la pista de Producción está disponible, esperando su primera versión. Los cuatro secretos de firma Android están en GitHub desde el 23-ago, así que el AAB se compila solo desde el workflow «Build AAB tienda» · Solo iPhone resuelto y verificado: TARGETED_DEVICE_FAMILY = "1" en las tres configuraciones de main, junto al bump a +28 (PR #113). El cambio NO llegó al 27 — estuvo un rato solo en el árbol de trabajo que dos sesiones compartían, y la familia de dispositivos viaja dentro del IPA, así que hubo que recompilar · el 28 llegó a las dos tiendas; License Agreement aceptado el 10-sep y estatus de comerciante declarado el 11-sep, así que Codemagic vuelve a poder subir · el 31 entró en TestFlight y en la submission el 12-sep (el primer intento falló por compilar main antes del bump)
✓
/: una campaña con /explore/donations/submit abría el flujo real con la bandera apagada — el escenario que castiga la directriz 2.3.1 de Apple. Dos arreglos: redirect en cada subruta (en go_router el del padre no corre para las hijas) y lista blanca de rutas de notificación, que además frena las once rutas que exigen extra y tumbaban la app. Con dos guardas de regresión en la suite
✓
platform_summary() fallaba entera al agrupar por una columna de salida que llevaba un count() dentro, y el mensaje de error culpaba a una migración sin aplicar. Arreglado (0053) y ampliado con cola de moderación, encuesta de Donaciones, IA y Biblia. El bloque de eventos leía además la tabla equivocada. Ahora exige rol editorial: antes bastaba con tener cuenta en el app · 12-sep: tarjeta «Somos comunidad» con las mismas cifras históricas que la app (public_stats(), mig. 0065)
✓
clip_id no pasaba la lista blanca) y que los testimonios pagaban a ElevenLabs antes de fallar por un límite de 40 caracteres en clip_audio (mig. 0057) · falta: Novena, que depende de la elección del usuario y pide diseño aparte
✓
ai-moderate-intention + ADR-011). Relaja la regla dura «nada se publica directo» con límites que la mantienen segura: el trigger NO se toca, falla hacia lo seguro, solo aprueba —rechazar sigue siendo humano— y una crisis escala con prioridad y en silencio · Llevaba un día desplegada sin que la llamara nadie: encender la bandera no habría hecho nada. El disparador solo cabe en el cliente del autor, porque la función exige que quien pide la revisión sea el dueño · el criterio se relajó dos veces por corrección del dueño (nombrar a alguien y su enfermedad ya no escalan) · falta: correr los 30 casos de tool/intention_eval/ —solo se probaron 5— y decidir el encendido
85%
docs/guia-editorial-testimonios-crisis.md — protocolo para lo que hable de suicidio o autolesión: se retiene hasta que lo apruebe un profesional de la psicología. Escrito para un voluntario sin formación clínica; lo único que decide es la prisa del aviso · EN BORRADOR, no está en vigor: falta el canal y el suplente del responsable de escalada, y dónde vive el registro de retenciones · dos obstáculos técnicos que salió al escribirla: el bucket audio es público y ni Retirar ni Eliminar borran el MP3, y la política de lectura de testimony no admite revisor_teologico — hoy el profesional no puede leer un testimonio sin rol de editor sobre todas las colas
40%
checkout, upload-artifact, setup-java, intl, uuid y, el 23-ago, gradle-wrapper 9.7.1, drift_dev 2.34.5, firebase_core 4.13.0, youtube_player_iframe 5→6 y flutter_launcher_icons 0.14. Los cinco últimos, verdes en main uno por uno · Dos aplazados, los dos por el mismo motivo: el CI no los cubre. local_auth 2→3 rompe el build y su fallo abriría la puerta en vez de cerrarla; flutter_local_notifications 17→18 (#61) sí está verde, pero un verde de CI no prueba que el aviso llegue al teléfono — el #65 reescribió reminder_scheduler.dart, único fichero del repo que usa ese paquete. Los dos piden dispositivo real · el salto major de youtube_player_iframe pide la misma mirada: analyze no cubre que el reproductor de Recursos siga pintando · el despliegue de Azure ya no pide entorno de staging a PRs que no tocan el CMS — confirmado en el #61 y el #64, donde «Build and Deploy» ya ni aparece · falta: entornos huérfanos de Azure por limpiar en el portal
85%
Progreso por release
ai-index y ai-ask, embeddings Voyage voyage-3, pestaña IA del CMS, Biblia indexada (66.906 versículos, ~6.700 perícopas) y tool/ai_eval/ con 90 preguntas. Doble interruptor: kCatholicAiEnabled compilado y ai_config.enabled; ninguna respuesta sin cita · se prueba con el build interno 0.9.x (ios-testflight-ia-interna), que nunca va a tienda · falta: pasar los gates del eval y la decisión de encendido
85%
kDonationsPilotEnabled=false (constante compilada — directriz 2.3.1 de Apple; un test falla si se enciende por descuido): la entrada lleva a una antesala que explica la idea y recoge una encuesta de interés (mig. 0045, RLS por usuario) · pestaña Encuesta en este CMS con semáforo contra el umbral (100 respuestas · 60 % «la usaría» · 25 de una misma ciudad) · PR #65 cierra la puerta trasera por push (guardia en las 4 subrutas + lista blanca de 51 rutas notificables) · falta para lanzar: dictamen legal del disclaimer, elegir 2-3 parroquias piloto y aplicar 0045 en producción
90%
busy_timeout+WAL (se perdían entradas del diario), verificados en dispositivo
100%
celebration_en, santoral 228/228 con name_en/short_bio_en, citas de fuente citation_en (migraciones 0043-0044, en producción desde el 13-ago) · voces del catálogo con idioma (0042)
100%
Del 26 al 29-ago (PRs #100–#112): las 13
mejoras del 26-ago —muro multi-oración con cola, Gloria, badge por oración completada, fotos
comunitarias de parroquias, catecismo marcable, «Somos comunidad» con cifras públicas, lectura
guiada de planes y banner de descarga de audios— más la sección nueva de Testimonios
(asistente guiado + redacción con IA + traducción + voz clonada en los dos idiomas, migración
0056) · los 6 ajustes del 28-ago: borrado de parroquias solo para admin (0058), galería de fotos
en el CMS, visor con zoom sin dependencia nueva, y el editor IA del muro (0059 + ADR-011) ·
el 29-ago, audio en segundo plano resuelto de raíz y un repaso tras probar en el
teléfono: la ficha del mapa se estiraba a pantalla completa (2344 px de 2400), el chip «Solo
favoritos» caía en el píxel 6000 de una pantalla de 390 —guardar funcionaba, volver a verlo
no—, y compartir en Eventos era un botón muerto: Share.share sin
sharePositionOrigin hace que iOS se niegue a abrir la hoja, y sin catch
esa excepción se perdía.
Bloqueado por recursos externos
🔒 Profesional de la psicología para los testimonios que hablen de autolesión o suicidio — y con él, el canal y el suplente del responsable de escalada. Sin eso la
guia-editorial-testimonios-crisis.md sigue en borrador y no entra en vigor ·
🔒 ícono final (hoy es el placeholder de tool/gen_icon.py) ·
🔒 revisión legal de la política de privacidad + sign-off doctrinal ·
🔒 licencia litúrgica del Oficio · 🔒 Sentry · 🔒 datos reales de horarios de Misa ·
🔒 dictamen del disclaimer de donaciones + 2-3 parroquias piloto (bloquea el
encendido del R9.1, no la app).
Ya no bloquea nada de tienda: Play Console, keystore, SMTP propio, Site URL y la
cadena entera de iOS están resueltos.
Siguientes pasos · mientras Apple revisa
Esta semana, sin esperar a Apple — 1. Google Play con el 31 publicado el 13-sep
(Data Safety y Foreground service al día) · 2. Plantilla de correo bilingüe ya estaba en
Supabase (comprobado con el correo del 12-sep) · 3. ElevenLabs, decidido el 14-sep: no se sube
de plan. Medido del 6 al 13-sep: ~9.000 car./día (≈270k/mes) con picos de 17-19k los días en que
alguien escucha capítulos de la Biblia o usa una segunda voz; el contenido del día en una sola voz
cuesta ~2.500 car./día por idioma. Hecho el 14-sep (mig. 0066): una voz por idioma para el
contenido diario y la Biblia fuera de ElevenLabs, configurable desde la tarjeta de voz del CMS;
falta calibrar nuestro contador con el % del panel de ElevenLabs · 4. Vigilar el consumo de voz en la tarjeta del CMS y que
los contadores de «Somos comunidad» empiecen a subir cuando el 31 llegue a los teléfonos · 5. Correr
los 25 casos que faltan del clasificador de intenciones (tool/intention_eval/): está ENCENDIDO
en producción publicando sin humano con solo 5 de 30 verificados.
1.0.1, en ramas, sin tocar el binario en revisión —
6. «Iniciar sesión con mi correo» (OTP de Supabase) y «Cerrar sesión»: hoy una cuenta vinculada no
puede volver desde otro teléfono ni recuperarse si se borra la app; es lo que obligó a retirar
«Desvincular» · 7. Idioma del usuario en sus metadatos para que el correo de confirmación salga en
un solo idioma · 8. Ficha de App Store en inglés (ASC no dejó guardar English (U.S.) el 12-sep;
textos en ficha §3 y capturas en ios-en-sin-barra/) y las 9 capturas reales también en Play ·
9. Hallazgos del 12-sep: pie del mapa «© © OpenStreetMap» con el símbolo repetido, el texto de
Explorar «lo demás llega en su release» y el aviso «provisional y pendiente de dictamen» en la portada de
la Biblia · 10. Novena en la cola de audio sin huecos y scripts/testimony_rls_test.sql
(roto desde la 0061) de vuelta al CI.
Cuando Apple apruebe — 11. Publicar (sale sola:
«Automatically release»), cerrar el ciclo aquí y en la ficha, y avisar a los 12 probadores · 12.
Dependabot: pasar uno a uno los cinco verdes (#129, #132–#134, #150) y probar en dispositivo
just_audio 0.9→0.10 (#131, toca el audio en 2.º plano) y build_runner (#130, CI en
rojo) · 13. Crecimiento: las 25 ideas del 2-sep, empezando por el nivel A y la secuencia litúrgica ·
14. Contenido: 82 historias bíblicas, láminas #15 y #20, diócesis en parroquias, horarios reales de
Misa · 15. Lo bloqueado por terceros sigue igual: ícono, revisión legal, sign-off doctrinal,
profesional de psicología y Sentry (o Crashlytics, que ya tiene firebase_core).