Sistema de Información de Víctimas
Proyecto de emergencia — Terremoto en Venezuela, junio 2025
📖 Contexto
SIVIV nació como respuesta inmediata al terremoto que afectó Venezuela en junio de 2025. Su objetivo era centralizar la información de personas ingresadas en hospitales y centros de atención, permitiendo a familiares buscar a sus seres queridos por nombre, apellido o cédula.
La aplicación se diseñó con tres principios:
- Ligereza extrema: un solo archivo HTML, sin build step, sin dependencias de servidor
- Resiliencia: funciona en conexiones deficientes (2G/3G), común en zonas de emergencia
- Privacidad: sin tracking, sin cookies, sin registro de usuarios
Durante su operación, SIVIV procesó más de 500 registros de pacientes distribuidos en múltiples centros de atención en el estado Anzoátegui y zonas aledañas.
🏗️ Arquitectura
| Capa | Tecnología | Rol |
|---|---|---|
| Frontend | Vue 3 + Tailwind CSS (CDN) |
Buscador público + Panel admin |
| Proxy / API | Cloudflare Pages Function |
Cache (60s), rate limit (30 req/min), auth admin |
| Base de datos | Supabase (PostgreSQL) |
Registros + búsqueda full-text (pg_trgm) |
| Hosting | Cloudflare Pages |
Edge deployment global, SSL, CDN |
🔌 API
La API es un proxy sobre Supabase REST, alojado como Cloudflare Pages Function. Se mantiene activa como legado del proyecto.
Base URL
https://siviv.pages.dev/api
Endpoints
La API expone la tabla pacientes de Supabase vía REST:
| Método | Ruta | Descripción | Auth |
|---|---|---|---|
| GET | /rest/v1/pacientes |
Listar/buscar pacientes | Público |
| POST | /rest/v1/pacientes |
Insertar paciente | Admin Key |
| DELETE | /rest/v1/pacientes?id=eq.X |
Eliminar paciente | Admin Key |
Parámetros de búsqueda (GET)
La API acepta todos los operadores de Supabase REST:
GET /api/rest/v1/pacientes?select=nombre,apellido,centro&nombre=ilike.%maria%&limit=10
| Parámetro | Ejemplo | Descripción |
|---|---|---|
select | nombre,apellido,edad | Columnas a retornar |
nombre | ilike.%maria% | Filtro case-insensitive |
or | (nombre.ilike.%X%,apellido.ilike.%X%) | OR lógico entre condiciones |
order | created_at.desc | Ordenamiento |
limit | 50 | Máx resultados (default 50) |
Autenticación (POST / DELETE)
fetch('https://siviv.pages.dev/api/rest/v1/pacientes', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-admin-key': '<ADMIN_KEY>'
},
body: JSON.stringify({
nombre: 'María',
apellido: 'González',
edad: 34,
centro: 'Hospital Central'
})
})
Cabeceras de respuesta
| Header | Valor | Significado |
|---|---|---|
x-siviv-cache | HIT / MISS | Cache de 60s en el edge |
cache-control | public, max-age=60 | Caché en CDN |
🗄️ Esquema de datos
CREATE TABLE public.pacientes ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, nombre TEXT NOT NULL, apellido TEXT NOT NULL, edad INTEGER, cedula TEXT, centro TEXT NOT NULL, created_at TIMESTAMPTZ DEFAULT now() ); -- Índices para búsqueda rápida CREATE INDEX idx_pacientes_nombre_trgm ON pacientes USING GIN (nombre gin_trgm_ops); CREATE INDEX idx_pacientes_apellido_trgm ON pacientes USING GIN (apellido gin_trgm_ops); CREATE INDEX idx_pacientes_cedula ON pacientes (cedula); -- Seguridad: Row Level Security ALTER TABLE pacientes ENABLE ROW LEVEL SECURITY; CREATE POLICY "lectura_publica" ON pacientes FOR SELECT USING (true); CREATE POLICY "registro_publico" ON pacientes FOR INSERT WITH CHECK (true); CREATE POLICY "admin_delete" ON pacientes FOR DELETE USING (true);
⚠️ Limitaciones
- Rate limit: 30 peticiones por minuto por IP
- Resultados máximos: 50 por consulta (paginar con
limit+offset) - Cache: GET requests tienen cache de 60s en el edge
- Sin autenticación de usuarios: el sistema fue diseñado para acceso público en contexto de emergencia
- Plan gratuito de Supabase: sujeto a límites de bandwidth y conexiones simultáneas
📦 Repositorio
Código fuente disponible en GitHub:
Toyoenohio/SIVIV