alerta-produccionmain → avivet.cl/registro-productivo-avicola/src/shared.js ← común a producción y módulo (Supabase, sesión, resolverOwner, hoy/fmtFecha/toast)
src/supabase/ ← app nueva: una URL, todos los productores, auth real
migrations/ ← migraciones SQL numeradas + ledger (README.md); schema_migrations registra lo aplicado
supabase/functions/ ← Edge Functions (alerta-produccion, aviso-invitacion)
src/avicolas/<nombre>/ ← apps GAS heredadas: una URL por productor (en mantención)
dashboard.html ← Monitor de Producción del asesor (Supabase): todos los productores, resumen semanal/mensual, exportación
index.html. No hay API intermediaria.supabase/functions/<nombre>/index.ts (fuente de verdad). Se despliegan pegando ese archivo en el Dashboard → Edge Functions, o con scripts/deploy-functions.sh (Supabase CLI, opcional).migrations/NNN_nombre.sql (idempotente, con guarda de orden y auto-registro en schema_migrations; ver migrations/README.md). Nunca SQL suelto en otras carpetas.registros: los agregados (stock por tamaño, cuadre, alimento) los calcula la función SQL stock_resumen (migrations/009_stock_resumen.sql, security invoker → RLS aplica). Si cambias columnas que entran en esos totales, actualiza la función, no el JS. p_hoy se pasa desde el cliente en hora local.src/shared.js se carga con <script src="../shared.js?v=N"> DESPUÉS de supabase-js y ANTES del script de la app. Si cambias shared.js, sube el ?v=N en las dos apps para que el navegador no use la copia en caché. Las funciones de sesión, resolverOwner, hoy, fmtFecha y toast viven SOLO ahí: no las redeclares en una app (el CI lo detecta).python3 scripts/validar-apps.py (es lo mismo que corre el CI en cada PR). Si falla, el PR queda en rojo.SUPABASE_KEY (anon key) como secreto — es pública por diseño de Supabase RLS.d.toLocaleDateString('en-CA') (YYYY-MM-DD). NUNCA toISOString().slice(0,10) para fechas de negocio — es UTC y en Chile desde ~21:00 devuelve el día siguiente (marcaba lotes al día como atrasados). toISOString() solo para timestamps (updated_at).vet_admin_lotes / vet_admin_registros (SELECT para el correo del asesor). Las políticas *_read_public (USING (true)) se eliminaron: rompían el aislamiento entre productores.verificarAlertas() es fire-and-forget: se llama sin await en guardarRegistro. Si falla, queda en console.warn sin interrumpir el flujo.lotes_produccion y registros.ALERTA_FROM) debe ser un dominio verificado en Resend. onboarding@resend.dev solo funciona en modo test de Resend.Edge Function alerta-produccion activa desde 2026-04-29. Secrets ya configurados en Supabase:
RESEND_API_KEY ✅ALERTA_EMAIL → andres.lazomv@outlook.com ✅ALERTA_FROM → alertas@avivet.cl ✅Condiciones que disparan alerta: mortalidad > 0,30% del lote, o caída de postura > 3% en un día.
Hy-line Brown, Lohmann Brown, Bovans Brown, ISA Brown — curvas de postura hardcodeadas en index.html.