Auditoria completa y plan de implementacion TZZR

- ARCHITECTURE.md: Estado real de 23 repos
- IMPLEMENTATION_PLAN.md: 7 fases de implementacion
- PHASES/: Scripts detallados para cada fase

Resultado de auditoria:
- 5 repos implementados
- 4 repos parciales
- 14 repos solo documentacion
This commit is contained in:
ARCHITECT
2025-12-24 08:59:14 +00:00
parent 1638a8cf85
commit 73ae91d337
7 changed files with 2089 additions and 2 deletions

View File

@@ -0,0 +1,419 @@
# FASE 1: PIPELINE MÍNIMO VIABLE
**Complejidad:** Media
**Duración estimada:** 2-3 días
**Prioridad:** CRÍTICA
---
## OBJETIVO
Establecer el flujo: PACKET → CLARA → PostgreSQL + R2
Esto permite que la app móvil envíe contenido y se almacene correctamente.
---
## PREREQUISITOS
- [x] FASE 0 completada
- [x] SSH acceso a DECK (72.62.1.113)
- [x] R2 bucket 'deck' accesible
- [x] PostgreSQL en DECK funcionando
- [x] HST funcionando (tags)
---
## PASO 1.1: Crear tablas de CLARA en DECK
### Conectar a DECK
```bash
ssh -i /home/orchestrator/.ssh/tzzr root@72.62.1.113
```
### Ejecutar SQL
```bash
sudo -u postgres psql -d tzzr << 'EOF'
-- Tabla principal de log
CREATE TABLE IF NOT EXISTS clara_log (
id BIGSERIAL PRIMARY KEY,
h_instancia VARCHAR(64) NOT NULL,
h_entrada VARCHAR(64) NOT NULL,
contenedor JSONB NOT NULL,
r2_paths JSONB DEFAULT '{}',
estado VARCHAR(20) DEFAULT 'recibido',
procesado_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
CONSTRAINT clara_log_h_entrada_unique UNIQUE (h_entrada)
);
-- Índices para búsqueda eficiente
CREATE INDEX IF NOT EXISTS idx_clara_h_instancia ON clara_log(h_instancia);
CREATE INDEX IF NOT EXISTS idx_clara_estado ON clara_log(estado);
CREATE INDEX IF NOT EXISTS idx_clara_created ON clara_log(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_clara_contenedor ON clara_log USING gin(contenedor);
-- Comentarios
COMMENT ON TABLE clara_log IS 'Log inmutable de entrada - recibe contenedores de PACKET';
COMMENT ON COLUMN clara_log.h_instancia IS 'Hash SHA-256 que identifica la instancia DECK';
COMMENT ON COLUMN clara_log.h_entrada IS 'Hash SHA-256 único del contenedor';
COMMENT ON COLUMN clara_log.contenedor IS 'Contenedor completo en formato JSON (S-CONTRACT)';
COMMENT ON COLUMN clara_log.r2_paths IS 'Rutas de archivos subidos a R2';
COMMENT ON COLUMN clara_log.estado IS 'Estado: recibido, en_mason, en_feldman, consolidado';
-- Verificar
SELECT 'Tabla clara_log creada correctamente' AS resultado;
\dt clara_log
\d clara_log
EOF
```
### Verificación
```bash
sudo -u postgres psql -d tzzr -c "SELECT COUNT(*) FROM clara_log;"
# Debe retornar 0 (tabla vacía)
```
### Rollback
```sql
DROP TABLE IF EXISTS clara_log CASCADE;
```
---
## PASO 1.2: Generar h_instancia para DECK
### Concepto
h_instancia es un hash SHA-256 único que identifica esta instancia de DECK.
### Generar
```bash
# En DECK
SEED="deck-personal-$(hostname)-$(date +%s)"
H_INSTANCIA=$(echo -n "$SEED" | sha256sum | cut -d' ' -f1)
echo "H_INSTANCIA=$H_INSTANCIA"
# Guardar en archivo de configuración
echo "H_INSTANCIA=$H_INSTANCIA" >> /opt/clara/.env
```
### Verificación
El hash debe tener 64 caracteres hexadecimales.
---
## PASO 1.3: Desplegar CLARA como Docker
### Crear estructura en DECK
```bash
ssh -i /home/orchestrator/.ssh/tzzr root@72.62.1.113 << 'REMOTE'
mkdir -p /opt/clara
cd /opt/clara
# Clonar repo
git clone http://localhost:3000/tzzr/clara.git .
# Crear .env
cat > .env << 'EOF'
# Generado automáticamente
H_INSTANCIA=<PEGAR_HASH_GENERADO>
# PostgreSQL
DB_HOST=172.17.0.1
DB_PORT=5432
DB_NAME=tzzr
DB_USER=deck
DB_PASSWORD=<PASSWORD_DECK>
# Cloudflare R2
R2_ENDPOINT=https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com
R2_ACCESS_KEY=ecddc771824c3cb3417d9451780db3d2
R2_SECRET_KEY=c8138e2597100ffb7dd1477ad722c0214f86097cd968752aea3cfcea5d54dbac
R2_BUCKET=deck
# Puerto
PORT=5051
EOF
# Construir y levantar
docker-compose up -d --build
# Verificar
docker-compose logs --tail=20
REMOTE
```
### docker-compose.yml actualizado
```yaml
version: '3.8'
services:
clara:
build: .
container_name: clara
ports:
- "5051:5051"
env_file:
- .env
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5051/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
default:
external:
name: deck_network
```
### Dockerfile
```dockerfile
FROM python:3.11-slim
WORKDIR /app
# Dependencias del sistema
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*
# Dependencias Python
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Código
COPY app.py .
# Puerto
EXPOSE 5051
# Ejecutar
CMD ["python", "app.py"]
```
### Verificación
```bash
# Desde DECK
curl http://localhost:5051/health
# Debe retornar: {"service": "clara", "status": "ok", ...}
# Desde ARCHITECT
curl http://72.62.1.113:5051/health
```
---
## PASO 1.4: Configurar Caddy para /ingest
### Editar Caddyfile en DECK
```bash
ssh -i /home/orchestrator/.ssh/tzzr root@72.62.1.113 << 'REMOTE'
# Añadir a Caddyfile existente
cat >> /etc/caddy/Caddyfile << 'EOF'
# CLARA - API de ingesta
clara.tzzrdeck.me {
reverse_proxy localhost:5051
}
# También en el dominio principal
tzzrdeck.me {
handle /ingest* {
reverse_proxy localhost:5051
}
# ... resto de configuración
}
EOF
# Recargar Caddy
systemctl reload caddy
REMOTE
```
### Verificación
```bash
# HTTPS (si DNS configurado)
curl https://clara.tzzrdeck.me/health
# O directamente
curl http://72.62.1.113:5051/health
```
---
## PASO 1.5: Probar ingesta completa
### Test desde curl
```bash
# Definir variables
H_INSTANCIA="<hash_de_paso_1.2>"
TEST_HASH=$(echo -n "test-$(date +%s)" | sha256sum | cut -d' ' -f1)
# Enviar contenedor de prueba
curl -X POST http://72.62.1.113:5051/ingest \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $H_INSTANCIA" \
-d '{
"id": "'$TEST_HASH'",
"archivo_hash": "'$TEST_HASH'",
"origen": {
"app": "curl-test",
"version": "1.0",
"timestamp_captura": "'$(date -Iseconds)'"
},
"contenido": {
"titulo": "Test de ingesta",
"descripcion": "Contenedor de prueba desde curl"
},
"etiquetas": []
}'
```
### Respuestas esperadas
```json
// Éxito
{"ok": true, "id": 1, "h_entrada": "abc123..."}
// Duplicado
{"error": "hash_exists"}
// Sin auth
{"error": "unauthorized"}
```
### Verificar en PostgreSQL
```bash
ssh -i /home/orchestrator/.ssh/tzzr root@72.62.1.113 \
"sudo -u postgres psql -d tzzr -c 'SELECT id, h_entrada, estado, created_at FROM clara_log ORDER BY id DESC LIMIT 5;'"
```
---
## PASO 1.6: Probar subida a R2
### Test con archivo
```bash
# Crear archivo de prueba
echo "Contenido de prueba" > /tmp/test.txt
TEST_DATA=$(base64 /tmp/test.txt)
TEST_HASH=$(echo -n "test-file-$(date +%s)" | sha256sum | cut -d' ' -f1)
curl -X POST http://72.62.1.113:5051/ingest \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $H_INSTANCIA" \
-d '{
"id": "'$TEST_HASH'",
"archivo_hash": "'$TEST_HASH'",
"origen": {
"app": "curl-test",
"version": "1.0"
},
"archivos": [{
"nombre": "test.txt",
"tipo": "text/plain",
"data": "'$TEST_DATA'"
}]
}'
```
### Verificar en R2
```bash
# Usando AWS CLI configurado para R2
aws s3 ls s3://deck/ --endpoint-url https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com
```
---
## CHECKLIST FINAL FASE 1
- [ ] 1.1 - Tabla clara_log creada en DECK PostgreSQL
- [ ] 1.2 - h_instancia generado y guardado
- [ ] 1.3 - CLARA corriendo en Docker
- [ ] 1.4 - Caddy configurado (opcional)
- [ ] 1.5 - Test de ingesta exitoso
- [ ] 1.6 - Archivo subido a R2
- [ ] Health check responde correctamente
- [ ] Logs sin errores
---
## MÉTRICAS DE ÉXITO
| Métrica | Valor Esperado |
|---------|----------------|
| /health responde | < 100ms |
| /ingest (sin archivo) | < 500ms |
| /ingest (con archivo) | < 2s |
| Registros en clara_log | > 0 |
| Archivos en R2/deck | > 0 |
---
## TROUBLESHOOTING
### CLARA no arranca
```bash
docker logs clara
# Verificar variables de entorno
docker exec clara env | grep -E "DB_|R2_"
```
### No conecta a PostgreSQL
```bash
# Verificar red
docker exec clara ping -c1 172.17.0.1
# Verificar puerto
docker exec clara nc -zv 172.17.0.1 5432
```
### Error R2
```bash
# Verificar credenciales
docker exec clara python -c "
import boto3
s3 = boto3.client('s3',
endpoint_url='https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com',
aws_access_key_id='ecddc771824c3cb3417d9451780db3d2',
aws_secret_access_key='c8138e2597100ffb7dd1477ad722c0214f86097cd968752aea3cfcea5d54dbac'
)
print(s3.list_buckets())
"
```
---
## SIGUIENTE FASE
Continuar con [FASE_2_PROCESAMIENTO_IA.md](FASE_2_PROCESAMIENTO_IA.md)