docs(v5): Complete system documentation

Comprehensive documentation for TZZR system v5 including:

- 00_VISION: Glossary and foundational philosophy
- 01_ARQUITECTURA: System overview and server specs
- 02_MODELO_DATOS: Entity definitions and data planes (T0, MST, BCK)
- 03_COMPONENTES: Agent docs (CLARA, MARGARET, FELDMAN, GRACE)
- 04_SEGURIDAD: Threat model and secrets management
- 05_OPERACIONES: Infrastructure and backup/recovery
- 06_INTEGRACIONES: GPU services (RunPod status: blocked)
- 99_ANEXOS: Repository inventory (24 repos)

Key findings documented:
- CRITICAL: UFW inactive on CORP/HST
- CRITICAL: PostgreSQL 5432 exposed
- CRITICAL: .env files with 644 permissions
- RunPod workers not starting (code ready in R2)
- Infisical designated as single source of secrets (D-001)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
ARCHITECT
2025-12-24 17:58:03 +00:00
parent a92d41c846
commit 6d15abcb1a
16 changed files with 4164 additions and 2 deletions

View File

@@ -0,0 +1,311 @@
# CLARA y MARGARET - Agentes de Ingesta
**Versión:** 5.0
**Fecha:** 2024-12-24
---
## Resumen
| Aspecto | CLARA | MARGARET |
|---------|-------|----------|
| Servidor | DECK (72.62.1.113) | CORP (92.112.181.188) |
| Puerto | 5051 | 5051 |
| Dominio | Personal | Empresarial |
| Base de datos | tzzr | corp |
| Tabla log | clara_log | margaret_log |
| Bucket R2 | deck | corp |
| Estado | Operativo | Operativo |
---
## Arquitectura
```
PACKET (App móvil)
│ POST /ingest
│ Content-Type: multipart/form-data
│ X-Auth-Key: {h_instancia}
┌─────────────────────────────────────────┐
│ CLARA (Personal) / MARGARET (Corp) │
│ │
│ 1. Validar h_instancia │
│ 2. Calcular h_entrada (SHA-256) │
│ 3. Subir archivos a R2 │
│ 4. Insertar en log (inmutable) │
│ 5. Estado: 'recibido' │
│ 6. Responder con h_entrada │
└─────────────────────────────────────────┘
ALFRED / JARED (siguiente paso)
```
---
## Endpoint de Ingesta
### Request
```http
POST /ingest HTTP/1.1
Host: deck.example.com:5051
Content-Type: multipart/form-data
X-Auth-Key: {h_instancia}
--boundary
Content-Disposition: form-data; name="tipo"
documento
--boundary
Content-Disposition: form-data; name="archivo"; filename="doc.pdf"
Content-Type: application/pdf
{binary data}
--boundary--
```
### Response
```json
{
"success": true,
"h_entrada": "a1b2c3d4e5f6...",
"estado": "recibido",
"timestamp": "2024-12-24T12:00:00Z"
}
```
---
## Cálculo de h_entrada
```python
import hashlib
import json
def calcular_h_entrada(h_instancia, tipo, contenido_bytes, timestamp):
"""
Calcula el hash único de entrada.
h_entrada = SHA-256(h_instancia:tipo:sha256(contenido):timestamp)
"""
hash_contenido = hashlib.sha256(contenido_bytes).hexdigest()
data = f"{h_instancia}:{tipo}:{hash_contenido}:{timestamp}"
return hashlib.sha256(data.encode()).hexdigest()
```
---
## Schema: clara_log / margaret_log
```sql
CREATE TABLE clara_log (
id BIGSERIAL PRIMARY KEY,
h_entrada VARCHAR(64) UNIQUE NOT NULL,
h_instancia VARCHAR(64) NOT NULL,
tipo VARCHAR(50) NOT NULL,
contenido_url TEXT, -- locker://deck/{h_entrada}/archivo
contenido_hash VARCHAR(64), -- SHA-256 del contenido
metadata JSONB,
estado VARCHAR(20) DEFAULT 'recibido',
created_at TIMESTAMPTZ DEFAULT NOW(),
processed_at TIMESTAMPTZ,
processed_by VARCHAR(50) -- 'alfred' o 'manual'
);
-- margaret_log tiene schema idéntico
CREATE TABLE margaret_log (
id BIGSERIAL PRIMARY KEY,
h_entrada VARCHAR(64) UNIQUE NOT NULL,
h_instancia VARCHAR(64) NOT NULL,
tipo VARCHAR(50) NOT NULL,
contenido_url TEXT,
contenido_hash VARCHAR(64),
metadata JSONB,
estado VARCHAR(20) DEFAULT 'recibido',
created_at TIMESTAMPTZ DEFAULT NOW(),
processed_at TIMESTAMPTZ,
processed_by VARCHAR(50)
);
```
---
## Estados del Log
| Estado | Descripción |
|--------|-------------|
| recibido | Ingesta completada, pendiente procesamiento |
| procesando | ALFRED/JARED está procesando |
| enviado_mason | Enviado a MASON para enriquecimiento |
| consolidado | Procesado por FELDMAN |
| error | Error en procesamiento |
---
## Almacenamiento en R2
### Estructura de URLs
```
locker://deck/{h_entrada}/archivo.ext
locker://corp/{h_entrada}/archivo.ext
```
### Implementación
```python
import boto3
def subir_a_r2(bucket, h_entrada, archivo_bytes, filename):
"""Sube archivo a Cloudflare R2."""
s3 = boto3.client(
's3',
endpoint_url='https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com',
aws_access_key_id=R2_ACCESS_KEY,
aws_secret_access_key=R2_SECRET_KEY
)
key = f"{h_entrada}/{filename}"
s3.put_object(
Bucket=bucket,
Key=key,
Body=archivo_bytes
)
return f"locker://{bucket}/{key}"
```
---
## Validación de h_instancia
```python
def validar_instancia(h_instancia):
"""
Valida que h_instancia exista y esté activa.
TODO: Implementar tabla de instancias activas.
Actualmente: Validación básica de formato.
"""
if not h_instancia:
return False
if len(h_instancia) != 64:
return False
# TODO: Consultar tabla de instancias
return True
```
---
## Tipos de Ingesta Soportados
| Tipo | Descripción | Extensiones |
|------|-------------|-------------|
| documento | Documentos | pdf, doc, docx |
| imagen | Imágenes | jpg, png, gif |
| audio | Audio | mp3, wav, m4a |
| video | Video | mp4, mov |
| texto | Texto plano | txt, md |
| json | Datos estructurados | json |
---
## Configuración
### Variables de Entorno
```bash
# CLARA (.env en /opt/clara/)
DB_HOST=localhost
DB_PORT=5432
DB_NAME=tzzr
DB_USER=clara
DB_PASSWORD=****
R2_ENDPOINT=https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com
R2_ACCESS_KEY=****
R2_SECRET_KEY=****
R2_BUCKET=deck
# MARGARET (.env en /opt/margaret/)
DB_HOST=localhost
DB_PORT=5432
DB_NAME=corp
DB_USER=margaret
DB_PASSWORD=****
R2_BUCKET=corp
```
### Docker Compose
```yaml
# CLARA
version: '3.8'
services:
clara:
container_name: clara-clara
image: tzzr/clara:latest
ports:
- "5051:5051"
env_file:
- .env
restart: unless-stopped
```
---
## Diferencias CLARA vs MARGARET
| Aspecto | CLARA | MARGARET |
|---------|-------|----------|
| Uso | Personal | Empresarial |
| Volumen | Bajo | Alto |
| Privacidad | Máxima | Compartida (empresa) |
| Integración | ALFRED | JARED → MASON → FELDMAN |
| Backup | deck bucket | corp bucket |
---
## Seguridad
### Actual
- Autenticación por h_instancia
- Comunicación HTTP (sin TLS interno)
- .env con permisos 644 (**CRÍTICO: cambiar a 600**)
### Recomendado
- TLS interno con certificados
- Rate limiting
- Validación de tipos MIME
- Escaneo antivirus (ClamAV)
---
## Monitoreo
### Logs
```bash
# CLARA
docker logs clara-clara -f
# MARGARET
docker logs margaret-margaret -f
```
### Métricas Sugeridas
- Ingestas por minuto
- Tamaño promedio de archivos
- Tiempo de procesamiento
- Errores por tipo

View File

@@ -0,0 +1,390 @@
# 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
```
### 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;
```
-- Ú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;
```