Files

391 lines
9.1 KiB
Markdown
Raw Permalink Normal View History

# FELDMAN - Agente de Consolidación
**Versión:** 5.0
**Fecha:** 2024-12-24
---
## Resumen
| Aspecto | Valor |
|---------|-------|
| Servidor | CORP (92.112.181.188) |
| Puerto | 5054 |
| Base de datos | corp |
| Tablas | feldman_cola, feldman_bloques, feldman_validaciones |
| Estado | Operativo |
---
## Rol en el Sistema
FELDMAN es el "notario" del sistema: valida y consolida datos en bloques inmutables.
```
MASON (enriquecido)
┌─────────────────────────────────────────┐
│ FELDMAN │
│ │
│ 1. Recibir en feldman_cola │
│ 2. Validar reglas (M-001, M-002, M-003)│
│ 3. Calcular hash_contenido │
│ 4. Encadenar (hash_previo) │
│ 5. Crear milestone o bloque │
│ 6. Marcar como consolidado │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ milestones / bloques (inmutables) │
└─────────────────────────────────────────┘
SENTINEL (auditoría futura)
```
---
## Reglas de Validación
| Regla | Nombre | Descripción | Acción si falla |
|-------|--------|-------------|-----------------|
| M-001 | Hash único | h_bloque/h_milestone no existe previamente | Rechazar |
| M-002 | Encadenamiento | hash_previo apunta a bloque existente | Rechazar |
| M-003 | Integridad | hash_contenido = SHA-256(contenido) | Rechazar |
### Implementación
```python
def validar_m001(h_bloque):
"""M-001: Hash debe ser único."""
existe = db.execute(
"SELECT 1 FROM bloques WHERE h_bloque = %s",
[h_bloque]
).fetchone()
return existe is None
def validar_m002(hash_previo, h_instancia):
"""M-002: hash_previo debe existir (excepto génesis)."""
if hash_previo is None:
# Primer bloque de la instancia (génesis)
existe = db.execute(
"SELECT 1 FROM bloques WHERE h_instancia = %s",
[h_instancia]
).fetchone()
return existe is None # OK si no hay bloques previos
existe = db.execute(
"SELECT 1 FROM bloques WHERE h_bloque = %s",
[hash_previo]
).fetchone()
return existe is not None
def validar_m003(hash_contenido, contenido):
"""M-003: Hash debe coincidir con contenido."""
import hashlib
import json
contenido_serializado = json.dumps(contenido, sort_keys=True)
hash_calculado = hashlib.sha256(contenido_serializado.encode()).hexdigest()
return hash_contenido == hash_calculado
```
---
## Schema de Tablas
### feldman_cola
```sql
CREATE TABLE feldman_cola (
id BIGSERIAL PRIMARY KEY,
tipo VARCHAR(50) NOT NULL, -- 'milestone' o 'bloque'
h_entrada VARCHAR(64) NOT NULL, -- Referencia a origen
h_instancia VARCHAR(64) NOT NULL,
contenido JSONB NOT NULL,
prioridad INTEGER DEFAULT 0,
estado VARCHAR(20) DEFAULT 'pendiente',
intentos INTEGER DEFAULT 0,
ultimo_error TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
processed_at TIMESTAMPTZ
);
CREATE INDEX idx_feldman_cola_estado ON feldman_cola(estado);
CREATE INDEX idx_feldman_cola_prioridad ON feldman_cola(prioridad DESC);
```
### feldman_bloques (alias de bloques)
```sql
-- Ver 02_MODELO_DATOS/planos.md para schema completo
CREATE TABLE bloques (
id BIGSERIAL PRIMARY KEY,
h_bloque VARCHAR(64) UNIQUE NOT NULL,
h_instancia VARCHAR(64) NOT NULL,
secuencia BIGINT NOT NULL,
hash_previo VARCHAR(64),
hash_contenido VARCHAR(64) NOT NULL,
tipo_bloque VARCHAR(50) NOT NULL,
contenido JSONB NOT NULL,
-- ... campos adicionales
UNIQUE (h_instancia, secuencia)
);
```
### feldman_validaciones
```sql
CREATE TABLE feldman_validaciones (
id BIGSERIAL PRIMARY KEY,
h_entrada VARCHAR(64) NOT NULL,
tipo_destino VARCHAR(50) NOT NULL, -- 'milestone' o 'bloque'
h_destino VARCHAR(64), -- h_milestone o h_bloque
regla VARCHAR(50) NOT NULL, -- M-001, M-002, M-003
resultado BOOLEAN NOT NULL,
mensaje TEXT,
validated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_feldman_val_entrada ON feldman_validaciones(h_entrada);
```
---
## Flujo de Consolidación
```
1. Entrada en feldman_cola
2. FELDMAN procesa (poll cada N segundos)
├─► Validar M-001 (hash único)
│ ├─ PASS → continuar
│ └─ FAIL → registrar error, marcar 'rechazado'
├─► Validar M-002 (encadenamiento)
│ ├─ PASS → continuar
│ └─ FAIL → registrar error, marcar 'rechazado'
├─► Validar M-003 (integridad)
│ ├─ PASS → continuar
│ └─ FAIL → registrar error, marcar 'rechazado'
3. Todas las validaciones PASS
4. Obtener última secuencia de h_instancia
5. Calcular h_bloque/h_milestone
6. INSERT en bloques/milestones
7. Actualizar feldman_cola → 'consolidado'
8. Registrar en feldman_validaciones
```
---
## Cálculo de Hashes
### h_bloque
```python
def calcular_h_bloque(h_instancia, secuencia, hash_previo, hash_contenido):
"""
Calcula el hash del bloque.
h_bloque = SHA-256(h_instancia:secuencia:hash_previo:hash_contenido)
"""
import hashlib
# hash_previo puede ser None para bloque génesis
previo = hash_previo or "genesis"
data = f"{h_instancia}:{secuencia}:{previo}:{hash_contenido}"
return hashlib.sha256(data.encode()).hexdigest()
```
### hash_contenido
```python
def calcular_hash_contenido(contenido):
"""
Calcula el hash del contenido.
hash_contenido = SHA-256(contenido_serializado)
"""
import hashlib
import json
# Serialización determinista
contenido_str = json.dumps(contenido, sort_keys=True, ensure_ascii=False)
return hashlib.sha256(contenido_str.encode()).hexdigest()
```
---
## API Endpoints
### POST /consolidar
```http
POST /consolidar HTTP/1.1
Host: corp.example.com:5054
Content-Type: application/json
{
"tipo": "bloque",
"h_entrada": "abc123...",
"h_instancia": "def456...",
"contenido": {
"tipo_bloque": "transaccion",
"monto": 1000,
"descripcion": "Pago factura #123"
}
}
```
### Response (éxito)
```json
{
"success": true,
"h_bloque": "ghi789...",
"secuencia": 42,
"hash_contenido": "jkl012...",
"validaciones": {
"M-001": true,
"M-002": true,
"M-003": true
}
}
```
### Response (error)
```json
{
"success": false,
"error": "Validación fallida",
"validaciones": {
"M-001": true,
"M-002": false,
"M-003": true
},
"mensaje": "M-002: hash_previo no existe en cadena"
}
```
---
## Configuración
### Variables de Entorno
```bash
# /opt/feldman/.env
DB_HOST=localhost
DB_PORT=5432
DB_NAME=corp
DB_USER=feldman
DB_PASSWORD=****
POLL_INTERVAL=5 # Segundos entre polls
MAX_BATCH=10 # Elementos por lote
MAX_RETRIES=3 # Reintentos antes de rechazar
```
---
## Estados de la Cola
| Estado | Descripción |
|--------|-------------|
| pendiente | En espera de procesamiento |
| procesando | FELDMAN está validando |
| consolidado | Validado y creado bloque/milestone |
| rechazado | Falló validación, no se reintentará |
| error | Error técnico, puede reintentarse |
---
## Auditoría
Cada validación se registra en `feldman_validaciones`:
```sql
-- Consultar historial de validaciones
SELECT
h_entrada,
regla,
resultado,
mensaje,
validated_at
FROM feldman_validaciones
WHERE h_entrada = 'abc123...'
ORDER BY validated_at;
```
---
## Futuro: Blockchain
FELDMAN está diseñado para evolucionar hacia blockchain:
1. **Actual:** Encadenamiento por hash_previo en PostgreSQL
2. **Fase 2:** Merkle tree para verificación eficiente
3. **Fase 3:** Smart contract en blockchain (Ethereum/Polygon)
```
Merkle Root
┌───────────┴───────────┐
│ │
Hash(AB) Hash(CD)
│ │
┌─────┴─────┐ ┌─────┴─────┐
│ │ │ │
Hash(A) Hash(B) Hash(C) Hash(D)
│ │ │ │
Bloque A Bloque B Bloque C Bloque D
```
---
## Monitoreo
### Logs
```bash
docker logs feldman-feldman -f
```
### Consultas de Estado
```sql
-- Elementos pendientes
SELECT COUNT(*) FROM feldman_cola WHERE estado = 'pendiente';
-- Últimas validaciones fallidas
SELECT * FROM feldman_validaciones
WHERE resultado = false
ORDER BY validated_at DESC
LIMIT 10;
-- Bloques creados hoy
SELECT COUNT(*) FROM bloques
WHERE created_at >= CURRENT_DATE;
```