🧱 Ejecutar las migrations
Las migrations son archivos .sql versionados en agent/supabase/migrations/ que describen toda la base de datos. Llevarlas a tu proyecto Supabase crea, de una vez, las 14 tablas y activa la extensión pgvector — todo mediante la primera migración, la 0001_init.sql. No creas las tablas manualmente: el esquema ya viene listo en el blueprint.
🟢 ¿Nuevo por aquí?
- Migration — un archivo SQL numerado que aplica un cambio en la base de datos. Ejecutarlos todos, en orden, reconstruye el esquema desde cero en cualquier proyecto.
- Supabase CLI — la herramienta de línea de comandos de Supabase. Ella conecta tu carpeta local con tu proyecto en la nube y impulsa las migrations para allá.
📊 Cómo leer: de izquierda a derecha, los archivos SQL se convierten en la base de datos real. Los cuadros azules con brillo son donde ocurre la acción (la CLI y el resultado); los cian son el origen y el destino. El secreto es que el esquema está en un archivo, no en tu memoria.
# 1) na raiz do repo, ligue ao seu projeto (pede a senha do banco)
supabase link --project-ref <seu-project-ref>
# 2) empurre TODAS as migrations de agent/supabase/migrations/
supabase db push
0001_init.sql) sin errores. En el panel de Supabase, en Table Editor, aparecen las 14 tablas; en Database → Extensions, vector está habilitada.💡 De dónde viene la contraseña
O supabase link usa la SUPABASE_DB_PASSWORD que guardaste en el ~/.env (Módulo 2.1). El <seu-project-ref> es el identificador del proyecto —aparece en la URL https://<ref>.supabase.co y en Settings.
Conceptos clave
SQL numerado que reconstruye el esquema.
Crea las 14 tablas y activa pgvector.
Un comando aplica todo en la nube.
Reproducible en cualquier proyecto.
📋 Las 14 tablas — descripción general
Cada cosa que registras se convierte en fila en una tabla. El esquema abarca las familias de datos de salud — comida, entrenamiento, peso, composición corporal, cafeína, suplementos, signos vitales, exámenes, check-ins, metas y contexto — además de la memoria semántica de los mensajes. El diagrama muestra cómo las fuentes alimentan las tablas y cómo el coach vuelve a leerlas.
📊 Cómo leer: las fuentes (cian, a la izquierda) escriben en las tablas (centro); el coach (azul) lee la instantánea de esas tablas y responde. La tabla messages se destaca porque es la única que guarda vectores (la memoria semántica — Tema 3).
Comida → macros + flags.
Entrenamientos registrados.
Pesajes (tendencia).
Composición corporal.
Cafeína a lo largo del día.
Suplementos y horarios.
PA, recovery, HRV, RHR, sueño.
Marcadores de sangre.
Registros diarios.
Tus metas.
Perfil y contexto fijo.
Memoria semántica (vector).
Estas 12 familias de datos + tablas de apoyo (como coach_summary, que guarda la recuperación y su causa) completan las 14 tablas que crea la migration.
Conceptos clave
Cada registro se convierte en una fila de una tabla.
Una tabla por tipo de dato.
El coach lee un resumen de esas tablas.
La única con vectores (memoria).
🧲 pgvector — la memoria
La migration 0001_init.sql conecta el pgvector antes de crear las tablas. Es lo que le da a la base de datos la capacidad de guardar la memoria semántica — buscar mensajes anteriores por significado, no por una palabra exacta.
🟢 ¿Nuevo por aquí? Qué es pgvector
pgvector es una extensión de PostgreSQL que agrega un nuevo tipo de columna: vector. Cada mensaje se convierte en un embedding (una lista de números que representa el significado del texto). pgvector compara estos vectores y encuentra lo que es parecido en significado — así el coach «recuerda» cuando hablaste del sueño, aunque no aparezca la palabra «sueño».
📊 Cómo leer: el texto se convierte en números (embedding), pgvector los guarda y luego los compara por distancia. Cuanto más cerca están dos vectores, más parecido es su significado: así es como la memoria recupera el pasado relevante.
🔌 No conectas manualmente
No necesitas ejecutar ningún comando extra: el create extension vector ya está dentro de la 0001_init.sql. Cuando hiciste el db push del Tema 1, pgvector ya quedó habilitado. Aquí solo tienes que entender por qué existe.
Conceptos clave
Extensión que almacena vectores en Postgres.
Números que representan el significado.
Encuentra lo parecido por distancia.
La 0001_init.sql hace eso por ti.
🪣 El bucket de almacenamiento de fotos
Las tablas guardan números y texto; las fotos (comida, análisis, cuerpo) van a un bucket de storage. HealthOS usa un bucket llamado health-assets, creado con un solo comando —y él es privado.
🟢 ¿Nuevo por aquí?
Bucket — es una "carpeta" de almacenamiento de archivos en Supabase, separada de las tablas. Privado significa que nadie accede a un archivo mediante la URL pública; solo el servidor, con la clave correcta, genera un enlace temporal para leerlo.
health-assets dónde se guardarán las fotos.# um comando cria o bucket PRIVADO de fotos
python3 agent/scripts/db.py mkbucket health-assets
health-assets aparece marcado como Private (no público). Puedes volver a ejecutarlo sin problema: no duplica.✓ Bucket privado (el correcto)
- ✓Las fotos de salud no se filtran mediante URL públicas.
- ✓El servidor genera enlaces temporales cuando hace falta.
- ✓Es el patrón que el
mkbucketya lo aplica.
✗ Bucket público (no lo hagas)
- ✗Cualquiera con la URL podría ver la foto de tu examen.
- ✗Datos de salud sensibles expuestos a internet.
- ✗No se puede «despublicar» lo que ya se filtró.
Conceptos clave
Almacenamiento de archivos, fuera de las tablas.
El bucket de fotos de HealthOS.
Sin URL pública; solo el servidor lo lee.
Un comando crea todo correctamente.
🔒 RLS — bloquear la base de datos
El esquema conecta el RLS (Row-Level Security) en cada tabla y no crea ninguna política. El efecto es radical y sencillo: la clave pública (anon) no lee nada; solo el servidor, con la clave service-role, atraviesa. Es el bloqueo estándar de HealthOS.
🟢 ¿Nuevo por aquí? Dos claves, dos mundos
- RLS — recurso de Postgres que decide, fila por fila, quién puede leer/escribir. Sin una política que lo permita, el comportamiento predeterminado es denegar.
- service-role — la clave de servidor. Ella elude la RLS (la omite), así que el agente lee y escribe con normalidad. Solo vive en
~/.env, nunca en el navegador. - anon — la clave pública, segura de exponer. Con RLS activada y cero políticas, esta no lee nada.
📊 Cómo leer: las dos claves llegan a la misma puerta (la RLS). La service-role (verde) pasa por encima y llega a las tablas; la anon (rojo, discontinuo) choca con la X y vuelve. Por eso es seguro exponer la clave pública.
✓ service-role (servidor)
- ✓Lee y escribe en todas las tablas.
- ✓Omite la RLS (pasa por encima).
- ✓Se limita a
~/.env, en el servidor.
✗ anon (pública)
- ✗No lee ninguna línea (RLS sin política).
- ✗No escribe nada.
- ✓Por eso es segura de exponer si hace falta.
Conceptos clave
Activada para todo, sin políticas = deniega.
La clave del servidor omite la RLS.
La clave pública no lee nada.
Privado por diseño, sin necesidad de configurar nada.
🔌 Probar la conexión
Antes de seguir con el agente, comprueba que el servidor se comunica con la base de datos. El db.py es la utilidad de base de datos de HealthOS; un select simple confirma que las claves del ~/.env están correctas y que la RLS permite el acceso del servidor.
goals).# lê as linhas da tabela goals usando a chave service-role do ~/.env
python3 agent/scripts/db.py select goals
goals (o una lista vacía [] si todavía no cambiaste el seed de ejemplo). Sin errores de conexión/autenticación = claves y RLS OK. Cambia goals por <outra-tabela> para inspeccionar cualquiera de las 14.🧪 Si da error
- •¿Falló la autenticación? A
SUPABASE_SERVICE_ROLE_KEYo laSUPABASE_URLen el~/.envestá equivocada. - •¿No existe la tabla? O
db pushdel Tema 1 no se ejecutó por completo — repítelo. - •¿La lista está vacía? Esto es un éxito de conexión: solo falta el seed (Tema 7).
✅ Autoevaluación (opcional): por qué el db.py select goals puede leer, si RLS está habilitada?
Conceptos clave
La utilidad de base de datos de HealthOS.
Prueba mínima de conexión.
Claves y RLS en funcionamiento.
Conexión correcta, solo falta el seed.
🌱 Seed y datos sensibles
La migration 0002_seed_example.sql planta uno seed de ejemplo (genérico, sin datos reales), solo para que veas el formato. El último paso es reemplazar este ejemplo por tus tus metas y contexto — y conserva tu seed real y tu CLAUDE.md fuera de git.
🟢 ¿Nuevo por aquí?
- Seed — datos iniciales que «siembran» la base de datos. El ejemplo es genérico; el tuyo, el real, va en las tablas
goalsecontext. - Fuera de Git — el repositorio es el plano limpio. Tus valores reales quedan solo en tu máquina/base de datos; se incluyen en el
.gitignorey nunca se versionan.
✓ Puedes versionar
- ✓Las migrations del esquema (
0001_init.sql). - ✓O
0002_seed_example.sqlgenérico. - ✓O
CLAUDE.mdmodelo (en blanco).
✗ Nunca versionar
- ✗Tu seed real (goals + context completados).
- ✗Tu
CLAUDE.mdcon un perfil real. - ✗O
~/.envy tus fotos.
⚠️ Los datos de salud son sensibles
Un seed real en un commit es una filtración permanente: el historial de git lo guarda todo. Antes de cualquier git add, confirma que los goals/context reales, CLAUDE.md completado y ~/.env están en el .gitignore. El repositorio público debe conservarse como el blueprint scrubbed, sin información personal.
Conceptos clave
Datos iniciales de la base de datos.
Reemplaza 0002 por tus metas+context.
El Seed real y CLAUDE.md no se versionan.
El repo público no contiene datos personales.
📋 Resumen del módulo
supabase db push crea las 14 tablas y conecta pgvector (0001_init.sql).db.py select goals confirma todo; el seed real y CLAUDE.md quedan fuera de git.Próximo módulo:
2.3 — El agente y el bot: darle vida al coach en Telegram, conectar el agente a la base de datos que acabas de configurar y responder al primer mensaje.