496 lines
17 KiB
Markdown
496 lines
17 KiB
Markdown
|
|
# 🏗️ ARQUITECTURA SERVIDOR DE CONTENIDO - TES
|
||
|
|
|
||
|
|
**Versión:** 1.0.0
|
||
|
|
**Fecha:** 2025-01-06
|
||
|
|
**Estado:** Diseño Técnico - Sin Implementación
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 PRINCIPIOS FUNDAMENTALES
|
||
|
|
|
||
|
|
1. **Servidor Propio**
|
||
|
|
- ✅ PostgreSQL en nuestro servidor
|
||
|
|
- ✅ API REST de solo lectura para app
|
||
|
|
- ✅ Panel admin separado (solo editores)
|
||
|
|
- ❌ NO Supabase
|
||
|
|
- ❌ NO servicios externos
|
||
|
|
- ❌ NO CMS externo
|
||
|
|
|
||
|
|
2. **App PWA (Solo Consumo)**
|
||
|
|
- ✅ Consume Content Pack JSON
|
||
|
|
- ✅ Funciona offline-first
|
||
|
|
- ✅ Cache local (IndexedDB)
|
||
|
|
- ❌ NO edita contenido
|
||
|
|
- ❌ NO tiene panel admin
|
||
|
|
|
||
|
|
3. **Separación Clara**
|
||
|
|
- Servidor → Genera Content Pack
|
||
|
|
- App → Consume Content Pack
|
||
|
|
- Panel Admin → Edita en servidor
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📐 ARQUITECTURA GENERAL
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────────────────────┐
|
||
|
|
│ SERVIDOR PROPIO │
|
||
|
|
├─────────────────────────────────────────────────────────┤
|
||
|
|
│ │
|
||
|
|
│ ┌──────────────────────────────────────────────────┐ │
|
||
|
|
│ │ PostgreSQL Database │ │
|
||
|
|
│ │ ├── content_items │ │
|
||
|
|
│ │ ├── media_resources │ │
|
||
|
|
│ │ ├── associations │ │
|
||
|
|
│ │ ├── versions │ │
|
||
|
|
│ │ └── audit_logs │ │
|
||
|
|
│ └──────────────────────────────────────────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
│ │ │
|
||
|
|
│ ┌──────────────────────────────────────────────────┐ │
|
||
|
|
│ │ API REST (Node.js + Express) │ │
|
||
|
|
│ │ ├── GET /api/content/pack/latest │ │
|
||
|
|
│ │ ├── GET /api/content/pack/:version │ │
|
||
|
|
│ │ ├── GET /api/content/protocol/:id │ │
|
||
|
|
│ │ ├── GET /api/content/guide/:id │ │
|
||
|
|
│ │ └── GET /api/health │ │
|
||
|
|
│ │ (SOLO LECTURA - Sin autenticación para app) │ │
|
||
|
|
│ └──────────────────────────────────────────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
│ │ │
|
||
|
|
│ ┌──────────────────────────────────────────────────┐ │
|
||
|
|
│ │ Panel Admin (React - Puerto 5174) │ │
|
||
|
|
│ │ ├── Editor de contenido │ │
|
||
|
|
│ │ ├── Gestor de recursos │ │
|
||
|
|
│ │ ├── Validación clínica │ │
|
||
|
|
│ │ └── Exportación de packs │ │
|
||
|
|
│ │ (REQUIERE AUTENTICACIÓN) │ │
|
||
|
|
│ └──────────────────────────────────────────────────┘ │
|
||
|
|
│ │ │
|
||
|
|
│ │ │
|
||
|
|
│ ┌──────────────────────────────────────────────────┐ │
|
||
|
|
│ │ Generador Content Pack │ │
|
||
|
|
│ │ ├── Lee de PostgreSQL │ │
|
||
|
|
│ │ ├── Genera JSON optimizado │ │
|
||
|
|
│ │ ├── Calcula hash SHA-256 │ │
|
||
|
|
│ │ └── Guarda en /packs/ │ │
|
||
|
|
│ └──────────────────────────────────────────────────┘ │
|
||
|
|
│ │
|
||
|
|
└─────────────────────────────────────────────────────────┘
|
||
|
|
│
|
||
|
|
│ (Content Pack JSON)
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────────────────────────────────┐
|
||
|
|
│ APP PWA (Frontend) │
|
||
|
|
├─────────────────────────────────────────────────────────┤
|
||
|
|
│ ┌──────────────────────────────────────────────────┐ │
|
||
|
|
│ │ Service Worker │ │
|
||
|
|
│ │ ├── Descarga pack al iniciar │ │
|
||
|
|
│ │ ├── Cache en IndexedDB │ │
|
||
|
|
│ │ └── Funciona 100% offline │ │
|
||
|
|
│ └──────────────────────────────────────────────────┘ │
|
||
|
|
│ │
|
||
|
|
│ ┌──────────────────────────────────────────────────┐ │
|
||
|
|
│ │ Content Adapter │ │
|
||
|
|
│ │ ├── Lee de cache local │ │
|
||
|
|
│ │ ├── Fallback a procedures.ts si no hay pack │ │
|
||
|
|
│ │ └── Sin modificar código existente │ │
|
||
|
|
│ └──────────────────────────────────────────────────┘ │
|
||
|
|
└─────────────────────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🗄️ BASE DE DATOS (PostgreSQL)
|
||
|
|
|
||
|
|
### Esquema: `tes_content`
|
||
|
|
|
||
|
|
**Justificación:**
|
||
|
|
- Schema dedicado para contenido
|
||
|
|
- Separado de otros datos del sistema
|
||
|
|
- Fácil backup y migración
|
||
|
|
|
||
|
|
### Tablas Principales
|
||
|
|
|
||
|
|
Ver `docs/SERVER_DATABASE_SCHEMA.sql` (se creará a continuación)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔌 API REST (Solo Lectura)
|
||
|
|
|
||
|
|
### Endpoints Públicos (Sin Autenticación)
|
||
|
|
|
||
|
|
#### 1. Health Check
|
||
|
|
```
|
||
|
|
GET /api/health
|
||
|
|
```
|
||
|
|
**Respuesta:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"status": "ok",
|
||
|
|
"timestamp": "2025-01-06T12:00:00Z",
|
||
|
|
"database": "connected",
|
||
|
|
"latest_pack_version": "1.0.0"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 2. Content Pack Latest
|
||
|
|
```
|
||
|
|
GET /api/content/pack/latest
|
||
|
|
```
|
||
|
|
**Respuesta:** Content Pack JSON completo (ver especificación)
|
||
|
|
|
||
|
|
**Headers:**
|
||
|
|
- `If-None-Match: <hash>` - Para validar si hay cambios
|
||
|
|
- `ETag: <hash>` - Hash del pack en respuesta
|
||
|
|
|
||
|
|
#### 3. Content Pack por Versión
|
||
|
|
```
|
||
|
|
GET /api/content/pack/:version
|
||
|
|
```
|
||
|
|
**Ejemplo:** `GET /api/content/pack/1.0.0`
|
||
|
|
|
||
|
|
#### 4. Protocolo Individual
|
||
|
|
```
|
||
|
|
GET /api/content/protocol/:slug
|
||
|
|
```
|
||
|
|
**Ejemplo:** `GET /api/content/protocol/rcp-adulto-svb`
|
||
|
|
|
||
|
|
**Respuesta:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"id": "...",
|
||
|
|
"type": "protocol",
|
||
|
|
"slug": "rcp-adulto-svb",
|
||
|
|
"title": "RCP Adulto - Soporte Vital Básico",
|
||
|
|
"content": { ... },
|
||
|
|
"resources": {
|
||
|
|
"images": [...],
|
||
|
|
"videos": [...]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 5. Guía Individual
|
||
|
|
```
|
||
|
|
GET /api/content/guide/:slug
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 6. Recurso Multimedia
|
||
|
|
```
|
||
|
|
GET /api/content/media/:id
|
||
|
|
```
|
||
|
|
**Respuesta:** URL del recurso o redirección a archivo
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Endpoints Admin (Con Autenticación)
|
||
|
|
|
||
|
|
Ver sección "Panel Admin" más abajo.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📦 CONTENT PACK JSON
|
||
|
|
|
||
|
|
### Estructura (Optimizada para Offline)
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"metadata": {
|
||
|
|
"version": "1.0.0",
|
||
|
|
"generated_at": "2025-01-06T12:00:00Z",
|
||
|
|
"hash": "sha256:abc123...",
|
||
|
|
"total_items": 45,
|
||
|
|
"total_resources": 120,
|
||
|
|
"size_bytes": 5242880
|
||
|
|
},
|
||
|
|
"content": {
|
||
|
|
"protocols": [...],
|
||
|
|
"guides": [...],
|
||
|
|
"manuals": [...],
|
||
|
|
"drugs": [...],
|
||
|
|
"checklists": [...]
|
||
|
|
},
|
||
|
|
"media": {
|
||
|
|
"resources": [...],
|
||
|
|
"associations": [...]
|
||
|
|
},
|
||
|
|
"links": {
|
||
|
|
"protocol_to_guide": [...],
|
||
|
|
"guide_to_protocol": [...],
|
||
|
|
"manual_to_protocols": [...]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Características:**
|
||
|
|
- ✅ Solo contenido `published`
|
||
|
|
- ✅ Solo última versión
|
||
|
|
- ✅ Recursos asociados incluidos
|
||
|
|
- ✅ Enlaces bidireccionales pre-calculados
|
||
|
|
- ✅ Hash SHA-256 para verificación
|
||
|
|
- ✅ Tamaño optimizado (< 10MB recomendado)
|
||
|
|
|
||
|
|
**Ubicación en Servidor:**
|
||
|
|
```
|
||
|
|
/packs/
|
||
|
|
├── pack-v1.0.0.json
|
||
|
|
├── pack-v1.1.0.json
|
||
|
|
└── pack-latest.json (symlink)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎛️ PANEL ADMIN (Conceptual)
|
||
|
|
|
||
|
|
### Arquitectura
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ Panel Admin (React - Puerto 5174) │
|
||
|
|
├─────────────────────────────────────────┤
|
||
|
|
│ ┌───────────────────────────────────┐ │
|
||
|
|
│ │ Auth (JWT) │ │
|
||
|
|
│ │ - Login en servidor │ │
|
||
|
|
│ │ - Token almacenado localmente │ │
|
||
|
|
│ └───────────────────────────────────┘ │
|
||
|
|
│ ┌───────────────────────────────────┐ │
|
||
|
|
│ │ Editor de Protocolo │ │
|
||
|
|
│ │ - Tabs: Básico, Pasos, Checklist │ │
|
||
|
|
│ │ - Preview "Modo TES" │ │
|
||
|
|
│ │ - Guarda en servidor via API │ │
|
||
|
|
│ └───────────────────────────────────┘ │
|
||
|
|
│ ┌───────────────────────────────────┐ │
|
||
|
|
│ │ Gestor de Recursos │ │
|
||
|
|
│ │ - Upload a servidor │ │
|
||
|
|
│ │ - Asociar a contenido │ │
|
||
|
|
│ └───────────────────────────────────┘ │
|
||
|
|
│ ┌───────────────────────────────────┐ │
|
||
|
|
│ │ Generador de Pack │ │
|
||
|
|
│ │ - Botón "Generar Pack" │ │
|
||
|
|
│ │ - Seleccionar versión │ │
|
||
|
|
│ │ - Descargar JSON │ │
|
||
|
|
│ └───────────────────────────────────┘ │
|
||
|
|
└─────────────────────────────────────────┘
|
||
|
|
│
|
||
|
|
│ (API REST con Auth)
|
||
|
|
▼
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ API Admin (Node.js + Express) │
|
||
|
|
│ - POST /api/admin/content │
|
||
|
|
│ - PUT /api/admin/content/:id │
|
||
|
|
│ - POST /api/admin/media │
|
||
|
|
│ - POST /api/admin/pack/generate │
|
||
|
|
└─────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### Endpoints Admin
|
||
|
|
|
||
|
|
#### Autenticación
|
||
|
|
```
|
||
|
|
POST /api/admin/auth/login
|
||
|
|
POST /api/admin/auth/logout
|
||
|
|
GET /api/admin/auth/me
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Contenido
|
||
|
|
```
|
||
|
|
GET /api/admin/content # Lista con filtros
|
||
|
|
GET /api/admin/content/:id # Detalle
|
||
|
|
POST /api/admin/content # Crear
|
||
|
|
PUT /api/admin/content/:id # Actualizar
|
||
|
|
DELETE /api/admin/content/:id # Eliminar (soft delete)
|
||
|
|
POST /api/admin/content/:id/validate # Solicitar validación
|
||
|
|
POST /api/admin/content/:id/publish # Publicar
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Recursos
|
||
|
|
```
|
||
|
|
GET /api/admin/media # Lista
|
||
|
|
POST /api/admin/media/upload # Upload archivo
|
||
|
|
PUT /api/admin/media/:id # Actualizar metadatos
|
||
|
|
DELETE /api/admin/media/:id # Eliminar
|
||
|
|
POST /api/admin/media/:id/associate # Asociar a contenido
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Content Pack
|
||
|
|
```
|
||
|
|
POST /api/admin/pack/generate # Generar nuevo pack
|
||
|
|
GET /api/admin/pack/versions # Lista de versiones
|
||
|
|
GET /api/admin/pack/:version # Descargar pack específico
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔒 SEGURIDAD
|
||
|
|
|
||
|
|
### API Pública (App)
|
||
|
|
- ✅ Sin autenticación (solo lectura)
|
||
|
|
- ✅ Rate limiting (100 req/min por IP)
|
||
|
|
- ✅ CORS configurado (solo dominios permitidos)
|
||
|
|
- ✅ Validación de inputs
|
||
|
|
|
||
|
|
### API Admin
|
||
|
|
- ✅ Autenticación JWT obligatoria
|
||
|
|
- ✅ RBAC (Roles: editor, validador, admin)
|
||
|
|
- ✅ Rate limiting (50 req/min por usuario)
|
||
|
|
- ✅ Validación de permisos por endpoint
|
||
|
|
- ✅ Audit log de todas las acciones
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📁 ESTRUCTURA DE DIRECTORIOS (Servidor)
|
||
|
|
|
||
|
|
```
|
||
|
|
server/
|
||
|
|
├── config/
|
||
|
|
│ ├── database.js # Config PostgreSQL
|
||
|
|
│ └── storage.js # Config almacenamiento archivos
|
||
|
|
├── database/
|
||
|
|
│ ├── migrations/
|
||
|
|
│ │ ├── 001_create_schema.sql
|
||
|
|
│ │ └── 002_create_tables.sql
|
||
|
|
│ └── seeds/
|
||
|
|
│ └── initial_data.sql
|
||
|
|
├── src/
|
||
|
|
│ ├── api/
|
||
|
|
│ │ ├── public/ # Endpoints públicos (app)
|
||
|
|
│ │ │ ├── health.js
|
||
|
|
│ │ │ ├── content-pack.js
|
||
|
|
│ │ │ └── content.js
|
||
|
|
│ │ └── admin/ # Endpoints admin
|
||
|
|
│ │ ├── auth.js
|
||
|
|
│ │ ├── content.js
|
||
|
|
│ │ ├── media.js
|
||
|
|
│ │ └── pack.js
|
||
|
|
│ ├── services/
|
||
|
|
│ │ ├── content-service.js
|
||
|
|
│ │ ├── media-service.js
|
||
|
|
│ │ └── pack-generator.js # Generador de Content Pack
|
||
|
|
│ ├── middleware/
|
||
|
|
│ │ ├── auth.js
|
||
|
|
│ │ ├── rbac.js
|
||
|
|
│ │ └── rate-limit.js
|
||
|
|
│ └── utils/
|
||
|
|
│ ├── validation.js
|
||
|
|
│ └── hash.js
|
||
|
|
├── storage/
|
||
|
|
│ ├── media/
|
||
|
|
│ │ ├── images/
|
||
|
|
│ │ └── videos/
|
||
|
|
│ └── packs/
|
||
|
|
│ ├── pack-v1.0.0.json
|
||
|
|
│ └── pack-latest.json
|
||
|
|
├── admin-panel/ # Panel admin (React)
|
||
|
|
│ └── (ya existe)
|
||
|
|
└── index.js # Servidor Express principal
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔄 FLUJO DE TRABAJO
|
||
|
|
|
||
|
|
### 1. Editor Crea Contenido
|
||
|
|
```
|
||
|
|
Editor → Panel Admin → POST /api/admin/content
|
||
|
|
→ Guarda en PostgreSQL (status: 'draft')
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Validador Revisa
|
||
|
|
```
|
||
|
|
Validador → Panel Admin → POST /api/admin/content/:id/validate
|
||
|
|
→ Actualiza status: 'approved'
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Admin Publica
|
||
|
|
```
|
||
|
|
Admin → Panel Admin → POST /api/admin/content/:id/publish
|
||
|
|
→ Actualiza status: 'published'
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. Generar Content Pack
|
||
|
|
```
|
||
|
|
Admin → Panel Admin → POST /api/admin/pack/generate
|
||
|
|
→ Genera JSON desde PostgreSQL
|
||
|
|
→ Calcula hash
|
||
|
|
→ Guarda en /storage/packs/
|
||
|
|
→ Crea symlink pack-latest.json
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5. App Consume
|
||
|
|
```
|
||
|
|
App → GET /api/content/pack/latest
|
||
|
|
→ Descarga JSON
|
||
|
|
→ Cache en IndexedDB
|
||
|
|
→ Funciona offline
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📊 MODELO DE DATOS (Resumen)
|
||
|
|
|
||
|
|
Ver `docs/SERVER_DATABASE_SCHEMA.sql` para detalles completos.
|
||
|
|
|
||
|
|
**Tablas:**
|
||
|
|
- `content_items` - Contenido principal
|
||
|
|
- `media_resources` - Recursos multimedia
|
||
|
|
- `content_resource_associations` - Asociaciones
|
||
|
|
- `content_versions` - Historial de versiones
|
||
|
|
- `audit_logs` - Auditoría
|
||
|
|
- `users` - Usuarios del panel admin
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ✅ CHECKLIST DE IMPLEMENTACIÓN
|
||
|
|
|
||
|
|
### Fase 1: Base de Datos
|
||
|
|
- [ ] Crear schema `tes_content`
|
||
|
|
- [ ] Crear tablas (content_items, media_resources, etc.)
|
||
|
|
- [ ] Crear índices
|
||
|
|
- [ ] Crear triggers
|
||
|
|
- [ ] Migrar contenido inicial
|
||
|
|
|
||
|
|
### Fase 2: API Pública
|
||
|
|
- [ ] Endpoint `/api/health`
|
||
|
|
- [ ] Endpoint `/api/content/pack/latest`
|
||
|
|
- [ ] Endpoint `/api/content/pack/:version`
|
||
|
|
- [ ] Endpoint `/api/content/protocol/:slug`
|
||
|
|
- [ ] Endpoint `/api/content/guide/:slug`
|
||
|
|
- [ ] Rate limiting
|
||
|
|
- [ ] CORS configurado
|
||
|
|
|
||
|
|
### Fase 3: Generador de Pack
|
||
|
|
- [ ] Servicio `pack-generator.js`
|
||
|
|
- [ ] Lectura desde PostgreSQL
|
||
|
|
- [ ] Generación de JSON
|
||
|
|
- [ ] Cálculo de hash SHA-256
|
||
|
|
- [ ] Guardado en `/storage/packs/`
|
||
|
|
- [ ] Symlink `pack-latest.json`
|
||
|
|
|
||
|
|
### Fase 4: API Admin
|
||
|
|
- [ ] Autenticación JWT
|
||
|
|
- [ ] RBAC middleware
|
||
|
|
- [ ] Endpoints CRUD contenido
|
||
|
|
- [ ] Endpoints gestión recursos
|
||
|
|
- [ ] Endpoint generación pack
|
||
|
|
- [ ] Audit logging
|
||
|
|
|
||
|
|
### Fase 5: Panel Admin
|
||
|
|
- [ ] Editor de protocolos
|
||
|
|
- [ ] Editor de guías
|
||
|
|
- [ ] Gestor de recursos
|
||
|
|
- [ ] Generador de pack (UI)
|
||
|
|
- [ ] Dashboard de estado
|
||
|
|
|
||
|
|
### Fase 6: Integración App
|
||
|
|
- [ ] ContentAdapter en app
|
||
|
|
- [ ] Descarga de pack al iniciar
|
||
|
|
- [ ] Cache en IndexedDB
|
||
|
|
- [ ] Fallback a procedures.ts
|
||
|
|
- [ ] Testing offline
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Fin del Documento**
|
||
|
|
|