Archive: System v4 - Estado al 2024-12-24
This commit is contained in:
205
v4-archive/contratos-comunes/README.md
Normal file
205
v4-archive/contratos-comunes/README.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# Contratos Comunes - Sistema GRACE
|
||||
|
||||
**Version:** 2.1
|
||||
**Estado:** Enterprise Standard
|
||||
|
||||
Especificacion del contrato comun (S-CONTRACT) y contratos de modulo (M-CONTRACT) para el ecosistema de microservicios cognitivos GRACE.
|
||||
|
||||
---
|
||||
|
||||
## Arquitectura
|
||||
|
||||
```
|
||||
Alfred (Orquestador n8n)
|
||||
|
|
||||
| S-CONTRACT v2.0
|
||||
v
|
||||
+-------------------+
|
||||
| GRACE |
|
||||
| 18 Microservicios|
|
||||
| Cognitivos |
|
||||
+-------------------+
|
||||
|
|
||||
v
|
||||
SYS_LOG + SFE
|
||||
```
|
||||
|
||||
**Filosofia:** "Alfred Decide, GRACE Transforma"
|
||||
|
||||
---
|
||||
|
||||
## Estructura del Repositorio
|
||||
|
||||
```
|
||||
contratos-comunes/
|
||||
+-- README.md # Este archivo
|
||||
+-- docs/
|
||||
| +-- S-CONTRACT.md # Contrato comun del sistema (v2.1)
|
||||
| +-- MODULOS_IA.md # Catalogo de 18 modulos
|
||||
| +-- ARQUITECTURA.md # Vision arquitectonica
|
||||
| +-- SENTINEL.md # Sistema de auditoria
|
||||
| +-- KEY_VAULT.md # Gestion de llaves y cifrado
|
||||
| +-- NOTARIO.md # Sellado blockchain
|
||||
| +-- IMPLEMENTACION.md # Wrappers y ejemplos
|
||||
+-- schemas/
|
||||
| +-- s-contract-request.json # JSON Schema para requests (v2.1)
|
||||
| +-- s-contract-response.json # JSON Schema para responses (v2.1)
|
||||
+-- m-contracts/
|
||||
| +-- CLASSIFIER.json # M-CONTRACT clasificador
|
||||
| +-- OCR_CORE.json # M-CONTRACT OCR
|
||||
| +-- ASR_ENGINE.json # M-CONTRACT ASR
|
||||
| +-- ... # (18 modulos total)
|
||||
+-- db-schemas/ # NUEVO: Schemas PostgreSQL
|
||||
| +-- 00_types.sql # Tipos enumerados
|
||||
| +-- 01_hst_tags.sql # Sistema de etiquetas HST
|
||||
| +-- 02_task_manager.sql # Gestor de tareas
|
||||
| +-- 03_work_log.sql # Log de trabajo
|
||||
| +-- 04_ai_context.sql # Contexto para IA
|
||||
| +-- 05_ai_requests.sql # Log de requests IA
|
||||
+-- archive/ # Versiones obsoletas
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Documentos Principales
|
||||
|
||||
| Documento | Descripcion | Prioridad |
|
||||
|-----------|-------------|-----------|
|
||||
| [S-CONTRACT.md](docs/S-CONTRACT.md) | Especificacion del contrato comun v2.0 | LEER PRIMERO |
|
||||
| [MODULOS_IA.md](docs/MODULOS_IA.md) | Catalogo de los 18 modulos GRACE | Alta |
|
||||
| [ARQUITECTURA.md](docs/ARQUITECTURA.md) | Vision arquitectonica del sistema | Alta |
|
||||
| [HST_API.md](docs/HST_API.md) | API de etiquetas HST v2.0 (tzrtech.org) | Alta |
|
||||
| [SENTINEL.md](docs/SENTINEL.md) | Sistema de auditoria dual (LIGHT/DEEP) | Media |
|
||||
| [KEY_VAULT.md](docs/KEY_VAULT.md) | Gestion de llaves y cifrado | Media |
|
||||
| [NOTARIO.md](docs/NOTARIO.md) | Sellado blockchain | Media |
|
||||
| [IMPLEMENTACION.md](docs/IMPLEMENTACION.md) | Wrappers Python/JS y ejemplos n8n | Referencia |
|
||||
| [db-schemas/README.md](db-schemas/README.md) | Schemas PostgreSQL compartidos | Alta |
|
||||
|
||||
---
|
||||
|
||||
## Database Schemas (db-schemas/)
|
||||
|
||||
Schemas PostgreSQL compartidos por todos los componentes del ecosistema:
|
||||
|
||||
| Schema | Descripción |
|
||||
|--------|-------------|
|
||||
| `hst_tags` | Sistema de etiquetas unificado (HST/EMP/HSU/PJT) |
|
||||
| `task_manager` | Proyectos, milestones, bloques y tareas |
|
||||
| `task_work_log` | Log de archivos entrantes/salientes |
|
||||
| `task_contexts` | Contexto enviado a servicios IA |
|
||||
| `task_ai_requests` | Log de todas las requests a IA |
|
||||
|
||||
Ver [db-schemas/README.md](db-schemas/README.md) para documentación completa.
|
||||
|
||||
---
|
||||
|
||||
## Conceptos Clave
|
||||
|
||||
### S-CONTRACT (Contrato del Sistema)
|
||||
Marco general que define:
|
||||
- Estructura de requests/responses
|
||||
- Trazabilidad (trace_id, step_id, idempotency_key)
|
||||
- Perfiles FULL/LITE
|
||||
- Logging (SYS_LOG)
|
||||
- Seguridad y cifrado
|
||||
|
||||
### M-CONTRACT (Contrato de Modulo)
|
||||
Cada modulo extiende S-CONTRACT con:
|
||||
- Schemas de input/output especificos
|
||||
- Cadena de fallback
|
||||
- Metricas de calidad baseline
|
||||
- Providers disponibles
|
||||
|
||||
### Perfiles
|
||||
|
||||
| Perfil | Uso | Campos |
|
||||
|--------|-----|--------|
|
||||
| FULL | Flujos criticos, auditoria completa | Todos |
|
||||
| LITE | Operaciones rapidas, alto volumen | Minimos |
|
||||
|
||||
### Status Codes
|
||||
|
||||
- `SUCCESS` - Ejecucion completa
|
||||
- `PARTIAL` - Resultado incompleto pero usable
|
||||
- `ERROR` - Fallo no recuperable
|
||||
- `TIMEOUT` - Excedio TTL
|
||||
- `FALLBACK` - Exito con modulo alternativo
|
||||
|
||||
---
|
||||
|
||||
## Los 18 Modulos GRACE
|
||||
|
||||
| Familia | Modulos |
|
||||
|---------|---------|
|
||||
| VISION | IMG_PREPROCESS, PDF_SCANNER, OCR_CORE |
|
||||
| VOZ | ASR_ENGINE, TTS_ENGINE |
|
||||
| IDENTIDAD | FACE_VECTOR, ID_CONSOLIDATION, AVATAR_GEN |
|
||||
| SEMANTICA | EMBEDDINGS, SUMMARIZER, TASK_EXTRACTOR, CLASSIFIER, SIMILARITY |
|
||||
| UTILIDADES | FIELD_EXTRACTOR, HASHER, INPUT_NORMALIZER, OUTPUT_ADAPTER, LANG_DETECT |
|
||||
|
||||
---
|
||||
|
||||
## Ejemplo Rapido
|
||||
|
||||
### Request LITE
|
||||
```json
|
||||
{
|
||||
"contract_version": "2.0",
|
||||
"profile": "LITE",
|
||||
"envelope": {
|
||||
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"idempotency_key": "a1b2c3d4e5f6..."
|
||||
},
|
||||
"routing": {"module": "CLASSIFIER"},
|
||||
"context": {"lang": "es", "mode": "strict"},
|
||||
"payload": {
|
||||
"type": "text",
|
||||
"encoding": "utf-8",
|
||||
"content": "Factura de Telefonica por 45.99 EUR"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Response
|
||||
```json
|
||||
{
|
||||
"contract_version": "2.0",
|
||||
"profile": "LITE",
|
||||
"envelope": {"trace_id": "550e8400-...", "idempotency_key": "a1b2c3d4..."},
|
||||
"status": {"code": "SUCCESS", "provider_used": "groq"},
|
||||
"result": {
|
||||
"schema": "classifier_output_v1",
|
||||
"data": {"category": "FINANZAS", "confidence": 0.98}
|
||||
},
|
||||
"quality": {"confidence": 0.98, "coverage": 1.0},
|
||||
"errors": []
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Historial de Versiones
|
||||
|
||||
| Version | Fecha | Cambios |
|
||||
|---------|-------|---------|
|
||||
| 1.0 | 2025-12-01 | Version inicial |
|
||||
| 1.1 | 2025-12-01 | Jerarquia S/M-CONTRACT |
|
||||
| 1.2 | 2025-12-01 | Consolidacion, modularizacion |
|
||||
| 2.0 | 2025-12-18 | Nomenclatura GRACE, reorganizacion repo |
|
||||
| 2.1 | 2025-12-18 | Modos de despliegue (EXTERNAL/SELF_HOSTED/SEMI), db-schemas |
|
||||
|
||||
---
|
||||
|
||||
## Repositorios Relacionados
|
||||
|
||||
- `deck` - Servidor central, iniciador de conexiones
|
||||
- `grace` - Capa de procesamiento IA
|
||||
- `penny` - Asistente de voz real-time
|
||||
- `the-factory` - Procesamiento documental
|
||||
- `mason` - Constructor de prompts
|
||||
- `hst` - Sistema de etiquetas HST
|
||||
|
||||
---
|
||||
|
||||
*Sistema GRACE - "Alfred Decide, GRACE Transforma"*
|
||||
# Hook test Wed Dec 24 00:21:51 UTC 2025
|
||||
167
v4-archive/contratos-comunes/docs/ARQUITECTURA.md
Normal file
167
v4-archive/contratos-comunes/docs/ARQUITECTURA.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# ARQUITECTURA COGNITIVA: SISTEMA GRACE (HIBRIDO)
|
||||
**Version:** 2.0
|
||||
**Estado:** Enterprise Standard
|
||||
|
||||
---
|
||||
|
||||
# 1. Filosofia del Sistema: "Alfred Decide, GRACE Transforma"
|
||||
|
||||
Para superar las limitaciones de hardware (VPS sin GPU), se adopta una arquitectura de **Orquestacion Hibrida**.
|
||||
|
||||
* **ALFRED (El Cuerpo - Local):** Reside en Hostinger (n8n). Es logico, determinista, gestiona credenciales, bases de datos y toma decisiones de enrutamiento.
|
||||
|
||||
* **GRACE (El Cerebro - Remoto):** Es efimero y reside en la nube (APIs). Procesa senales complejas (vision, audio, semantica) y devuelve JSON estructurado.
|
||||
|
||||
---
|
||||
|
||||
# 2. Diagrama de Arquitectura
|
||||
|
||||
```
|
||||
+-----------------------------------------------------------------------+
|
||||
| INFRAESTRUCTURA |
|
||||
+-----------------------------------------------------------------------+
|
||||
| |
|
||||
| +------------------+ +------------------+ +------------------+ |
|
||||
| | ALFRED (n8n) | | GRACE (APIs) | | ALMACENAMIENTO | |
|
||||
| | | | | | | |
|
||||
| | - Orquestacion |<--->| - 18 modulos IA | | - Hostinger | |
|
||||
| | - Validacion | | - OpenRouter | | - S3/GCS | |
|
||||
| | - Logging | | - Groq | | - Nextcloud | |
|
||||
| | - Decisiones | | - RunPod | | | |
|
||||
| +------------------+ +------------------+ +------------------+ |
|
||||
| | | | |
|
||||
| +----------------------++-----------------------+ |
|
||||
| | |
|
||||
| +------------------+ +------------------+ +------------------+ |
|
||||
| | NocoDB/PG | | Key Vault | | SENTINEL | |
|
||||
| | | | | | | |
|
||||
| | - SYS_LOG | | - API Keys | | - LIGHT (reglas) | |
|
||||
| | - SFE | | - Encryption | | - DEEP (LLM) | |
|
||||
| | - HST Tags | | - Certificados | | - Patrones | |
|
||||
| +------------------+ +------------------+ +------------------+ |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 3. Mapa de Modulos IA (Implementacion Tecnica)
|
||||
|
||||
Basado en la especificacion de 18 microservicios:
|
||||
|
||||
## Familia A: VISION (Ojos)
|
||||
* **Objetivo:** OCR, Analisis de Documentos, Extraccion de Datos.
|
||||
* **Motor:** GPT-4o (Vision) o Claude 3.5 Sonnet.
|
||||
* **Flujo:** Alfred envia imagen (base64/URL) -> GRACE analiza -> Devuelve JSON.
|
||||
|
||||
## Familia B: VOZ (Oidos)
|
||||
* **Objetivo:** Transcripcion de reuniones y notas de voz (ASR).
|
||||
* **Motor:** Whisper Large v3 (Groq API) o Faster Whisper (RunPod).
|
||||
* **Rendimiento:** Transcripcion a 500x tiempo real.
|
||||
|
||||
## Familia D: SEMANTICA (Cortex)
|
||||
* **Objetivo:** Clasificacion, Resumen, Extraccion de Tareas.
|
||||
* **Motor:** Meta Llama 3 70B (OpenRouter/Groq).
|
||||
* **Rendimiento:** Latencia sub-segundo.
|
||||
|
||||
## Familia C: IDENTIDAD (Biometria)
|
||||
* **Estado:** Roadmap Fase 2.
|
||||
* **Implementacion:** RunPod Serverless para calculo vectorial facial.
|
||||
|
||||
---
|
||||
|
||||
# 4. Protocolo de Datos e Identidad
|
||||
|
||||
Para garantizar la integridad y trazabilidad:
|
||||
|
||||
## A. Matricula Interna (TraceID) -> UUID v4
|
||||
* **Generacion:** Descentralizada (en n8n/Alfred).
|
||||
* **Funcion:** Clave Primaria en SYS_LOG.
|
||||
* **Proposito:** Unicidad matematica garantizada.
|
||||
|
||||
## B. Huella de Integridad (idempotency_key) -> SHA256
|
||||
* **Generacion:** `sha256(input_payload)`.
|
||||
* **Funcion:** Control de Idempotencia.
|
||||
* **Proposito:** Evitar reprocesamiento y verificar integridad.
|
||||
|
||||
---
|
||||
|
||||
# 5. El Contrato Comun (S-CONTRACT)
|
||||
|
||||
Todo intercambio entre Alfred y GRACE sigue el S-CONTRACT v2.0.
|
||||
|
||||
Ver `S-CONTRACT.md` para especificacion completa.
|
||||
|
||||
```
|
||||
+---------------------------------------------------------------------+
|
||||
| PRINCIPIO FUNDAMENTAL |
|
||||
| |
|
||||
| "Un modulo que no cumple el contrato, no existe para Alfred" |
|
||||
+---------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 6. Flujo de Procesamiento
|
||||
|
||||
```
|
||||
1. ENTRADA
|
||||
- Alfred recibe evento (webhook, email, archivo)
|
||||
- Genera trace_id y idempotency_key
|
||||
|
||||
2. VALIDACION
|
||||
- Verifica permisos (player_id + method_hash)
|
||||
- Valida schema de entrada
|
||||
|
||||
3. ROUTING
|
||||
- Carga M-CONTRACT del modulo destino
|
||||
- Evalua provider_preference
|
||||
- Selecciona proveedor disponible
|
||||
|
||||
4. TRANSFORMACION (GRACE)
|
||||
- Envia request S-CONTRACT
|
||||
- Espera response (respetando timeout)
|
||||
- Si falla, activa fallback_chain
|
||||
|
||||
5. PERSISTENCIA
|
||||
- Guarda resultado en almacenamiento
|
||||
- Registra en SYS_LOG
|
||||
|
||||
6. AUDITORIA
|
||||
- SENTINEL-LIGHT valida conformidad
|
||||
- SENTINEL-DEEP analiza errores
|
||||
- NOTARIO sella si aplica
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 7. Infraestructura de Soporte (DECK)
|
||||
|
||||
* **Orquestador:** n8n (Docker)
|
||||
* **Base de Datos:** PostgreSQL 15 + NocoDB
|
||||
* **Almacenamiento:** Nextcloud / FileBrowser
|
||||
* **Cache:** Redis
|
||||
* **Seguridad:** Nginx Proxy Manager + SSL
|
||||
* **Mail:** Mail-in-a-Box
|
||||
* **Servicios:** Shlink, Addy.io, Vaultwarden
|
||||
|
||||
Ver repositorio `deck` para configuracion detallada.
|
||||
|
||||
---
|
||||
|
||||
# 8. Documentos Relacionados
|
||||
|
||||
| Documento | Descripcion |
|
||||
|-----------|-------------|
|
||||
| S-CONTRACT.md | Especificacion del contrato comun |
|
||||
| MODULOS_IA.md | Catalogo de 18 modulos GRACE |
|
||||
| SENTINEL.md | Sistema de auditoria |
|
||||
| KEY_VAULT.md | Gestion de llaves y cifrado |
|
||||
| NOTARIO.md | Sellado blockchain |
|
||||
| IMPLEMENTACION.md | Wrappers y ejemplos |
|
||||
|
||||
---
|
||||
|
||||
**Fin del Documento ARQUITECTURA - Version 2.0**
|
||||
|
||||
*Sistema GRACE - "Alfred Decide, GRACE Transforma"*
|
||||
337
v4-archive/contratos-comunes/docs/FACTORY_PROTOCOL_v1.0.md
Normal file
337
v4-archive/contratos-comunes/docs/FACTORY_PROTOCOL_v1.0.md
Normal file
@@ -0,0 +1,337 @@
|
||||
# THE FACTORY Protocol v1.0
|
||||
|
||||
> Protocolo de Generación Iterativa con Director y Auditores
|
||||
|
||||
## 1. Visión General
|
||||
|
||||
THE FACTORY es el sistema de generación iterativa del ecosistema TZZR. Implementa un ciclo de mejora continua donde un **Director** coordina la generación, un **Executor** produce artefactos, un **Evaluator** evalúa la calidad, y un **Auditor** registra todo para trazabilidad.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ THE FACTORY │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ DIRECTOR │───▶│ EXECUTOR │───▶│ EVALUATOR│ │
|
||||
│ │ (decide) │◀───│(genera) │◀───│ (evalúa) │ │
|
||||
│ └────┬─────┘ └──────────┘ └──────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────┐ │
|
||||
│ │ AUDITOR │ ──▶ SENTINEL │
|
||||
│ │(registra)│ │
|
||||
│ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 2. Componentes
|
||||
|
||||
### 2.1 DIRECTOR
|
||||
|
||||
El Director es el cerebro de THE FACTORY. Sus responsabilidades:
|
||||
|
||||
- **Recibir jobs** de ALFRED (DECK) o CLARA (CORP)
|
||||
- **Seleccionar modelos** apropiados para cada tarea
|
||||
- **Decidir convergencia** basándose en confianza y mejora marginal
|
||||
- **Gestionar presupuesto** y límites de iteraciones
|
||||
- **Coordinar** el flujo entre Executor y Evaluator
|
||||
|
||||
```javascript
|
||||
// Decisión de convergencia
|
||||
const decision = director.decideConvergence(job, evaluation);
|
||||
// Converge si:
|
||||
// - confidence >= 0.85 (umbral configurable)
|
||||
// - mejora < 0.02 con confidence > 0.7 (rendimientos decrecientes)
|
||||
```
|
||||
|
||||
### 2.2 EXECUTOR
|
||||
|
||||
El Executor genera artefactos según el tipo de función:
|
||||
|
||||
| Función | Modelos Disponibles |
|
||||
|---------|---------------------|
|
||||
| TEXT_GENERATION | claude-sonnet, claude-opus, gpt-4, llama-3 |
|
||||
| IMAGE_GENERATION | flux-pro, flux-dev, sdxl, dalle-3 |
|
||||
| CODE_GENERATION | claude-sonnet, claude-opus, gpt-4 |
|
||||
| DOCUMENT_GENERATION | claude-opus, gpt-4 |
|
||||
| AUDIO_GENERATION | elevenlabs, bark, xtts |
|
||||
| VIDEO_GENERATION | runway, pika, stable-video |
|
||||
|
||||
### 2.3 EVALUATOR
|
||||
|
||||
El Evaluator analiza cada artefacto contra el objetivo:
|
||||
|
||||
```json
|
||||
{
|
||||
"confidence": 0.82,
|
||||
"strengths": ["Cumple estructura básica", "Lenguaje apropiado"],
|
||||
"weaknesses": ["Falta detalle en sección X"],
|
||||
"feedback": "Mejorar especificidad y añadir ejemplos concretos."
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 AUDITOR
|
||||
|
||||
El Auditor registra cada evento para trazabilidad completa:
|
||||
|
||||
- `JOB_CREATED` - Inicio del job
|
||||
- `JOB_STARTED` - Ejecución iniciada
|
||||
- `ITERATION_COMPLETED` - Cada iteración
|
||||
- `JOB_COMPLETED` - Finalización
|
||||
|
||||
## 3. Estados de Job
|
||||
|
||||
```
|
||||
PENDING ──▶ QUEUED ──▶ RUNNING ──▶ EVALUATING ──┬──▶ CONVERGED
|
||||
│ │ │
|
||||
│ │ └──▶ EXHAUSTED
|
||||
│ │
|
||||
└────────────┘
|
||||
(iteración)
|
||||
```
|
||||
|
||||
| Estado | Descripción |
|
||||
|--------|-------------|
|
||||
| PENDING | Job creado, esperando recursos |
|
||||
| QUEUED | En cola para ejecución |
|
||||
| RUNNING | Executor generando artefacto |
|
||||
| EVALUATING | Evaluator analizando resultado |
|
||||
| CONVERGED | Objetivo alcanzado (confidence >= threshold) |
|
||||
| EXHAUSTED | Límite de iteraciones o presupuesto alcanzado |
|
||||
| FAILED | Error irrecuperable |
|
||||
| CANCELLED | Cancelado por usuario |
|
||||
|
||||
## 4. Estructura del Job
|
||||
|
||||
### 4.1 Request (S-CONTRACT compatible)
|
||||
|
||||
```json
|
||||
{
|
||||
"seed": "Genera un plan de entrenamiento PPL de 4 semanas...",
|
||||
"objective": "Plan estructurado con progresión semanal y ejercicios específicos",
|
||||
"function": "TEXT_GENERATION",
|
||||
"limits": {
|
||||
"max_cycles": 5,
|
||||
"budget_usd": 1.0,
|
||||
"timeout_ms": 120000
|
||||
},
|
||||
"input_refs": ["locker://deck/fitness/datos.json"],
|
||||
"output_format": "markdown",
|
||||
"tags": ["deck", "fitness", "plan"],
|
||||
"metadata": {
|
||||
"source": "ALFRED",
|
||||
"project_id": 123
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 Response
|
||||
|
||||
```json
|
||||
{
|
||||
"job_id": "fac-abc123-xyz789",
|
||||
"state": "CONVERGED",
|
||||
"total_iterations": 3,
|
||||
"total_cost_usd": 0.47,
|
||||
"final_artifact_ref": "locker://factory/artifacts/abc123.md",
|
||||
"final_confidence": 0.89,
|
||||
"convergence_reason": "confidence_threshold_met",
|
||||
"iterations": [
|
||||
{
|
||||
"number": 1,
|
||||
"confidence": 0.72,
|
||||
"feedback": "Añadir más detalle en ejercicios"
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"confidence": 0.81,
|
||||
"feedback": "Mejorar progresión de pesos"
|
||||
},
|
||||
{
|
||||
"number": 3,
|
||||
"confidence": 0.89,
|
||||
"feedback": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Integración con ALFRED y CLARA
|
||||
|
||||
### 5.1 ALFRED (DECK - Lite)
|
||||
|
||||
ALFRED usa THE FACTORY para generación de contenido personal:
|
||||
|
||||
```javascript
|
||||
// alfred.js
|
||||
const result = await factory.submitJob({
|
||||
seed: "Genera plan de entrenamiento para perder peso",
|
||||
objective: "Plan PPL estructurado con progresión",
|
||||
function: "TEXT_GENERATION",
|
||||
tags: ["deck", "fitness"],
|
||||
limits: { max_cycles: 4, budget_usd: 0.3 }
|
||||
});
|
||||
```
|
||||
|
||||
### 5.2 CLARA (CORP - Full)
|
||||
|
||||
CLARA usa THE FACTORY para documentos certificados:
|
||||
|
||||
```javascript
|
||||
// clara.js
|
||||
const result = await factory.submitJob({
|
||||
seed: "Genera factura profesional para pedido ORD-2025-001",
|
||||
objective: "Factura PDF con todos los datos fiscales",
|
||||
function: "DOCUMENT_GENERATION",
|
||||
tags: ["corp", "factura"],
|
||||
limits: { max_cycles: 3, budget_usd: 0.5 }
|
||||
});
|
||||
|
||||
// CLARA añade certificación con NOTARIO
|
||||
const certified = await notario.certify(result);
|
||||
```
|
||||
|
||||
## 6. Flujo de Iteración
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ ITERACIÓN N │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 1. DIRECTOR prepara seed + feedback de iteración N-1 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 2. EXECUTOR genera artefacto con modelo seleccionado │
|
||||
│ - Calcula hash del artefacto │
|
||||
│ - Guarda en LOCKER │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 3. EVALUATOR evalúa artefacto vs objetivo │
|
||||
│ - confidence: 0.0 - 1.0 │
|
||||
│ - strengths: [] │
|
||||
│ - weaknesses: [] │
|
||||
│ - feedback: "..." │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 4. AUDITOR registra iteración en SENTINEL │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 5. DIRECTOR decide: │
|
||||
│ - confidence >= 0.85 → CONVERGED │
|
||||
│ - cost >= budget → EXHAUSTED │
|
||||
│ - iteration >= max → EXHAUSTED │
|
||||
│ - else → ITERAR (volver a paso 1) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 7. Costes y Límites
|
||||
|
||||
### 7.1 Costes por Modelo (estimados)
|
||||
|
||||
| Modelo | Coste por 1K tokens |
|
||||
|--------|---------------------|
|
||||
| claude-sonnet | $0.003 |
|
||||
| claude-opus | $0.015 |
|
||||
| gpt-4 | $0.01 |
|
||||
| flux-pro | $0.05/imagen |
|
||||
| flux-dev | $0.02/imagen |
|
||||
|
||||
### 7.2 Límites por Defecto
|
||||
|
||||
```javascript
|
||||
const DEFAULT_LIMITS = {
|
||||
max_cycles: 5, // Máximo de iteraciones
|
||||
budget_usd: 1.0, // Presupuesto máximo
|
||||
timeout_ms: 120000, // 2 minutos por iteración
|
||||
convergence_threshold: 0.85 // Umbral de convergencia
|
||||
};
|
||||
```
|
||||
|
||||
## 8. Despliegue en RUNPOD
|
||||
|
||||
THE FACTORY se despliega como un Serverless Endpoint en RUNPOD:
|
||||
|
||||
```yaml
|
||||
# runpod-deployment.yaml
|
||||
endpoint:
|
||||
name: the-factory
|
||||
gpu: RTX-A4000 # Para generación de imágenes
|
||||
workers:
|
||||
min: 0
|
||||
max: 3
|
||||
timeout: 300
|
||||
env:
|
||||
- ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
||||
- LOCKER_API_KEY: ${LOCKER_API_KEY}
|
||||
- SENTINEL_URL: https://sentinel.tzzr.net
|
||||
```
|
||||
|
||||
## 9. API Reference
|
||||
|
||||
### POST /jobs
|
||||
|
||||
Crear nuevo job de generación.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"seed": "string",
|
||||
"objective": "string",
|
||||
"function": "TEXT_GENERATION | IMAGE_GENERATION | ...",
|
||||
"limits": { "max_cycles": 5, "budget_usd": 1.0 },
|
||||
"tags": ["string"]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"job_id": "string",
|
||||
"state": "PENDING"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /jobs/{job_id}
|
||||
|
||||
Obtener estado de job.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"job_id": "string",
|
||||
"state": "RUNNING | CONVERGED | ...",
|
||||
"current_iteration": 2,
|
||||
"total_cost_usd": 0.15
|
||||
}
|
||||
```
|
||||
|
||||
### GET /jobs/{job_id}/result
|
||||
|
||||
Obtener resultado completo.
|
||||
|
||||
**Response:** Job completo con todas las iteraciones.
|
||||
|
||||
### DELETE /jobs/{job_id}
|
||||
|
||||
Cancelar job en ejecución.
|
||||
|
||||
## 10. Changelog
|
||||
|
||||
### v1.0 (2025-01-10)
|
||||
- Versión inicial del protocolo
|
||||
- Componentes: Director, Executor, Evaluator, Auditor
|
||||
- Integración con ALFRED y CLARA
|
||||
- Soporte para TEXT, IMAGE, CODE, DOCUMENT generation
|
||||
|
||||
---
|
||||
|
||||
*Este documento es parte del sistema S-CONTRACT v2.1*
|
||||
156
v4-archive/contratos-comunes/docs/HST_API.md
Normal file
156
v4-archive/contratos-comunes/docs/HST_API.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# HST API v2.0
|
||||
|
||||
**Servidor:** https://tzrtech.org
|
||||
**Estado:** Producción
|
||||
**Última actualización:** 2025-12-18
|
||||
|
||||
---
|
||||
|
||||
## Estadísticas
|
||||
|
||||
| Tabla | Registros | Descripción |
|
||||
|-------|-----------|-------------|
|
||||
| hst | 658 | Etiquetas del sistema |
|
||||
| spe | 145 | Especialidades |
|
||||
| flg | 65 | Flags |
|
||||
| vsn | 84 | Versiones |
|
||||
| vue | 21 | Vistas |
|
||||
| **Total** | **973** | Todas con h_maestro |
|
||||
|
||||
---
|
||||
|
||||
## Sistema Dual de Hashes
|
||||
|
||||
```
|
||||
h_maestro = SHA256(grupo || ':' || ref)
|
||||
→ Identidad SEMÁNTICA (determinista)
|
||||
→ Ejemplo: SHA256("hst:abk") = "335350bb41a329c..."
|
||||
|
||||
mrf = SHA256(bytes_imagen)
|
||||
→ Identidad de ARCHIVO
|
||||
→ URL: https://tzrtech.org/{mrf}.png
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Dump completo
|
||||
```
|
||||
GET https://tzrtech.org/api/index.json
|
||||
```
|
||||
|
||||
Retorna array con todos los tags.
|
||||
|
||||
### Tag por h_maestro
|
||||
```
|
||||
GET https://tzrtech.org/api/tags/{h_maestro}
|
||||
```
|
||||
|
||||
Ejemplo:
|
||||
```bash
|
||||
curl https://tzrtech.org/api/tags/335350bb41a329c31acac43197232850bc6828ec76650291ce230446e520774f
|
||||
```
|
||||
|
||||
### Búsqueda y filtro
|
||||
```
|
||||
GET https://tzrtech.org/api/tags?grupo={grupo}
|
||||
GET https://tzrtech.org/api/tags?q={query}
|
||||
GET https://tzrtech.org/api/tags?grupo={grupo}&q={query}
|
||||
```
|
||||
|
||||
Ejemplos:
|
||||
```bash
|
||||
# Todas las etiquetas hst
|
||||
curl "https://tzrtech.org/api/tags?grupo=hst"
|
||||
|
||||
# Buscar "finanzas"
|
||||
curl "https://tzrtech.org/api/tags?q=finanzas"
|
||||
|
||||
# Buscar "yoga" en vsn
|
||||
curl "https://tzrtech.org/api/tags?grupo=vsn&q=yoga"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Formato de Respuesta
|
||||
|
||||
```json
|
||||
{
|
||||
"ref": "abk",
|
||||
"h_maestro": "335350bb41a329c31acac43197232850bc6828ec76650291ce230446e520774f",
|
||||
"mrf": "ed456cb46151edb46106863d16b4e4cade7af8e33d8c7cae8489125aee76ffa7",
|
||||
"nombre_es": "audiolibro",
|
||||
"nombre_en": "audiobook",
|
||||
"grupo": "hst",
|
||||
"imagen_url": "https://tzrtech.org/ed456cb46151edb46106863d16b4e4cade7af8e33d8c7cae8489125aee76ffa7.png"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Uso desde DECK
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
# Obtener tag por h_maestro
|
||||
def get_tag(h_maestro: str) -> dict:
|
||||
response = requests.get(f"https://tzrtech.org/api/tags/{h_maestro}")
|
||||
return response.json()
|
||||
|
||||
# Buscar tags por grupo
|
||||
def search_tags(grupo: str = None, query: str = None) -> list:
|
||||
params = {}
|
||||
if grupo:
|
||||
params["grupo"] = grupo
|
||||
if query:
|
||||
params["q"] = query
|
||||
response = requests.get("https://tzrtech.org/api/tags", params=params)
|
||||
return response.json()
|
||||
|
||||
# Calcular h_maestro localmente (para verificación)
|
||||
import hashlib
|
||||
|
||||
def calculate_h_maestro(grupo: str, ref: str) -> str:
|
||||
return hashlib.sha256(f"{grupo}:{ref}".encode()).hexdigest()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Uso en S-CONTRACT
|
||||
|
||||
```json
|
||||
{
|
||||
"context": {
|
||||
"tags": {
|
||||
"hst": ["335350bb41a329c...", "a7b3c9d4e5f6..."],
|
||||
"hsu": [],
|
||||
"emp": ["empresa_h_maestro..."],
|
||||
"pjt": ["proyecto_h_maestro..."]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Subdominios Semánticos
|
||||
|
||||
Las imágenes también son accesibles via subdominio:
|
||||
|
||||
```
|
||||
https://hst_finanzas.tzrtech.org → redirect → /{mrf}.png
|
||||
https://spe_aluminio.tzrtech.org → redirect → /{mrf}.png
|
||||
```
|
||||
|
||||
Formato: `{grupo}_{ref_normalizado}.tzrtech.org`
|
||||
|
||||
---
|
||||
|
||||
## Historial
|
||||
|
||||
| Versión | Fecha | Cambios |
|
||||
|---------|-------|---------|
|
||||
| 1.0 | 2025-12 | MVP imágenes con mrf |
|
||||
| 2.0 | 2025-12-18 | Añadido h_maestro, API endpoints, limpieza duplicados |
|
||||
538
v4-archive/contratos-comunes/docs/IMPLEMENTACION.md
Normal file
538
v4-archive/contratos-comunes/docs/IMPLEMENTACION.md
Normal file
@@ -0,0 +1,538 @@
|
||||
# IMPLEMENTACION - Wrappers y Ejemplos
|
||||
**Version:** 2.0
|
||||
**Dependencia:** `S-CONTRACT.md`
|
||||
**Estado:** Referencia
|
||||
|
||||
---
|
||||
|
||||
# 1. Introduccion
|
||||
|
||||
Este documento proporciona implementaciones de referencia para:
|
||||
- Construccion de requests S-CONTRACT
|
||||
- Validacion de responses
|
||||
- Integracion con Alfred (n8n)
|
||||
|
||||
---
|
||||
|
||||
# 2. ContractBuilder (Python)
|
||||
|
||||
## 2.1 Clase Principal
|
||||
|
||||
```python
|
||||
import uuid
|
||||
import hashlib
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional, Dict, Any, List
|
||||
from dataclasses import dataclass, asdict
|
||||
|
||||
@dataclass
|
||||
class ContractBuilder:
|
||||
"""
|
||||
Constructor de requests S-CONTRACT v2.0.
|
||||
"""
|
||||
contract_version: str = "2.0"
|
||||
profile: str = "FULL"
|
||||
|
||||
# Envelope
|
||||
trace_id: Optional[str] = None
|
||||
parent_trace_id: Optional[str] = None
|
||||
step_id: Optional[str] = None
|
||||
step_index: int = 1
|
||||
total_steps: Optional[int] = None
|
||||
idempotency_key: Optional[str] = None
|
||||
ttl_ms: int = 30000
|
||||
provider_timeout_ms: int = 15000
|
||||
|
||||
# Routing
|
||||
module: Optional[str] = None
|
||||
module_version: Optional[str] = None
|
||||
provider_preference: Optional[List[str]] = None
|
||||
fallback_chain: Optional[List[str]] = None
|
||||
max_fallback_level: int = 2
|
||||
|
||||
# Context
|
||||
lang: str = "es"
|
||||
mode: str = "strict"
|
||||
pii_filter: bool = False
|
||||
bandera_id: Optional[str] = None
|
||||
player_id: Optional[str] = None
|
||||
method_hash: Optional[str] = None
|
||||
human_readable: Optional[str] = None
|
||||
|
||||
# Payload
|
||||
payload_type: str = "text"
|
||||
encoding: str = "utf-8"
|
||||
content: Optional[str] = None
|
||||
content_hash: Optional[str] = None
|
||||
schema_expected: Optional[str] = None
|
||||
|
||||
# Batch
|
||||
is_batch: bool = False
|
||||
batch_id: Optional[str] = None
|
||||
item_index: Optional[int] = None
|
||||
items_total: int = 1
|
||||
batch_mode: str = "SEQUENTIAL"
|
||||
|
||||
# Storage
|
||||
input_location: str = "internal"
|
||||
input_ref: Optional[str] = None
|
||||
output_location: str = "internal"
|
||||
output_ref: Optional[str] = None
|
||||
persist_intermediate: bool = True
|
||||
retention_days: int = 30
|
||||
|
||||
# Security
|
||||
encryption_profile: str = "NONE"
|
||||
data_sensitivity: str = "LOW"
|
||||
key_vault_ref: Optional[str] = None
|
||||
pii_detected: bool = False
|
||||
gdpr_relevant: bool = False
|
||||
|
||||
def __post_init__(self):
|
||||
# Auto-generate IDs if not provided
|
||||
if not self.trace_id:
|
||||
self.trace_id = str(uuid.uuid4())
|
||||
if not self.step_id:
|
||||
self.step_id = str(uuid.uuid4())
|
||||
|
||||
def set_content(self, content: str) -> 'ContractBuilder':
|
||||
"""Sets content and auto-calculates hash."""
|
||||
self.content = content
|
||||
self.content_hash = hashlib.sha256(content.encode('utf-8')).hexdigest()
|
||||
if not self.idempotency_key:
|
||||
self.idempotency_key = self.content_hash
|
||||
return self
|
||||
|
||||
def for_module(self, module: str, version: str = "1.0") -> 'ContractBuilder':
|
||||
"""Sets target module."""
|
||||
self.module = module
|
||||
self.module_version = version
|
||||
return self
|
||||
|
||||
def with_fallback(self, chain: List[str]) -> 'ContractBuilder':
|
||||
"""Sets fallback chain."""
|
||||
self.fallback_chain = chain
|
||||
return self
|
||||
|
||||
def lite(self) -> 'ContractBuilder':
|
||||
"""Switches to LITE profile."""
|
||||
self.profile = "LITE"
|
||||
return self
|
||||
|
||||
def build(self) -> Dict[str, Any]:
|
||||
"""Builds the final request dictionary."""
|
||||
timestamp = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
if self.profile == "LITE":
|
||||
return self._build_lite(timestamp)
|
||||
return self._build_full(timestamp)
|
||||
|
||||
def _build_lite(self, timestamp: str) -> Dict[str, Any]:
|
||||
return {
|
||||
"contract_version": self.contract_version,
|
||||
"profile": "LITE",
|
||||
"envelope": {
|
||||
"trace_id": self.trace_id,
|
||||
"idempotency_key": self.idempotency_key
|
||||
},
|
||||
"routing": {
|
||||
"module": self.module
|
||||
},
|
||||
"context": {
|
||||
"lang": self.lang,
|
||||
"mode": self.mode
|
||||
},
|
||||
"payload": {
|
||||
"type": self.payload_type,
|
||||
"encoding": self.encoding,
|
||||
"content": self.content
|
||||
}
|
||||
}
|
||||
|
||||
def _build_full(self, timestamp: str) -> Dict[str, Any]:
|
||||
return {
|
||||
"contract_version": self.contract_version,
|
||||
"profile": "FULL",
|
||||
"envelope": {
|
||||
"trace_id": self.trace_id,
|
||||
"parent_trace_id": self.parent_trace_id,
|
||||
"step_id": self.step_id,
|
||||
"step_index": self.step_index,
|
||||
"total_steps": self.total_steps,
|
||||
"idempotency_key": self.idempotency_key,
|
||||
"timestamp_init": timestamp,
|
||||
"ttl_ms": self.ttl_ms,
|
||||
"provider_timeout_ms": self.provider_timeout_ms
|
||||
},
|
||||
"routing": {
|
||||
"module": self.module,
|
||||
"version": self.module_version,
|
||||
"provider_preference": self.provider_preference,
|
||||
"fallback_chain": self.fallback_chain,
|
||||
"max_fallback_level": self.max_fallback_level
|
||||
},
|
||||
"context": {
|
||||
"lang": self.lang,
|
||||
"mode": self.mode,
|
||||
"pii_filter": self.pii_filter,
|
||||
"bandera_id": self.bandera_id,
|
||||
"player_id": self.player_id,
|
||||
"method_hash": self.method_hash,
|
||||
"human_readable": self.human_readable
|
||||
},
|
||||
"payload": {
|
||||
"type": self.payload_type,
|
||||
"encoding": self.encoding,
|
||||
"content": self.content,
|
||||
"content_hash": self.content_hash,
|
||||
"schema_expected": self.schema_expected
|
||||
},
|
||||
"batch": {
|
||||
"is_batch": self.is_batch,
|
||||
"batch_id": self.batch_id,
|
||||
"item_index": self.item_index,
|
||||
"items_total": self.items_total,
|
||||
"batch_mode": self.batch_mode
|
||||
},
|
||||
"storage": {
|
||||
"input_location": self.input_location,
|
||||
"input_ref": self.input_ref,
|
||||
"output_location": self.output_location,
|
||||
"output_ref": self.output_ref,
|
||||
"persist_intermediate": self.persist_intermediate,
|
||||
"retention_days": self.retention_days
|
||||
},
|
||||
"security": {
|
||||
"encryption_profile": self.encryption_profile,
|
||||
"data_sensitivity": self.data_sensitivity,
|
||||
"key_vault_ref": self.key_vault_ref,
|
||||
"pii_detected": self.pii_detected,
|
||||
"gdpr_relevant": self.gdpr_relevant
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2.2 Uso
|
||||
|
||||
```python
|
||||
# Request LITE para clasificacion
|
||||
request = (
|
||||
ContractBuilder()
|
||||
.for_module("CLASSIFIER")
|
||||
.set_content("Factura de Telefonica por 45.99 EUR")
|
||||
.lite()
|
||||
.build()
|
||||
)
|
||||
|
||||
# Request FULL con fallback
|
||||
request = (
|
||||
ContractBuilder()
|
||||
.for_module("OCR_CORE", "1.0")
|
||||
.set_content(base64_image)
|
||||
.with_fallback(["OCR_LOCAL", "OCR_GROQ", "OCR_OPENAI"])
|
||||
.build()
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 3. ResponseValidator (Python)
|
||||
|
||||
```python
|
||||
from typing import Dict, Any, List, Optional
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class ValidationResult:
|
||||
valid: bool
|
||||
errors: List[str]
|
||||
warnings: List[str]
|
||||
|
||||
class ResponseValidator:
|
||||
"""
|
||||
Validador de responses S-CONTRACT v2.0.
|
||||
"""
|
||||
|
||||
VALID_STATUS_CODES = {'SUCCESS', 'PARTIAL', 'ERROR', 'TIMEOUT', 'FALLBACK'}
|
||||
REQUIRED_LITE = {'contract_version', 'profile', 'envelope', 'status', 'result'}
|
||||
REQUIRED_FULL = REQUIRED_LITE | {'quality', 'metadata', 'storage', 'audit'}
|
||||
|
||||
def validate(self, response: Dict[str, Any]) -> ValidationResult:
|
||||
errors = []
|
||||
warnings = []
|
||||
|
||||
# Contract version
|
||||
if response.get('contract_version') != '2.0':
|
||||
warnings.append(f"Contract version mismatch: {response.get('contract_version')}")
|
||||
|
||||
# Profile
|
||||
profile = response.get('profile', 'FULL')
|
||||
required = self.REQUIRED_LITE if profile == 'LITE' else self.REQUIRED_FULL
|
||||
|
||||
# Required fields
|
||||
for field in required:
|
||||
if field not in response:
|
||||
errors.append(f"Missing required field: {field}")
|
||||
|
||||
# Status validation
|
||||
status = response.get('status', {})
|
||||
if isinstance(status, dict):
|
||||
code = status.get('code')
|
||||
if code not in self.VALID_STATUS_CODES:
|
||||
errors.append(f"Invalid status code: {code}")
|
||||
else:
|
||||
errors.append("Status must be an object with 'code' field")
|
||||
|
||||
# Envelope validation
|
||||
envelope = response.get('envelope', {})
|
||||
if not envelope.get('trace_id'):
|
||||
errors.append("Missing trace_id in envelope")
|
||||
if not envelope.get('idempotency_key'):
|
||||
warnings.append("Missing idempotency_key in envelope")
|
||||
|
||||
# Quality validation (FULL profile)
|
||||
if profile == 'FULL':
|
||||
quality = response.get('quality', {})
|
||||
confidence = quality.get('confidence')
|
||||
if confidence is not None:
|
||||
if not (0 <= confidence <= 1):
|
||||
errors.append(f"Confidence out of range: {confidence}")
|
||||
|
||||
return ValidationResult(
|
||||
valid=len(errors) == 0,
|
||||
errors=errors,
|
||||
warnings=warnings
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 4. Integracion n8n (Alfred)
|
||||
|
||||
## 4.1 Nodo Function: Build Request
|
||||
|
||||
```javascript
|
||||
// n8n Function node: Build S-CONTRACT Request
|
||||
|
||||
const crypto = require('crypto');
|
||||
|
||||
function buildRequest(input, module, profile = 'LITE') {
|
||||
const content = typeof input === 'string' ? input : JSON.stringify(input);
|
||||
const contentHash = crypto.createHash('sha256').update(content).digest('hex');
|
||||
const traceId = $node.data.trace_id || crypto.randomUUID();
|
||||
|
||||
if (profile === 'LITE') {
|
||||
return {
|
||||
contract_version: '2.0',
|
||||
profile: 'LITE',
|
||||
envelope: {
|
||||
trace_id: traceId,
|
||||
idempotency_key: contentHash
|
||||
},
|
||||
routing: { module },
|
||||
context: { lang: 'es', mode: 'strict' },
|
||||
payload: {
|
||||
type: 'text',
|
||||
encoding: 'utf-8',
|
||||
content: content
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
contract_version: '2.0',
|
||||
profile: 'FULL',
|
||||
envelope: {
|
||||
trace_id: traceId,
|
||||
step_id: crypto.randomUUID(),
|
||||
step_index: 1,
|
||||
idempotency_key: contentHash,
|
||||
timestamp_init: new Date().toISOString(),
|
||||
ttl_ms: 30000
|
||||
},
|
||||
routing: {
|
||||
module,
|
||||
fallback_chain: $node.data.fallback_chain || []
|
||||
},
|
||||
context: {
|
||||
lang: 'es',
|
||||
mode: 'strict',
|
||||
player_id: $node.data.player_id,
|
||||
human_readable: $node.data.description
|
||||
},
|
||||
payload: {
|
||||
type: 'text',
|
||||
encoding: 'utf-8',
|
||||
content: content,
|
||||
content_hash: contentHash
|
||||
},
|
||||
batch: { is_batch: false, items_total: 1 },
|
||||
storage: {
|
||||
input_location: 'internal',
|
||||
persist_intermediate: true,
|
||||
retention_days: 30
|
||||
},
|
||||
security: {
|
||||
encryption_profile: 'NONE',
|
||||
data_sensitivity: 'LOW'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Usage
|
||||
const request = buildRequest(
|
||||
$input.first().json.text,
|
||||
'CLASSIFIER',
|
||||
'LITE'
|
||||
);
|
||||
|
||||
return [{ json: request }];
|
||||
```
|
||||
|
||||
## 4.2 Nodo Function: Validate Response
|
||||
|
||||
```javascript
|
||||
// n8n Function node: Validate S-CONTRACT Response
|
||||
|
||||
function validateResponse(response) {
|
||||
const errors = [];
|
||||
const warnings = [];
|
||||
|
||||
// Status check
|
||||
const status = response.status?.code;
|
||||
const validStatus = ['SUCCESS', 'PARTIAL', 'ERROR', 'TIMEOUT', 'FALLBACK'];
|
||||
|
||||
if (!validStatus.includes(status)) {
|
||||
errors.push(`Invalid status: ${status}`);
|
||||
}
|
||||
|
||||
// Envelope check
|
||||
if (!response.envelope?.trace_id) {
|
||||
errors.push('Missing trace_id');
|
||||
}
|
||||
|
||||
// Result check
|
||||
if (status === 'SUCCESS' && !response.result?.data) {
|
||||
warnings.push('SUCCESS status but no result data');
|
||||
}
|
||||
|
||||
return {
|
||||
valid: errors.length === 0,
|
||||
errors,
|
||||
warnings,
|
||||
trace_id: response.envelope?.trace_id,
|
||||
status: status,
|
||||
result: response.result?.data
|
||||
};
|
||||
}
|
||||
|
||||
const validation = validateResponse($input.first().json);
|
||||
|
||||
if (!validation.valid) {
|
||||
throw new Error(`Contract validation failed: ${validation.errors.join(', ')}`);
|
||||
}
|
||||
|
||||
return [{ json: validation }];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 5. Logging a SYS_LOG
|
||||
|
||||
```python
|
||||
import psycopg2
|
||||
from psycopg2.extras import Json
|
||||
from datetime import datetime
|
||||
|
||||
def log_to_syslog(conn, request: dict, response: dict):
|
||||
"""
|
||||
Inserta registro en SYS_LOG.
|
||||
"""
|
||||
envelope = request.get('envelope', {})
|
||||
r_envelope = response.get('envelope', {})
|
||||
status = response.get('status', {})
|
||||
quality = response.get('quality', {})
|
||||
metadata = response.get('metadata', {})
|
||||
|
||||
sql = """
|
||||
INSERT INTO SYS_LOG (
|
||||
trace_id, step_id, idempotency_key,
|
||||
step_index, step_type, profile,
|
||||
timestamp_created, timestamp_started, timestamp_completed,
|
||||
duration_ms,
|
||||
module_name, module_version,
|
||||
provider_used, fallback_level, model_id,
|
||||
status_code,
|
||||
input_hash, input_ref, input_type,
|
||||
output_hash, output_ref,
|
||||
confidence, coverage,
|
||||
tokens_input, tokens_output,
|
||||
cost_units
|
||||
) VALUES (
|
||||
%(trace_id)s, %(step_id)s, %(idempotency_key)s,
|
||||
%(step_index)s, %(step_type)s, %(profile)s,
|
||||
%(timestamp_created)s, %(timestamp_started)s, %(timestamp_completed)s,
|
||||
%(duration_ms)s,
|
||||
%(module_name)s, %(module_version)s,
|
||||
%(provider_used)s, %(fallback_level)s, %(model_id)s,
|
||||
%(status_code)s,
|
||||
%(input_hash)s, %(input_ref)s, %(input_type)s,
|
||||
%(output_hash)s, %(output_ref)s,
|
||||
%(confidence)s, %(coverage)s,
|
||||
%(tokens_input)s, %(tokens_output)s,
|
||||
%(cost_units)s
|
||||
)
|
||||
"""
|
||||
|
||||
params = {
|
||||
'trace_id': envelope.get('trace_id'),
|
||||
'step_id': envelope.get('step_id'),
|
||||
'idempotency_key': envelope.get('idempotency_key'),
|
||||
'step_index': envelope.get('step_index', 1),
|
||||
'step_type': 'TRANSFORM',
|
||||
'profile': request.get('profile', 'FULL'),
|
||||
'timestamp_created': datetime.now(),
|
||||
'timestamp_started': envelope.get('timestamp_init'),
|
||||
'timestamp_completed': r_envelope.get('timestamp_end'),
|
||||
'duration_ms': metadata.get('processing_ms'),
|
||||
'module_name': request.get('routing', {}).get('module'),
|
||||
'module_version': request.get('routing', {}).get('version'),
|
||||
'provider_used': status.get('provider_used'),
|
||||
'fallback_level': status.get('fallback_level_used', 0),
|
||||
'model_id': metadata.get('model_id'),
|
||||
'status_code': status.get('code'),
|
||||
'input_hash': request.get('payload', {}).get('content_hash'),
|
||||
'input_ref': request.get('storage', {}).get('input_ref'),
|
||||
'input_type': request.get('payload', {}).get('type'),
|
||||
'output_hash': response.get('storage', {}).get('output_hash'),
|
||||
'output_ref': response.get('storage', {}).get('output_ref'),
|
||||
'confidence': quality.get('confidence'),
|
||||
'coverage': quality.get('coverage'),
|
||||
'tokens_input': quality.get('tokens_input'),
|
||||
'tokens_output': quality.get('tokens_output'),
|
||||
'cost_units': metadata.get('cost_units')
|
||||
}
|
||||
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(sql, params)
|
||||
conn.commit()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 6. Checklist de Implementacion
|
||||
|
||||
- [ ] Implementar ContractBuilder en Python
|
||||
- [ ] Implementar ContractBuilder en JavaScript (n8n)
|
||||
- [ ] Implementar ResponseValidator
|
||||
- [ ] Crear funcion log_to_syslog
|
||||
- [ ] Configurar nodos n8n con templates
|
||||
- [ ] Probar flujo completo LITE
|
||||
- [ ] Probar flujo completo FULL
|
||||
- [ ] Probar fallback chain
|
||||
|
||||
---
|
||||
|
||||
**Fin del Documento IMPLEMENTACION - Version 2.0**
|
||||
|
||||
*Sistema GRACE - "Alfred Decide, GRACE Transforma"*
|
||||
595
v4-archive/contratos-comunes/docs/KEY_VAULT.md
Normal file
595
v4-archive/contratos-comunes/docs/KEY_VAULT.md
Normal file
@@ -0,0 +1,595 @@
|
||||
# 07c. KEY VAULT Y CRIPTOGRAFÍA
|
||||
**Manual de Arquitectura Técnica — Documento 07c**
|
||||
**Versión:** 1.2
|
||||
**Dependencia:** `S-CONTRACT.md`
|
||||
**Estado:** Enterprise Standard
|
||||
|
||||
---
|
||||
|
||||
# C.1 Introducción
|
||||
|
||||
El Key Vault es el **tercer espacio de almacenamiento** del ecosistema, separado de:
|
||||
- **Libro Mayor (SFE)**: Datos de negocio
|
||||
- **Almacenamiento de archivos**: Hostinger/S3
|
||||
- **Key Vault**: Llaves, credenciales y secretos
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ PRINCIPIO DE SEPARACIÓN │
|
||||
│ │
|
||||
│ "Las llaves nunca viajan con los datos que protegen" │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# C.2 Arquitectura del Key Vault
|
||||
|
||||
## C.2.1 Componentes
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ KEY VAULT │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ SECRETS │ │ KEYS │ │ CERTS │ │
|
||||
│ │ STORE │ │ STORE │ │ STORE │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
│ │ │ │ │
|
||||
│ └──────────────────┼──────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────┴──────┐ │
|
||||
│ │ ACCESS │ │
|
||||
│ │ CONTROL │ │
|
||||
│ └──────┬──────┘ │
|
||||
│ │ │
|
||||
│ ┌──────┴──────┐ │
|
||||
│ │ AUDIT LOG │ │
|
||||
│ └─────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## C.2.2 Tipos de Secretos
|
||||
|
||||
| Tipo | Descripción | Ejemplo | Rotación |
|
||||
|------|-------------|---------|----------|
|
||||
| **API_KEY** | Llaves de APIs externas | OpenRouter, Groq | 90 días |
|
||||
| **ENCRYPTION_KEY** | Llaves de cifrado de datos | AES-256 keys | 365 días |
|
||||
| **DB_CREDENTIAL** | Credenciales de bases de datos | NocoDB, PostgreSQL | 30 días |
|
||||
| **SERVICE_TOKEN** | Tokens de servicios internos | n8n, Nextcloud | 7 días |
|
||||
| **USER_SECRET** | Secretos específicos de usuario | OAuth tokens | Variable |
|
||||
| **CERTIFICATE** | Certificados TLS/mTLS | SSL certs | 90 días |
|
||||
| **SIGNING_KEY** | Llaves de firma digital | JWT signing | 180 días |
|
||||
|
||||
---
|
||||
|
||||
# C.3 Modelo de Datos
|
||||
|
||||
## C.3.1 Tabla VAULT_SECRETS
|
||||
|
||||
```sql
|
||||
CREATE TABLE VAULT_SECRETS (
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- IDENTIFICACIÓN
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
secret_id VARCHAR(100) UNIQUE NOT NULL,
|
||||
version INTEGER DEFAULT 1,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- CLASIFICACIÓN
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
secret_type VARCHAR(50) NOT NULL,
|
||||
category VARCHAR(50),
|
||||
tags VARCHAR(50)[],
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- VALOR (CIFRADO)
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
encrypted_value BYTEA NOT NULL,
|
||||
encryption_algorithm VARCHAR(50) DEFAULT 'AES-256-GCM',
|
||||
key_encryption_key_id VARCHAR(100),
|
||||
nonce BYTEA,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- METADATA
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
description TEXT,
|
||||
owner_id UUID,
|
||||
owner_type VARCHAR(50),
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- CICLO DE VIDA
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
status VARCHAR(20) DEFAULT 'ACTIVE',
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
expires_at TIMESTAMPTZ,
|
||||
last_rotated_at TIMESTAMPTZ,
|
||||
rotation_interval_days INTEGER,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- ACCESO
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
access_policy JSONB DEFAULT '{}',
|
||||
allowed_modules VARCHAR(50)[],
|
||||
allowed_players UUID[],
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- AUDITORÍA
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
access_count INTEGER DEFAULT 0,
|
||||
last_accessed_at TIMESTAMPTZ,
|
||||
last_accessed_by VARCHAR(100),
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- CONSTRAINTS
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
CONSTRAINT valid_status CHECK (
|
||||
status IN ('ACTIVE', 'DISABLED', 'EXPIRED', 'ROTATING', 'DELETED')
|
||||
),
|
||||
CONSTRAINT valid_type CHECK (
|
||||
secret_type IN ('API_KEY', 'ENCRYPTION_KEY', 'DB_CREDENTIAL',
|
||||
'SERVICE_TOKEN', 'USER_SECRET', 'CERTIFICATE', 'SIGNING_KEY')
|
||||
)
|
||||
);
|
||||
|
||||
-- Índices
|
||||
CREATE INDEX idx_vault_secret_id ON VAULT_SECRETS(secret_id);
|
||||
CREATE INDEX idx_vault_type ON VAULT_SECRETS(secret_type);
|
||||
CREATE INDEX idx_vault_status ON VAULT_SECRETS(status);
|
||||
CREATE INDEX idx_vault_expires ON VAULT_SECRETS(expires_at) WHERE expires_at IS NOT NULL;
|
||||
CREATE INDEX idx_vault_owner ON VAULT_SECRETS(owner_id);
|
||||
```
|
||||
|
||||
## C.3.2 Tabla VAULT_ACCESS_LOG
|
||||
|
||||
```sql
|
||||
CREATE TABLE VAULT_ACCESS_LOG (
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- IDENTIFICACIÓN
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- SECRETO ACCEDIDO
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
secret_id VARCHAR(100) NOT NULL,
|
||||
secret_version INTEGER,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- CONTEXTO DE ACCESO
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
trace_id UUID,
|
||||
step_id UUID,
|
||||
module_name VARCHAR(50),
|
||||
operation VARCHAR(50) NOT NULL,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- ACTOR
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
accessor_type VARCHAR(50) NOT NULL,
|
||||
accessor_id VARCHAR(100) NOT NULL,
|
||||
accessor_ip INET,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- RESULTADO
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
status VARCHAR(20) NOT NULL,
|
||||
error_code VARCHAR(50),
|
||||
error_message TEXT,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- TEMPORALIDAD
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
timestamp TIMESTAMPTZ DEFAULT NOW(),
|
||||
duration_ms INTEGER,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- SEGURIDAD
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
encryption_profile VARCHAR(20),
|
||||
purpose TEXT,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- CONSTRAINTS
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
CONSTRAINT valid_operation CHECK (
|
||||
operation IN ('READ', 'CREATE', 'UPDATE', 'DELETE', 'ROTATE',
|
||||
'ENABLE', 'DISABLE', 'LIST', 'DECRYPT', 'ENCRYPT')
|
||||
),
|
||||
CONSTRAINT valid_access_status CHECK (
|
||||
status IN ('SUCCESS', 'DENIED', 'ERROR', 'EXPIRED', 'NOT_FOUND')
|
||||
),
|
||||
CONSTRAINT valid_accessor CHECK (
|
||||
accessor_type IN ('MODULE', 'PLAYER', 'SYSTEM', 'ADMIN', 'SERVICE')
|
||||
)
|
||||
);
|
||||
|
||||
-- Índices para auditoría eficiente
|
||||
CREATE INDEX idx_vault_log_secret ON VAULT_ACCESS_LOG(secret_id);
|
||||
CREATE INDEX idx_vault_log_trace ON VAULT_ACCESS_LOG(trace_id) WHERE trace_id IS NOT NULL;
|
||||
CREATE INDEX idx_vault_log_timestamp ON VAULT_ACCESS_LOG(timestamp);
|
||||
CREATE INDEX idx_vault_log_accessor ON VAULT_ACCESS_LOG(accessor_type, accessor_id);
|
||||
CREATE INDEX idx_vault_log_denied ON VAULT_ACCESS_LOG(status, timestamp)
|
||||
WHERE status = 'DENIED';
|
||||
```
|
||||
|
||||
## C.3.3 Tabla VAULT_ENCRYPTION_KEYS (KEK)
|
||||
|
||||
```sql
|
||||
CREATE TABLE VAULT_ENCRYPTION_KEYS (
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- IDENTIFICACIÓN
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
key_id VARCHAR(100) UNIQUE NOT NULL,
|
||||
version INTEGER DEFAULT 1,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- PROPIEDADES
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
algorithm VARCHAR(50) NOT NULL DEFAULT 'AES-256-GCM',
|
||||
key_size_bits INTEGER NOT NULL DEFAULT 256,
|
||||
purpose VARCHAR(50) NOT NULL,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- VALOR (protegido por Master Key externa)
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
encrypted_key_material BYTEA NOT NULL,
|
||||
master_key_ref VARCHAR(100),
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- CICLO DE VIDA
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
status VARCHAR(20) DEFAULT 'ACTIVE',
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
activated_at TIMESTAMPTZ,
|
||||
expires_at TIMESTAMPTZ,
|
||||
deactivated_at TIMESTAMPTZ,
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- CONSTRAINTS
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
CONSTRAINT valid_kek_status CHECK (
|
||||
status IN ('PENDING', 'ACTIVE', 'DEACTIVATED', 'DESTROYED')
|
||||
),
|
||||
CONSTRAINT valid_purpose CHECK (
|
||||
purpose IN ('DATA_ENCRYPTION', 'SECRET_ENCRYPTION', 'SIGNING', 'KEY_WRAPPING')
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# C.4 Perfiles de Cifrado
|
||||
|
||||
## C.4.1 Perfil NONE
|
||||
|
||||
```yaml
|
||||
profile: NONE
|
||||
description: "Sin cifrado gestionado por el sistema"
|
||||
transport: TLS 1.3 (obligatorio)
|
||||
at_rest: Sin cifrar
|
||||
use_cases:
|
||||
- Datos públicos
|
||||
- Logs técnicos no sensibles
|
||||
- Métricas de rendimiento
|
||||
key_vault: No requerido
|
||||
```
|
||||
|
||||
## C.4.2 Perfil E2E_BASIC
|
||||
|
||||
```yaml
|
||||
profile: E2E_BASIC
|
||||
description: "Cifrado estándar para datos internos"
|
||||
transport: TLS 1.3
|
||||
at_rest:
|
||||
algorithm: AES-256-GCM
|
||||
key_derivation: PBKDF2-SHA256
|
||||
key_rotation: Anual
|
||||
use_cases:
|
||||
- Documentos internos
|
||||
- Emails corporativos
|
||||
- Datos de configuración
|
||||
key_vault:
|
||||
required: true
|
||||
key_type: ENCRYPTION_KEY
|
||||
access_policy: module_based
|
||||
```
|
||||
|
||||
## C.4.3 Perfil E2E_STRICT
|
||||
|
||||
```yaml
|
||||
profile: E2E_STRICT
|
||||
description: "Cifrado fuerte para datos sensibles"
|
||||
transport: mTLS (mutual TLS)
|
||||
at_rest:
|
||||
algorithm: AES-256-GCM
|
||||
key_derivation: Argon2id
|
||||
key_rotation: Trimestral
|
||||
envelope_encryption: true
|
||||
additional:
|
||||
- PII masking antes de procesar
|
||||
- Audit logging obligatorio
|
||||
- Zero-knowledge donde sea posible
|
||||
use_cases:
|
||||
- PII (datos personales)
|
||||
- Datos financieros
|
||||
- Información médica
|
||||
- Biometría
|
||||
key_vault:
|
||||
required: true
|
||||
key_type: ENCRYPTION_KEY
|
||||
access_policy: per_record
|
||||
key_isolation: true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# C.5 Operaciones del Key Vault
|
||||
|
||||
## C.5.1 URIs del Key Vault
|
||||
|
||||
El contrato común usa referencias URI al Key Vault:
|
||||
|
||||
```
|
||||
kv://production/encryption/player_abc123
|
||||
kv://production/api-keys/openrouter
|
||||
kv://staging/certificates/mtls-client
|
||||
```
|
||||
|
||||
Formato:
|
||||
```
|
||||
kv://{environment}/{category}/{secret_id}
|
||||
```
|
||||
|
||||
## C.5.2 Integración con el Contrato
|
||||
|
||||
En el request:
|
||||
```json
|
||||
"security": {
|
||||
"encryption_profile": "E2E_STRICT",
|
||||
"data_sensitivity": "HIGH",
|
||||
"key_vault_ref": "kv://production/encryption/player_abc123"
|
||||
}
|
||||
```
|
||||
|
||||
Alfred al procesar:
|
||||
1. Extrae `key_vault_ref`
|
||||
2. Solicita la llave al Key Vault (pasando `trace_id`)
|
||||
3. Descifra el payload si viene cifrado
|
||||
4. Procesa con GRACE
|
||||
5. Cifra el resultado con la misma llave (o una derivada)
|
||||
6. Almacena resultado cifrado
|
||||
|
||||
---
|
||||
|
||||
# C.6 Flujo de Cifrado End-to-End
|
||||
|
||||
## C.6.1 Envelope Encryption
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ ENVELOPE ENCRYPTION │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ Plaintext │ │
|
||||
│ │ Data │ │
|
||||
│ └──────┬──────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Data │◄───│ DEK │ (Data Encryption Key) │
|
||||
│ │ Encrypted │ │ (efímera) │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ │
|
||||
│ │ │ │
|
||||
│ │ ▼ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ │ DEK │◄───│ KEK │ │
|
||||
│ │ │ Encrypted │ │ (Key Vault) │ │
|
||||
│ │ └──────┬──────┘ └─────────────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌──────────────────────────────────────┐ │
|
||||
│ │ Stored Package: │ │
|
||||
│ │ - encrypted_data │ │
|
||||
│ │ - encrypted_dek │ │
|
||||
│ │ - kek_id │ │
|
||||
│ │ - nonce │ │
|
||||
│ │ - algorithm │ │
|
||||
│ └──────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## C.6.2 Implementación Python
|
||||
|
||||
```python
|
||||
import os
|
||||
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||
import base64
|
||||
|
||||
class EnvelopeEncryption:
|
||||
"""Implementa envelope encryption para E2E_STRICT."""
|
||||
|
||||
def __init__(self, key_vault_client):
|
||||
self.vault = key_vault_client
|
||||
|
||||
async def encrypt(self, plaintext: bytes, kek_id: str) -> dict:
|
||||
"""Cifra datos usando envelope encryption."""
|
||||
# 1. Generar DEK efímera
|
||||
dek = os.urandom(32)
|
||||
data_nonce = os.urandom(12)
|
||||
|
||||
# 2. Cifrar datos con DEK
|
||||
aesgcm = AESGCM(dek)
|
||||
encrypted_data = aesgcm.encrypt(data_nonce, plaintext, None)
|
||||
|
||||
# 3. Obtener KEK y cifrar DEK
|
||||
kek = await self.vault.get_secret(kek_id)
|
||||
dek_nonce = os.urandom(12)
|
||||
kek_aesgcm = AESGCM(kek)
|
||||
encrypted_dek = kek_aesgcm.encrypt(dek_nonce, dek, kek_id.encode())
|
||||
|
||||
return {
|
||||
"encrypted_data": base64.b64encode(encrypted_data).decode(),
|
||||
"encrypted_dek": base64.b64encode(encrypted_dek).decode(),
|
||||
"data_nonce": base64.b64encode(data_nonce).decode(),
|
||||
"dek_nonce": base64.b64encode(dek_nonce).decode(),
|
||||
"kek_id": kek_id,
|
||||
"algorithm": "AES-256-GCM"
|
||||
}
|
||||
|
||||
async def decrypt(self, package: dict) -> bytes:
|
||||
"""Descifra datos usando envelope encryption."""
|
||||
# 1. Obtener KEK
|
||||
kek = await self.vault.get_secret(package["kek_id"])
|
||||
|
||||
# 2. Descifrar DEK
|
||||
kek_aesgcm = AESGCM(kek)
|
||||
dek = kek_aesgcm.decrypt(
|
||||
base64.b64decode(package["dek_nonce"]),
|
||||
base64.b64decode(package["encrypted_dek"]),
|
||||
package["kek_id"].encode()
|
||||
)
|
||||
|
||||
# 3. Descifrar datos
|
||||
aesgcm = AESGCM(dek)
|
||||
return aesgcm.decrypt(
|
||||
base64.b64decode(package["data_nonce"]),
|
||||
base64.b64decode(package["encrypted_data"]),
|
||||
None
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# C.7 Gestión de Llaves
|
||||
|
||||
## C.7.1 Jerarquía de Llaves
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ JERARQUÍA DE LLAVES │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ MASTER KEY (MK) │ │
|
||||
│ │ Almacenada fuera del sistema │ │
|
||||
│ │ (HSM / KMS externo / Variable de entorno) │ │
|
||||
│ └────────────────────────┬────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────────────┼───────────────┐ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ KEK-DATA │ │ KEK-SECRETS │ │ KEK-SIGNING │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ DEK-1..n │ │ API Keys │ │ JWT Keys │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## C.7.2 Política de Rotación
|
||||
|
||||
| Tipo de Llave | Rotación | Período de Gracia | Automatizable |
|
||||
|---------------|----------|-------------------|---------------|
|
||||
| Master Key | Anual | 30 días | No (manual) |
|
||||
| KEK | Semestral | 14 días | Sí |
|
||||
| DEK | Por sesión | N/A | Automático |
|
||||
| API Keys | 90 días | 7 días | Sí |
|
||||
|
||||
---
|
||||
|
||||
# C.8 Control de Acceso
|
||||
|
||||
## C.8.1 Políticas de Acceso
|
||||
|
||||
```json
|
||||
{
|
||||
"secret_id": "openrouter-api-key",
|
||||
"access_policy": {
|
||||
"type": "MODULE_BASED",
|
||||
"rules": [
|
||||
{
|
||||
"principal_type": "MODULE",
|
||||
"principals": ["CLASSIFIER", "SUMMARIZER", "OCR_CORE"],
|
||||
"operations": ["READ"],
|
||||
"conditions": {
|
||||
"require_trace_id": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"principal_type": "ADMIN",
|
||||
"principals": ["admin@tzzr.pro"],
|
||||
"operations": ["READ", "UPDATE", "ROTATE", "DELETE"],
|
||||
"conditions": {
|
||||
"require_mfa": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"default_deny": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# C.9 Integración con SENTINEL
|
||||
|
||||
## C.9.1 Reglas de Auditoría
|
||||
|
||||
```yaml
|
||||
rules:
|
||||
KV-001:
|
||||
name: "Accesos denegados excesivos"
|
||||
severity: HIGH
|
||||
condition: "denied_count_1h > 5 per accessor"
|
||||
action: ALERT_SECURITY
|
||||
|
||||
KV-002:
|
||||
name: "Secreto próximo a expirar"
|
||||
severity: MEDIUM
|
||||
condition: "expires_at < NOW() + 7 days"
|
||||
action: NOTIFY_ADMIN
|
||||
|
||||
KV-003:
|
||||
name: "Rotación pendiente"
|
||||
severity: MEDIUM
|
||||
condition: "last_rotated_at < NOW() - rotation_interval"
|
||||
action: SCHEDULE_ROTATION
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# C.10 Checklist de Implementación
|
||||
|
||||
## Infraestructura:
|
||||
- [ ] Crear tablas VAULT_SECRETS, VAULT_ACCESS_LOG, VAULT_ENCRYPTION_KEYS
|
||||
- [ ] Configurar Master Key (variable de entorno o KMS)
|
||||
- [ ] Generar KEKs iniciales
|
||||
- [ ] Configurar backup automático
|
||||
|
||||
## Integración:
|
||||
- [ ] Implementar cliente Key Vault
|
||||
- [ ] Integrar con ContractBuilder
|
||||
- [ ] Implementar envelope encryption
|
||||
|
||||
## Seguridad:
|
||||
- [ ] Configurar políticas de acceso
|
||||
- [ ] Habilitar logging de accesos
|
||||
- [ ] Configurar alertas SENTINEL
|
||||
- [ ] Establecer rotación automática
|
||||
|
||||
---
|
||||
|
||||
**Fin del Documento 07c — Key Vault y Criptografía**
|
||||
|
||||
*Referencia: `S-CONTRACT.md` v1.2*
|
||||
528
v4-archive/contratos-comunes/docs/LECCIONES_CORP.md
Normal file
528
v4-archive/contratos-comunes/docs/LECCIONES_CORP.md
Normal file
@@ -0,0 +1,528 @@
|
||||
# Lecciones para CORP
|
||||
|
||||
**Documento de onboarding para empresas del ecosistema TZZR**
|
||||
|
||||
---
|
||||
|
||||
## Leccion 1: Que es CORP
|
||||
|
||||
CORP es una **empresa** dentro del ecosistema TZZR. No es un sistema, es un tenant.
|
||||
|
||||
```
|
||||
ECOSISTEMA TZZR
|
||||
├── DECK → Orquestador para HUMANOS
|
||||
├── CORP → Orquestador para EMPRESAS (tu)
|
||||
├── GRACE → Procesamiento IA
|
||||
├── THE FACTORY → Procesamiento documental
|
||||
├── PENNY → Asistente de voz (solo humanos)
|
||||
└── HST → Sistema de etiquetas
|
||||
```
|
||||
|
||||
### Lo que puedes hacer
|
||||
- Llamar a GRACE (clasificar, extraer, resumir)
|
||||
- Llamar a THE FACTORY (procesar documentos)
|
||||
- Usar etiquetas HST para organizar
|
||||
|
||||
### Lo que NO puedes hacer
|
||||
- Llamar a PENNY (es solo para humanos via DECK)
|
||||
|
||||
---
|
||||
|
||||
## Leccion 2: S-CONTRACT
|
||||
|
||||
Toda comunicacion con GRACE y THE FACTORY usa el formato **S-CONTRACT v2.1**.
|
||||
|
||||
### Request minimo (perfil LITE)
|
||||
|
||||
```json
|
||||
{
|
||||
"contract_version": "2.1",
|
||||
"profile": "LITE",
|
||||
"envelope": {
|
||||
"trace_id": "uuid-unico-por-request",
|
||||
"idempotency_key": "sha256-del-contenido-64-chars"
|
||||
},
|
||||
"routing": {
|
||||
"module": "CLASSIFIER"
|
||||
},
|
||||
"context": {
|
||||
"lang": "es"
|
||||
},
|
||||
"payload": {
|
||||
"type": "text",
|
||||
"encoding": "utf-8",
|
||||
"content": "Factura de Telefonica por 45.99 EUR"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Request completo (perfil FULL)
|
||||
|
||||
```json
|
||||
{
|
||||
"contract_version": "2.1",
|
||||
"profile": "FULL",
|
||||
"envelope": {
|
||||
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"idempotency_key": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234",
|
||||
"step_id": "660e8400-e29b-41d4-a716-446655440001",
|
||||
"step_index": 1,
|
||||
"timestamp_init": "2025-12-18T10:00:00Z",
|
||||
"ttl_ms": 30000
|
||||
},
|
||||
"routing": {
|
||||
"module": "CLASSIFIER",
|
||||
"version": "1.0",
|
||||
"provider_preference": ["groq", "openai"],
|
||||
"max_fallback_level": 2
|
||||
},
|
||||
"context": {
|
||||
"lang": "es",
|
||||
"mode": "strict",
|
||||
"pii_filter": false,
|
||||
"system_instruction": "Clasifica el documento segun categoria contable.",
|
||||
"datasets": [
|
||||
{
|
||||
"codigo": "DS_CATEGORIAS_CORP",
|
||||
"tipo": "vocabulary",
|
||||
"contenido": "GASTO_OPERATIVO, GASTO_FINANCIERO, INGRESO_VENTA..."
|
||||
}
|
||||
],
|
||||
"tags": {
|
||||
"hst": ["335350bb41a329c..."],
|
||||
"hsu": [],
|
||||
"emp": ["h_maestro_de_corp..."],
|
||||
"pjt": ["h_maestro_proyecto..."]
|
||||
},
|
||||
"ambiente": {
|
||||
"timezone": "Europe/Madrid",
|
||||
"locale": "es-ES",
|
||||
"currency": "EUR",
|
||||
"session_type": "batch"
|
||||
}
|
||||
},
|
||||
"payload": {
|
||||
"type": "document",
|
||||
"encoding": "url",
|
||||
"content": "https://storage.corp.example/factura-001.pdf"
|
||||
},
|
||||
"deployment": {
|
||||
"mode": "SEMI",
|
||||
"tier_preference": ["SELF_HOSTED", "EXTERNAL"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Response esperada
|
||||
|
||||
```json
|
||||
{
|
||||
"contract_version": "2.1",
|
||||
"profile": "FULL",
|
||||
"envelope": {
|
||||
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"idempotency_key": "a1b2c3d4e5f6...",
|
||||
"timestamp_end": "2025-12-18T10:00:03Z"
|
||||
},
|
||||
"status": {
|
||||
"code": "SUCCESS",
|
||||
"provider_used": "groq",
|
||||
"deployment_used": {
|
||||
"mode": "SEMI",
|
||||
"tier_used": "EXTERNAL",
|
||||
"provider_used": "groq"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"schema": "classifier_output_v1",
|
||||
"data": {
|
||||
"category": "GASTO_OPERATIVO",
|
||||
"subcategory": "TELECOMUNICACIONES",
|
||||
"confidence": 0.94
|
||||
}
|
||||
},
|
||||
"quality": {
|
||||
"confidence": 0.94,
|
||||
"coverage": 1.0
|
||||
},
|
||||
"metadata": {
|
||||
"model_id": "llama-3.3-70b",
|
||||
"processing_ms": 1234
|
||||
},
|
||||
"errors": []
|
||||
}
|
||||
```
|
||||
|
||||
### Status codes
|
||||
|
||||
| Code | Significado |
|
||||
|------|-------------|
|
||||
| `SUCCESS` | Todo bien |
|
||||
| `PARTIAL` | Resultado incompleto pero usable |
|
||||
| `ERROR` | Fallo |
|
||||
| `TIMEOUT` | Excedio tiempo |
|
||||
| `FALLBACK` | Exito con proveedor alternativo |
|
||||
|
||||
---
|
||||
|
||||
## Leccion 3: HST (Sistema de Etiquetas)
|
||||
|
||||
HST es el sistema de etiquetas que da coherencia semantica a todo.
|
||||
|
||||
### API disponible
|
||||
|
||||
```bash
|
||||
# Todas las etiquetas
|
||||
GET https://tzrtech.org/api/index.json
|
||||
|
||||
# Tag especifico
|
||||
GET https://tzrtech.org/api/tags/{h_maestro}
|
||||
|
||||
# Buscar
|
||||
GET https://tzrtech.org/api/tags?grupo=hst
|
||||
GET https://tzrtech.org/api/tags?q=finanzas
|
||||
```
|
||||
|
||||
### Grupos de etiquetas
|
||||
|
||||
| Grupo | Descripcion | Quien las crea |
|
||||
|-------|-------------|----------------|
|
||||
| `hst` | Sistema | tzrtech.org (sync) |
|
||||
| `emp` | Empresa | Tu (CORP) |
|
||||
| `hsu` | Usuario | Tu (para tus usuarios) |
|
||||
| `pjt` | Proyecto | Tu (para tus proyectos) |
|
||||
|
||||
### Sistema dual de hashes
|
||||
|
||||
```
|
||||
h_maestro = SHA256(grupo || ':' || ref)
|
||||
→ Identifica semanticamente (para S-CONTRACT)
|
||||
→ Ejemplo: SHA256("hst:finanzas") = "a7b3c9..."
|
||||
|
||||
mrf = SHA256(bytes_imagen)
|
||||
→ Identifica el archivo de imagen
|
||||
→ URL: https://tzrtech.org/{mrf}.png
|
||||
```
|
||||
|
||||
### Calcular h_maestro
|
||||
|
||||
```python
|
||||
import hashlib
|
||||
|
||||
def h_maestro(grupo: str, ref: str) -> str:
|
||||
return hashlib.sha256(f"{grupo}:{ref}".encode()).hexdigest()
|
||||
|
||||
# Ejemplo
|
||||
h = h_maestro("emp", "corp") # Tu identidad como empresa
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Leccion 4: Modulos disponibles
|
||||
|
||||
### GRACE (18 modulos)
|
||||
|
||||
| Modulo | Familia | Uso |
|
||||
|--------|---------|-----|
|
||||
| `CLASSIFIER` | SEMANTICA | Clasificar documentos |
|
||||
| `SUMMARIZER` | SEMANTICA | Resumir textos |
|
||||
| `TASK_EXTRACTOR` | SEMANTICA | Extraer tareas de texto |
|
||||
| `FIELD_EXTRACTOR` | UTILIDADES | Extraer campos estructurados |
|
||||
| `OCR_CORE` | VISION | Extraer texto de imagenes |
|
||||
| `ASR_ENGINE` | VOZ | Transcribir audio |
|
||||
| `EMBEDDINGS` | SEMANTICA | Vectorizar texto |
|
||||
| `SIMILARITY` | SEMANTICA | Comparar textos |
|
||||
| `LANG_DETECT` | UTILIDADES | Detectar idioma |
|
||||
|
||||
### THE FACTORY
|
||||
|
||||
Procesamiento documental:
|
||||
- PDF a texto
|
||||
- Extraccion estructurada
|
||||
- OCR de facturas
|
||||
- Consolidacion de documentos
|
||||
|
||||
---
|
||||
|
||||
## Leccion 5: Tablas PostgreSQL
|
||||
|
||||
Usaras las mismas estructuras que DECK. Schemas en `contratos-comunes/db-schemas/`.
|
||||
|
||||
### Orden de aplicacion
|
||||
|
||||
```bash
|
||||
psql -f 00_types.sql # Tipos enumerados
|
||||
psql -f 01_hst_tags.sql # Etiquetas HST
|
||||
psql -f 02_task_manager.sql # Proyectos y tareas
|
||||
psql -f 03_work_log.sql # Log de archivos
|
||||
psql -f 04_ai_context.sql # Contextos IA
|
||||
psql -f 05_ai_requests.sql # Log de requests
|
||||
```
|
||||
|
||||
### Tabla: hst_tags (tus etiquetas propias)
|
||||
|
||||
```sql
|
||||
CREATE TABLE hst_tags (
|
||||
id SERIAL PRIMARY KEY,
|
||||
h_maestro VARCHAR(64) UNIQUE NOT NULL, -- SHA256(grupo:ref)
|
||||
ref VARCHAR(50) NOT NULL, -- Codigo corto
|
||||
mrf VARCHAR(64), -- Hash de imagen (opcional)
|
||||
nombre VARCHAR(100) NOT NULL,
|
||||
nombre_en VARCHAR(100),
|
||||
grupo hst_grupo NOT NULL, -- emp, hsu, pjt
|
||||
padre_h_maestro VARCHAR(64), -- Jerarquia
|
||||
activo BOOLEAN DEFAULT true
|
||||
);
|
||||
|
||||
-- Tus etiquetas de empresa
|
||||
INSERT INTO hst_tags (h_maestro, ref, nombre, grupo) VALUES
|
||||
(generate_h_maestro('emp', 'corp'), 'corp', 'CORP', 'emp');
|
||||
|
||||
-- Tus proyectos
|
||||
INSERT INTO hst_tags (h_maestro, ref, nombre, grupo) VALUES
|
||||
(generate_h_maestro('pjt', 'contabilidad_2025'), 'contabilidad_2025', 'Contabilidad 2025', 'pjt');
|
||||
```
|
||||
|
||||
### Tabla: s_contract_contexts (contextos reutilizables)
|
||||
|
||||
```sql
|
||||
-- Crear un contexto para tus operaciones
|
||||
INSERT INTO s_contract_contexts (codigo, nombre, context, deployment) VALUES
|
||||
(
|
||||
'CTX_CORP_FACTURAS',
|
||||
'Contexto para facturas CORP',
|
||||
'{
|
||||
"lang": "es",
|
||||
"mode": "strict",
|
||||
"system_instruction": "Procesa facturas de CORP. Extrae: proveedor, fecha, importe, IVA.",
|
||||
"datasets": [],
|
||||
"tags": {"hst": [], "hsu": [], "emp": ["h_corp..."], "pjt": []},
|
||||
"ambiente": {"timezone": "Europe/Madrid", "locale": "es-ES", "currency": "EUR"}
|
||||
}'::jsonb,
|
||||
'{"mode": "SEMI", "tier_preference": ["EXTERNAL", "SELF_HOSTED"]}'::jsonb
|
||||
);
|
||||
```
|
||||
|
||||
### Tabla: ai_requests (log de tus requests)
|
||||
|
||||
```sql
|
||||
-- Registrar cada request que hagas
|
||||
INSERT INTO ai_requests (
|
||||
trace_id, service, module, context_codigo, status
|
||||
) VALUES (
|
||||
'tu-trace-id',
|
||||
'grace',
|
||||
'CLASSIFIER',
|
||||
'CTX_CORP_FACTURAS',
|
||||
'pending'
|
||||
);
|
||||
|
||||
-- Actualizar cuando termine
|
||||
UPDATE ai_requests SET
|
||||
status = 'success',
|
||||
tier_used = 'EXTERNAL',
|
||||
provider_used = 'groq',
|
||||
latency_ms = 1234,
|
||||
completed_at = NOW()
|
||||
WHERE trace_id = 'tu-trace-id';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Leccion 6: Tu libro diario (MST + BCK)
|
||||
|
||||
Como empresa, llevas un libro diario con dos partes:
|
||||
|
||||
### MST (Master)
|
||||
|
||||
Registro principal de operaciones:
|
||||
|
||||
```sql
|
||||
CREATE TABLE corp_libro_mst (
|
||||
id SERIAL PRIMARY KEY,
|
||||
fecha DATE NOT NULL,
|
||||
tipo VARCHAR(50) NOT NULL, -- ingreso, gasto, asiento
|
||||
concepto TEXT NOT NULL,
|
||||
importe DECIMAL(12,2),
|
||||
moneda VARCHAR(3) DEFAULT 'EUR',
|
||||
|
||||
-- Referencias
|
||||
documento_ref TEXT, -- URL al documento
|
||||
h_maestro_categoria VARCHAR(64), -- Etiqueta HST
|
||||
|
||||
-- Trazabilidad
|
||||
trace_id VARCHAR(36), -- Si vino de IA
|
||||
procesado_por VARCHAR(50), -- grace, factory, manual
|
||||
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### BCK (Backup/Auditoria)
|
||||
|
||||
Copia de respaldo con historial:
|
||||
|
||||
```sql
|
||||
CREATE TABLE corp_libro_bck (
|
||||
id SERIAL PRIMARY KEY,
|
||||
mst_id INTEGER REFERENCES corp_libro_mst(id),
|
||||
version INTEGER DEFAULT 1,
|
||||
datos_anteriores JSONB,
|
||||
datos_nuevos JSONB,
|
||||
motivo_cambio TEXT,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Leccion 7: Flujo de trabajo
|
||||
|
||||
```
|
||||
1. Llega documento (factura PDF)
|
||||
│
|
||||
▼
|
||||
2. Almacenas en bandeja de entrada
|
||||
│
|
||||
▼
|
||||
3. Construyes S-CONTRACT
|
||||
{routing: {module: "FIELD_EXTRACTOR"}, ...}
|
||||
│
|
||||
▼
|
||||
4. Envias a GRACE o THE FACTORY
|
||||
│
|
||||
▼
|
||||
5. Recibes respuesta estructurada
|
||||
{result: {data: {proveedor: "X", importe: 100}}}
|
||||
│
|
||||
▼
|
||||
6. Registras en tu libro MST
|
||||
│
|
||||
▼
|
||||
7. Etiquetas con HST
|
||||
│
|
||||
▼
|
||||
8. Mueves de bandeja a procesado
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Leccion 8: Codigo Python base
|
||||
|
||||
```python
|
||||
import hashlib
|
||||
import uuid
|
||||
import requests
|
||||
from datetime import datetime, timezone
|
||||
|
||||
class CorpClient:
|
||||
def __init__(self, grace_url: str, factory_url: str):
|
||||
self.grace_url = grace_url
|
||||
self.factory_url = factory_url
|
||||
self.emp_h_maestro = self.h_maestro("emp", "corp")
|
||||
|
||||
def h_maestro(self, grupo: str, ref: str) -> str:
|
||||
return hashlib.sha256(f"{grupo}:{ref}".encode()).hexdigest()
|
||||
|
||||
def idempotency_key(self, content: str) -> str:
|
||||
return hashlib.sha256(content.encode()).hexdigest()
|
||||
|
||||
def build_request(
|
||||
self,
|
||||
module: str,
|
||||
content: str,
|
||||
content_type: str = "text",
|
||||
system_instruction: str = None,
|
||||
tags_pjt: list = None
|
||||
) -> dict:
|
||||
return {
|
||||
"contract_version": "2.1",
|
||||
"profile": "FULL",
|
||||
"envelope": {
|
||||
"trace_id": str(uuid.uuid4()),
|
||||
"idempotency_key": self.idempotency_key(content),
|
||||
"timestamp_init": datetime.now(timezone.utc).isoformat()
|
||||
},
|
||||
"routing": {
|
||||
"module": module
|
||||
},
|
||||
"context": {
|
||||
"lang": "es",
|
||||
"mode": "strict",
|
||||
"system_instruction": system_instruction,
|
||||
"tags": {
|
||||
"hst": [],
|
||||
"hsu": [],
|
||||
"emp": [self.emp_h_maestro],
|
||||
"pjt": tags_pjt or []
|
||||
},
|
||||
"ambiente": {
|
||||
"timezone": "Europe/Madrid",
|
||||
"locale": "es-ES",
|
||||
"currency": "EUR",
|
||||
"session_type": "batch"
|
||||
}
|
||||
},
|
||||
"payload": {
|
||||
"type": content_type,
|
||||
"encoding": "utf-8" if content_type == "text" else "url",
|
||||
"content": content
|
||||
},
|
||||
"deployment": {
|
||||
"mode": "SEMI",
|
||||
"tier_preference": ["EXTERNAL", "SELF_HOSTED"]
|
||||
}
|
||||
}
|
||||
|
||||
def classify(self, text: str) -> dict:
|
||||
request = self.build_request(
|
||||
module="CLASSIFIER",
|
||||
content=text,
|
||||
system_instruction="Clasifica el documento: FACTURA, CONTRATO, EMAIL, OTRO"
|
||||
)
|
||||
response = requests.post(f"{self.grace_url}/process", json=request)
|
||||
return response.json()
|
||||
|
||||
def extract_fields(self, document_url: str, fields: list) -> dict:
|
||||
request = self.build_request(
|
||||
module="FIELD_EXTRACTOR",
|
||||
content=document_url,
|
||||
content_type="document",
|
||||
system_instruction=f"Extrae estos campos: {', '.join(fields)}"
|
||||
)
|
||||
response = requests.post(f"{self.factory_url}/process", json=request)
|
||||
return response.json()
|
||||
|
||||
|
||||
# Uso
|
||||
client = CorpClient(
|
||||
grace_url="https://grace.api.example",
|
||||
factory_url="https://factory.api.example"
|
||||
)
|
||||
|
||||
# Clasificar un texto
|
||||
result = client.classify("Factura de Movistar por 45.99 EUR")
|
||||
print(result["result"]["data"]["category"])
|
||||
|
||||
# Extraer campos de un PDF
|
||||
result = client.extract_fields(
|
||||
"https://storage.corp/factura.pdf",
|
||||
["proveedor", "fecha", "importe", "iva"]
|
||||
)
|
||||
print(result["result"]["data"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resumen
|
||||
|
||||
1. **S-CONTRACT** es tu idioma para hablar con GRACE y THE FACTORY
|
||||
2. **HST** te da etiquetas para organizar todo
|
||||
3. **h_maestro** identifica cada etiqueta (determinista)
|
||||
4. **Tu libro MST+BCK** registra tus operaciones
|
||||
5. **Tu almacenamiento es bandeja de entrada**, no permanente
|
||||
6. **Habla con DECK** para alinear codigo compartido
|
||||
|
||||
---
|
||||
|
||||
*Ecosistema TZZR - "Alfred Decide, GRACE Transforma"*
|
||||
668
v4-archive/contratos-comunes/docs/MASON_PROTOCOL_v1.0.md
Normal file
668
v4-archive/contratos-comunes/docs/MASON_PROTOCOL_v1.0.md
Normal file
@@ -0,0 +1,668 @@
|
||||
# MASON Protocol v1.0
|
||||
**Version:** 1.0
|
||||
**Dependencia:** `S-CONTRACT.md`, `NOTARIO.md`
|
||||
**Estado:** Implementación
|
||||
|
||||
---
|
||||
|
||||
# 1. Introducción
|
||||
|
||||
MASON es el **constructor de documentos** del ecosistema GRACE. Prepara, valida, ensambla y transforma datos antes de enviarlos a THE FACTORY para generación o a NOTARIO para certificación.
|
||||
|
||||
```
|
||||
+---------------------------------------------------------------------+
|
||||
| PRINCIPIO MASON |
|
||||
| |
|
||||
| "MASON prepara, FACTORY genera, NOTARIO certifica" |
|
||||
+---------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 2. Arquitectura
|
||||
|
||||
```
|
||||
+---------------------------------------------------------------------+
|
||||
| MASON |
|
||||
| (Constructor de Documentos) |
|
||||
+---------------------------------------------------------------------+
|
||||
| |
|
||||
| Datos Entrada |
|
||||
| | |
|
||||
| v |
|
||||
| +-----------------+ |
|
||||
| | VALIDATOR | Valida estructura y campos requeridos |
|
||||
| +-----------------+ |
|
||||
| | |
|
||||
| v |
|
||||
| +-----------------+ |
|
||||
| | ENRICHER | Añade datos calculados y referencias |
|
||||
| +-----------------+ |
|
||||
| | |
|
||||
| v |
|
||||
| +-----------------+ |
|
||||
| | ASSEMBLER | Ensambla componentes según template |
|
||||
| +-----------------+ |
|
||||
| | |
|
||||
| v |
|
||||
| +-----------------+ |
|
||||
| | FORMATTER | Formatea para destino (FACTORY, NOTARIO) |
|
||||
| +-----------------+ |
|
||||
| | |
|
||||
| v |
|
||||
| Documento Preparado |
|
||||
| |
|
||||
+---------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 3. Componentes
|
||||
|
||||
## 3.1 VALIDATOR
|
||||
|
||||
Valida datos de entrada contra esquemas definidos.
|
||||
|
||||
```javascript
|
||||
class Validator {
|
||||
validate(data, schema) {
|
||||
const errors = [];
|
||||
|
||||
// Campos requeridos
|
||||
for (const field of schema.required || []) {
|
||||
if (!data[field]) {
|
||||
errors.push({ field, error: 'required' });
|
||||
}
|
||||
}
|
||||
|
||||
// Tipos de datos
|
||||
for (const [field, type] of Object.entries(schema.types || {})) {
|
||||
if (data[field] && typeof data[field] !== type) {
|
||||
errors.push({ field, error: 'invalid_type', expected: type });
|
||||
}
|
||||
}
|
||||
|
||||
// Reglas personalizadas
|
||||
for (const rule of schema.rules || []) {
|
||||
const result = rule.check(data);
|
||||
if (!result.valid) {
|
||||
errors.push({ field: rule.field, error: result.error });
|
||||
}
|
||||
}
|
||||
|
||||
return { valid: errors.length === 0, errors };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3.2 ENRICHER
|
||||
|
||||
Añade datos calculados y referencias externas.
|
||||
|
||||
```javascript
|
||||
class Enricher {
|
||||
async enrich(data, context) {
|
||||
const enriched = { ...data };
|
||||
|
||||
// Timestamps
|
||||
enriched.created_at = new Date().toISOString();
|
||||
enriched.mason_version = '1.0';
|
||||
|
||||
// Cálculos automáticos
|
||||
if (enriched.lineas) {
|
||||
enriched.subtotal = this.calculateSubtotal(enriched.lineas);
|
||||
enriched.iva = enriched.subtotal * 0.21;
|
||||
enriched.total = enriched.subtotal + enriched.iva;
|
||||
}
|
||||
|
||||
// Referencias externas
|
||||
if (enriched.cliente_id) {
|
||||
enriched.cliente = await this.fetchCliente(enriched.cliente_id);
|
||||
}
|
||||
|
||||
// Numeración automática
|
||||
if (!enriched.numero) {
|
||||
enriched.numero = await this.generateNumero(enriched.tipo);
|
||||
}
|
||||
|
||||
return enriched;
|
||||
}
|
||||
|
||||
calculateSubtotal(lineas) {
|
||||
return lineas.reduce((sum, l) => sum + (l.cantidad * l.precio), 0);
|
||||
}
|
||||
|
||||
async generateNumero(tipo) {
|
||||
const prefix = {
|
||||
factura: 'FAC',
|
||||
pedido: 'PED',
|
||||
presupuesto: 'PRE',
|
||||
albaran: 'ALB',
|
||||
}[tipo] || 'DOC';
|
||||
|
||||
const year = new Date().getFullYear();
|
||||
const seq = await this.getNextSequence(tipo);
|
||||
|
||||
return `${prefix}-${year}-${String(seq).padStart(4, '0')}`;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3.3 ASSEMBLER
|
||||
|
||||
Ensambla componentes según template.
|
||||
|
||||
```javascript
|
||||
class Assembler {
|
||||
constructor() {
|
||||
this.templates = new Map();
|
||||
}
|
||||
|
||||
registerTemplate(type, template) {
|
||||
this.templates.set(type, template);
|
||||
}
|
||||
|
||||
assemble(type, data) {
|
||||
const template = this.templates.get(type);
|
||||
if (!template) {
|
||||
throw new Error(`Template not found: ${type}`);
|
||||
}
|
||||
|
||||
return {
|
||||
type,
|
||||
template: template.name,
|
||||
version: template.version,
|
||||
sections: this.buildSections(template, data),
|
||||
metadata: {
|
||||
assembled_at: new Date().toISOString(),
|
||||
assembler: 'MASON',
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
buildSections(template, data) {
|
||||
return template.sections.map(section => ({
|
||||
id: section.id,
|
||||
type: section.type,
|
||||
content: this.renderSection(section, data),
|
||||
}));
|
||||
}
|
||||
|
||||
renderSection(section, data) {
|
||||
// Interpolar variables en contenido
|
||||
let content = section.content;
|
||||
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
content = content.replace(new RegExp(`{{${key}}}`, 'g'), value);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3.4 FORMATTER
|
||||
|
||||
Formatea para destino específico.
|
||||
|
||||
```javascript
|
||||
class Formatter {
|
||||
formatForFactory(assembled) {
|
||||
return {
|
||||
seed: this.buildPrompt(assembled),
|
||||
objective: `Documento ${assembled.type} profesional`,
|
||||
function: 'DOCUMENT_GENERATION',
|
||||
output_format: 'pdf',
|
||||
context: {
|
||||
template: assembled.template,
|
||||
sections: assembled.sections,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
formatForNotario(assembled, options = {}) {
|
||||
return {
|
||||
document: assembled,
|
||||
certification_type: options.certification_type || 'standard',
|
||||
requires_blockchain: options.blockchain !== false,
|
||||
metadata: {
|
||||
formatter: 'MASON',
|
||||
formatted_at: new Date().toISOString(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
buildPrompt(assembled) {
|
||||
const lines = [
|
||||
`Genera un documento ${assembled.type} profesional.`,
|
||||
'',
|
||||
'Secciones:',
|
||||
];
|
||||
|
||||
for (const section of assembled.sections) {
|
||||
lines.push(`- ${section.id}: ${section.content.substring(0, 100)}...`);
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 4. Templates de Documentos
|
||||
|
||||
## 4.1 Factura
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "factura_v1",
|
||||
"version": "1.0",
|
||||
"type": "factura",
|
||||
"required_fields": [
|
||||
"cliente", "lineas", "fecha"
|
||||
],
|
||||
"sections": [
|
||||
{
|
||||
"id": "header",
|
||||
"type": "header",
|
||||
"content": "FACTURA {{numero}}"
|
||||
},
|
||||
{
|
||||
"id": "emisor",
|
||||
"type": "info_block",
|
||||
"content": "{{empresa_nombre}}\n{{empresa_direccion}}\nCIF: {{empresa_cif}}"
|
||||
},
|
||||
{
|
||||
"id": "receptor",
|
||||
"type": "info_block",
|
||||
"content": "{{cliente_nombre}}\n{{cliente_direccion}}\nCIF: {{cliente_cif}}"
|
||||
},
|
||||
{
|
||||
"id": "detalles",
|
||||
"type": "table",
|
||||
"content": "{{lineas_tabla}}"
|
||||
},
|
||||
{
|
||||
"id": "totales",
|
||||
"type": "totals",
|
||||
"content": "Subtotal: {{subtotal}}€\nIVA (21%): {{iva}}€\nTOTAL: {{total}}€"
|
||||
},
|
||||
{
|
||||
"id": "footer",
|
||||
"type": "footer",
|
||||
"content": "Forma de pago: {{forma_pago}}\nVencimiento: {{fecha_vencimiento}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 4.2 Pedido
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "pedido_v1",
|
||||
"version": "1.0",
|
||||
"type": "pedido",
|
||||
"required_fields": [
|
||||
"proveedor", "productos", "fecha"
|
||||
],
|
||||
"sections": [
|
||||
{
|
||||
"id": "header",
|
||||
"type": "header",
|
||||
"content": "PEDIDO {{numero}}"
|
||||
},
|
||||
{
|
||||
"id": "proveedor",
|
||||
"type": "info_block",
|
||||
"content": "Proveedor: {{proveedor_nombre}}\nContacto: {{proveedor_contacto}}"
|
||||
},
|
||||
{
|
||||
"id": "productos",
|
||||
"type": "table",
|
||||
"content": "{{productos_tabla}}"
|
||||
},
|
||||
{
|
||||
"id": "condiciones",
|
||||
"type": "text",
|
||||
"content": "Plazo de entrega: {{plazo_entrega}}\nCondiciones: {{condiciones}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 5. Flujo Completo
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────────┐
|
||||
│ FLUJO MASON → FACTORY → NOTARIO │
|
||||
└────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
1. CLARA recibe petición de documento
|
||||
│
|
||||
▼
|
||||
2. MASON.validate(datos, schema)
|
||||
│ → Si inválido: retorna errores
|
||||
▼
|
||||
3. MASON.enrich(datos, context)
|
||||
│ → Añade cálculos, referencias, numeración
|
||||
▼
|
||||
4. MASON.assemble(tipo, datos_enriquecidos)
|
||||
│ → Construye estructura según template
|
||||
▼
|
||||
5. MASON.formatForFactory(assembled)
|
||||
│
|
||||
▼
|
||||
6. THE FACTORY genera documento (iterativo)
|
||||
│ → Director → Executor → Evaluator → converge
|
||||
▼
|
||||
7. MASON.formatForNotario(documento)
|
||||
│
|
||||
▼
|
||||
8. NOTARIO certifica
|
||||
│ → Hash + Timestamp + Merkle + Blockchain
|
||||
▼
|
||||
9. LOCKER almacena
|
||||
│ → locker://corp/facturas/FAC-2025-0001.pdf
|
||||
▼
|
||||
10. Retorna referencia certificada
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 6. API
|
||||
|
||||
## 6.1 Mason.prepare()
|
||||
|
||||
```javascript
|
||||
const mason = new Mason();
|
||||
|
||||
const result = await mason.prepare({
|
||||
tipo: 'factura',
|
||||
data: {
|
||||
cliente_id: 'CLI-001',
|
||||
lineas: [
|
||||
{ concepto: 'Traje azul marino', cantidad: 1, precio: 349 },
|
||||
{ concepto: 'Ajustes', cantidad: 1, precio: 50 }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
auto_enrich: true,
|
||||
validate: true,
|
||||
target: 'FACTORY'
|
||||
}
|
||||
});
|
||||
|
||||
// Result:
|
||||
{
|
||||
"success": true,
|
||||
"document": {
|
||||
"numero": "FAC-2025-0001",
|
||||
"cliente": { "nombre": "Juan García", "cif": "12345678A" },
|
||||
"lineas": [...],
|
||||
"subtotal": 399,
|
||||
"iva": 83.79,
|
||||
"total": 482.79
|
||||
},
|
||||
"formatted": {
|
||||
"seed": "Genera un documento factura profesional...",
|
||||
"objective": "...",
|
||||
"function": "DOCUMENT_GENERATION"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 6.2 Mason.build()
|
||||
|
||||
```javascript
|
||||
const document = await mason.build('factura', preparedData);
|
||||
|
||||
// Genera directamente sin pasar por FACTORY
|
||||
// Útil para documentos simples o regeneración
|
||||
```
|
||||
|
||||
## 6.3 Mason.validate()
|
||||
|
||||
```javascript
|
||||
const validation = mason.validate(data, 'factura');
|
||||
|
||||
if (!validation.valid) {
|
||||
console.log('Errores:', validation.errors);
|
||||
// [{ field: 'cliente', error: 'required' }]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 7. Integración con S-CONTRACT
|
||||
|
||||
## 7.1 Request a MASON
|
||||
|
||||
```json
|
||||
{
|
||||
"contract_version": "2.1",
|
||||
"request_id": "msn-abc123",
|
||||
"source": {
|
||||
"system": "CORP",
|
||||
"orchestrator": "CLARA"
|
||||
},
|
||||
"target": {
|
||||
"service": "MASON",
|
||||
"operation": "prepare"
|
||||
},
|
||||
"input": {
|
||||
"tipo": "factura",
|
||||
"data": { ... },
|
||||
"options": {
|
||||
"auto_enrich": true,
|
||||
"target": "FACTORY"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 7.2 Response de MASON
|
||||
|
||||
```json
|
||||
{
|
||||
"contract_version": "2.1",
|
||||
"request_id": "msn-abc123",
|
||||
"status": {
|
||||
"code": "SUCCESS",
|
||||
"message": "Document prepared successfully"
|
||||
},
|
||||
"output": {
|
||||
"document": { ... },
|
||||
"formatted": { ... },
|
||||
"validation": {
|
||||
"valid": true,
|
||||
"errors": []
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"mason_version": "1.0",
|
||||
"template_used": "factura_v1",
|
||||
"enrichments_applied": ["calculate_totals", "generate_numero", "fetch_cliente"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 8. Configuración
|
||||
|
||||
```yaml
|
||||
mason:
|
||||
enabled: true
|
||||
|
||||
# Validación
|
||||
strict_validation: true
|
||||
fail_on_warning: false
|
||||
|
||||
# Enriquecimiento
|
||||
auto_enrich: true
|
||||
fetch_external_refs: true
|
||||
|
||||
# Numeración
|
||||
sequence_prefix: "TZZR"
|
||||
sequence_padding: 4
|
||||
reset_yearly: true
|
||||
|
||||
# Templates
|
||||
templates_dir: "./templates"
|
||||
custom_templates_enabled: true
|
||||
|
||||
# Destinos
|
||||
default_target: "FACTORY"
|
||||
|
||||
# Cache
|
||||
cache_enrichments: true
|
||||
cache_ttl_seconds: 300
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 9. Schemas de Validación
|
||||
|
||||
## 9.1 Factura
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Factura Schema",
|
||||
"type": "object",
|
||||
"required": ["cliente", "lineas", "fecha"],
|
||||
"properties": {
|
||||
"cliente": {
|
||||
"type": "object",
|
||||
"required": ["nombre"],
|
||||
"properties": {
|
||||
"nombre": { "type": "string", "minLength": 1 },
|
||||
"cif": { "type": "string", "pattern": "^[A-Z0-9]{9}$" },
|
||||
"direccion": { "type": "string" },
|
||||
"email": { "type": "string", "format": "email" }
|
||||
}
|
||||
},
|
||||
"lineas": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["concepto", "cantidad", "precio"],
|
||||
"properties": {
|
||||
"concepto": { "type": "string" },
|
||||
"cantidad": { "type": "number", "minimum": 0 },
|
||||
"precio": { "type": "number", "minimum": 0 }
|
||||
}
|
||||
}
|
||||
},
|
||||
"fecha": { "type": "string", "format": "date" },
|
||||
"forma_pago": {
|
||||
"type": "string",
|
||||
"enum": ["transferencia", "tarjeta", "efectivo", "domiciliacion"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 10. Implementación Completa
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* MASON - Constructor de Documentos
|
||||
*/
|
||||
class Mason {
|
||||
constructor(config = {}) {
|
||||
this.version = '1.0';
|
||||
this.validator = new Validator();
|
||||
this.enricher = new Enricher(config);
|
||||
this.assembler = new Assembler();
|
||||
this.formatter = new Formatter();
|
||||
|
||||
// Cargar templates por defecto
|
||||
this.loadDefaultTemplates();
|
||||
}
|
||||
|
||||
loadDefaultTemplates() {
|
||||
this.assembler.registerTemplate('factura', FACTURA_TEMPLATE);
|
||||
this.assembler.registerTemplate('pedido', PEDIDO_TEMPLATE);
|
||||
this.assembler.registerTemplate('presupuesto', PRESUPUESTO_TEMPLATE);
|
||||
this.assembler.registerTemplate('albaran', ALBARAN_TEMPLATE);
|
||||
}
|
||||
|
||||
async prepare(request) {
|
||||
const { tipo, data, options = {} } = request;
|
||||
|
||||
// 1. Validar
|
||||
if (options.validate !== false) {
|
||||
const validation = this.validator.validate(data, this.getSchema(tipo));
|
||||
if (!validation.valid) {
|
||||
return { success: false, errors: validation.errors };
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Enriquecer
|
||||
let enriched = data;
|
||||
if (options.auto_enrich !== false) {
|
||||
enriched = await this.enricher.enrich(data, { tipo });
|
||||
}
|
||||
|
||||
// 3. Ensamblar
|
||||
const assembled = this.assembler.assemble(tipo, enriched);
|
||||
|
||||
// 4. Formatear para destino
|
||||
let formatted;
|
||||
switch (options.target) {
|
||||
case 'FACTORY':
|
||||
formatted = this.formatter.formatForFactory(assembled);
|
||||
break;
|
||||
case 'NOTARIO':
|
||||
formatted = this.formatter.formatForNotario(assembled, options);
|
||||
break;
|
||||
default:
|
||||
formatted = assembled;
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
document: enriched,
|
||||
assembled,
|
||||
formatted,
|
||||
validation: { valid: true, errors: [] }
|
||||
};
|
||||
}
|
||||
|
||||
getSchema(tipo) {
|
||||
return SCHEMAS[tipo] || {};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Mason, Validator, Enricher, Assembler, Formatter };
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 11. Checklist de Implementación
|
||||
|
||||
- [x] Definir arquitectura de componentes
|
||||
- [x] Implementar Validator
|
||||
- [x] Implementar Enricher
|
||||
- [x] Implementar Assembler
|
||||
- [x] Implementar Formatter
|
||||
- [x] Crear templates de documentos
|
||||
- [x] Definir schemas de validación
|
||||
- [x] Integrar con S-CONTRACT
|
||||
- [ ] Tests unitarios
|
||||
- [ ] Tests de integración con FACTORY
|
||||
- [ ] Tests de integración con NOTARIO
|
||||
|
||||
---
|
||||
|
||||
**Fin del Documento MASON Protocol - Version 1.0**
|
||||
|
||||
*Sistema GRACE - "MASON prepara, FACTORY genera, NOTARIO certifica"*
|
||||
298
v4-archive/contratos-comunes/docs/MODULOS_IA.md
Normal file
298
v4-archive/contratos-comunes/docs/MODULOS_IA.md
Normal file
@@ -0,0 +1,298 @@
|
||||
# CAPA COGNITIVA - GRACE (Sistema de Modulos IA)
|
||||
**Version:** 2.0
|
||||
**Estado:** Enterprise Standard
|
||||
**Filosofia Base:** Microservicios Cognitivos - Contrato Comun - Determinismo y Observabilidad
|
||||
|
||||
---
|
||||
|
||||
# 1. Introduccion a GRACE
|
||||
|
||||
GRACE no es un chatbot.
|
||||
GRACE es un **conjunto de 18 microservicios cognitivos desacoplados**, especializados en tareas de:
|
||||
|
||||
- Vision
|
||||
- Voz
|
||||
- Biometria
|
||||
- Semantica
|
||||
- Extraccion de datos
|
||||
- Normalizacion
|
||||
- Clasificacion
|
||||
|
||||
GRACE representa la **capa de cognicion** del ecosistema.
|
||||
No toma decisiones.
|
||||
No altera estados.
|
||||
No escribe en la Base de Datos.
|
||||
|
||||
**"GRACE transforma, Alfred decide."**
|
||||
|
||||
---
|
||||
|
||||
# 2. Integracion con S-CONTRACT
|
||||
|
||||
Toda llamada a GRACE debe seguir estrictamente el S-CONTRACT v2.0.
|
||||
|
||||
## 2.1 Request (Perfil LITE)
|
||||
|
||||
```json
|
||||
{
|
||||
"contract_version": "2.0",
|
||||
"profile": "LITE",
|
||||
"envelope": {
|
||||
"trace_id": "uuid-v4-global",
|
||||
"idempotency_key": "sha256-del-input"
|
||||
},
|
||||
"routing": {
|
||||
"module": "CLASSIFIER"
|
||||
},
|
||||
"context": {
|
||||
"lang": "es",
|
||||
"mode": "strict"
|
||||
},
|
||||
"payload": {
|
||||
"type": "text",
|
||||
"encoding": "utf-8",
|
||||
"content": "Texto a procesar"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2.2 Response
|
||||
|
||||
```json
|
||||
{
|
||||
"contract_version": "2.0",
|
||||
"profile": "LITE",
|
||||
"envelope": {
|
||||
"trace_id": "uuid-v4-global",
|
||||
"idempotency_key": "sha256-del-input",
|
||||
"timestamp_end": "2025-12-18T10:30:00.450Z"
|
||||
},
|
||||
"status": {
|
||||
"code": "SUCCESS",
|
||||
"fallback_level_used": 0,
|
||||
"provider_used": "groq"
|
||||
},
|
||||
"result": {
|
||||
"schema": "classifier_output_v1",
|
||||
"data": {
|
||||
"category": "FINANZAS",
|
||||
"confidence": 0.98
|
||||
}
|
||||
},
|
||||
"quality": {
|
||||
"confidence": 0.98,
|
||||
"coverage": 1.0,
|
||||
"tokens_input": 150,
|
||||
"tokens_output": 45
|
||||
},
|
||||
"metadata": {
|
||||
"model_id": "llama-3-70b-instruct",
|
||||
"processing_ms": 340
|
||||
},
|
||||
"errors": [],
|
||||
"warnings": []
|
||||
}
|
||||
```
|
||||
|
||||
### Status codes
|
||||
|
||||
| Codigo | Significado |
|
||||
|--------|-------------|
|
||||
| `SUCCESS` | Ejecucion completa y valida |
|
||||
| `PARTIAL` | Resultado incompleto pero usable |
|
||||
| `ERROR` | Fallo no recuperable |
|
||||
| `TIMEOUT` | Excedio TTL |
|
||||
| `FALLBACK` | Exito usando modulo alternativo |
|
||||
|
||||
---
|
||||
|
||||
# 3. Catalogo de Modulos (Los 18 Microservicios)
|
||||
|
||||
GRACE se divide en cinco familias.
|
||||
|
||||
---
|
||||
|
||||
## FAMILIA A - VISION (Procesado Documental)
|
||||
|
||||
### **1. IMG_PREPROCESS**
|
||||
Normalizacion de entrada.
|
||||
Operaciones:
|
||||
- Crop inteligente
|
||||
- Denoise
|
||||
- Upscale 2x
|
||||
- Grayscale
|
||||
|
||||
### **2. PDF_SCANNER**
|
||||
Limpieza avanzada para documentos escaneados.
|
||||
Operaciones:
|
||||
- Deskew
|
||||
- Binarizacion adaptativa
|
||||
- Eliminacion bordes negros
|
||||
|
||||
### **3. OCR_CORE**
|
||||
Extraccion de texto.
|
||||
Incluye:
|
||||
- Layout analysis
|
||||
- HOCR
|
||||
- Texto plano
|
||||
|
||||
---
|
||||
|
||||
## FAMILIA B - VOZ (Reuniones)
|
||||
|
||||
### **4. ASR_ENGINE**
|
||||
Reconocimiento del habla.
|
||||
- Modelo: Whisper Large v3 / Faster Whisper
|
||||
- Diarizacion A/B
|
||||
- Timestamps por frase
|
||||
|
||||
### **5. TTS_ENGINE**
|
||||
Sintesis de voz neutral para notificaciones internas.
|
||||
|
||||
---
|
||||
|
||||
## FAMILIA C - IDENTIDAD (Biometria)
|
||||
|
||||
### **6. FACE_VECTOR**
|
||||
Vector biometrico facial (Float32 L2).
|
||||
No guarda fotos, solo matematicas.
|
||||
|
||||
### **7. ID_CONSOLIDATION**
|
||||
Fusion de identidades de un mismo Player.
|
||||
Algoritmo: **Mediana geometrica** para eliminar outliers.
|
||||
|
||||
### **8. AVATAR_GEN**
|
||||
Generacion de avatar neutral 512x512 a partir del vector consolidado.
|
||||
|
||||
---
|
||||
|
||||
## FAMILIA D - SEMANTICA (NLP)
|
||||
|
||||
### **9. EMBEDDINGS**
|
||||
Vectorizacion semantica para busquedas.
|
||||
|
||||
### **10. SUMMARIZER**
|
||||
Resumen estructurado:
|
||||
```json
|
||||
{
|
||||
"objetivos": [],
|
||||
"acuerdos": [],
|
||||
"riesgos": []
|
||||
}
|
||||
```
|
||||
|
||||
### **11. TASK_EXTRACTOR**
|
||||
Mineria de acciones, responsabilidades y fechas.
|
||||
|
||||
### **12. CLASSIFIER**
|
||||
Asigna SET_HST basado en contenido textual.
|
||||
|
||||
### **13. SIMILARITY**
|
||||
Comparador vectorial (Cosine Similarity).
|
||||
|
||||
---
|
||||
|
||||
## FAMILIA E - UTILIDADES
|
||||
|
||||
### **14. FIELD_EXTRACTOR**
|
||||
Lectura estructurada mediante regex + IA.
|
||||
Ej.: CIF, fechas, importes.
|
||||
|
||||
### **15. HASHER**
|
||||
Generador oficial de SHA256 y UUID v4.
|
||||
|
||||
### **16. INPUT_NORMALIZER**
|
||||
Traduccion de formatos y enumeraciones.
|
||||
|
||||
### **17. OUTPUT_ADAPTER**
|
||||
Adaptacion a formatos legacy.
|
||||
|
||||
### **18. LANG_DETECT**
|
||||
Identificacion ISO 639-1.
|
||||
|
||||
---
|
||||
|
||||
# 4. Cadenas de Fallback (Resiliencia Operativa)
|
||||
|
||||
GRACE nunca falla silenciosamente.
|
||||
Cada modulo define una cadena de degradacion via `fallback_chain`.
|
||||
|
||||
## Ejemplo OCR
|
||||
|
||||
```json
|
||||
"routing": {
|
||||
"module": "OCR_CORE",
|
||||
"fallback_chain": ["OCR_LOCAL", "OCR_GROQ", "OCR_OPENAI"]
|
||||
}
|
||||
```
|
||||
|
||||
## Ejemplo ASR
|
||||
|
||||
```json
|
||||
"routing": {
|
||||
"module": "ASR_ENGINE",
|
||||
"fallback_chain": ["ASR_WHISPER_LOCAL", "ASR_FASTER_WHISPER", "ASR_GROQ"]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 5. Filosofia Operativa de GRACE
|
||||
|
||||
### Stateless
|
||||
GRACE nunca guarda estado.
|
||||
|
||||
### Determinista
|
||||
La misma entrada -> siempre la misma salida.
|
||||
|
||||
### Intercambiable
|
||||
Se puede sustituir un modelo por otro sin romper el sistema.
|
||||
|
||||
### Trazable
|
||||
Toda ejecucion queda registrada via trace_id.
|
||||
|
||||
### No persiste datos sensibles
|
||||
Los archivos viven solo en almacenamiento gestionado.
|
||||
|
||||
---
|
||||
|
||||
# 6. Relacion GRACE <-> Alfred <-> SFE
|
||||
|
||||
### GRACE transforma
|
||||
OCR, ASR, vectores, embeddings.
|
||||
|
||||
### Alfred decide
|
||||
Valida, encamina, escribe en SFE.
|
||||
|
||||
### SFE registra
|
||||
El estado final y su evidencia.
|
||||
|
||||
```
|
||||
Entrada (URL)
|
||||
|
|
||||
GRACE (microservicio)
|
||||
|
|
||||
Transformacion estructurada
|
||||
|
|
||||
Alfred (validacion)
|
||||
|
|
||||
SFE (narrativa oficial)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 7. M-CONTRACTs
|
||||
|
||||
Cada modulo debe definir su M-CONTRACT extendiendo S-CONTRACT.
|
||||
|
||||
Ver carpeta `/m-contracts/` para definiciones formales de:
|
||||
- CLASSIFIER.json
|
||||
- OCR_CORE.json
|
||||
- ASR_ENGINE.json
|
||||
- (18 modulos total)
|
||||
|
||||
---
|
||||
|
||||
**Fin del Documento MODULOS_IA - Version 2.0**
|
||||
|
||||
*Sistema GRACE - "GRACE transforma, Alfred decide"*
|
||||
261
v4-archive/contratos-comunes/docs/NOTARIO.md
Normal file
261
v4-archive/contratos-comunes/docs/NOTARIO.md
Normal file
@@ -0,0 +1,261 @@
|
||||
# NOTARIO - Sistema de Sellado Blockchain
|
||||
**Version:** 2.0
|
||||
**Dependencia:** `S-CONTRACT.md`
|
||||
**Estado:** Especificacion
|
||||
|
||||
---
|
||||
|
||||
# 1. Introduccion
|
||||
|
||||
NOTARIO es el modulo responsable del **sellado inmutable** de registros criticos en blockchain. Opera como la ultima capa de confianza del ecosistema GRACE.
|
||||
|
||||
```
|
||||
+---------------------------------------------------------------------+
|
||||
| PRINCIPIO NOTARIO |
|
||||
| |
|
||||
| "Lo que NOTARIO sella, nadie lo altera" |
|
||||
+---------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 2. Arquitectura
|
||||
|
||||
```
|
||||
+---------------------------------------------------------------------+
|
||||
| NOTARIO |
|
||||
+---------------------------------------------------------------------+
|
||||
| |
|
||||
| SYS_LOG (Libro Diario) |
|
||||
| | |
|
||||
| | (procesos completados + auditados) |
|
||||
| v |
|
||||
| +-----------------+ |
|
||||
| | BATCH COLLECTOR | Agrupa registros por ventana temporal |
|
||||
| +-----------------+ |
|
||||
| | |
|
||||
| v |
|
||||
| +-----------------+ |
|
||||
| | MERKLE BUILDER | Construye arbol Merkle del batch |
|
||||
| +-----------------+ |
|
||||
| | |
|
||||
| v |
|
||||
| +-----------------+ |
|
||||
| | BLOCKCHAIN TX | Publica hash raiz en blockchain |
|
||||
| +-----------------+ |
|
||||
| | |
|
||||
| v |
|
||||
| SYS_LOG (UPDATE blockchain_tx_ref) |
|
||||
| |
|
||||
+---------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 3. Dos Franjas Temporales
|
||||
|
||||
## 3.1 Franja Interna
|
||||
|
||||
Tiempo del sistema para:
|
||||
- Procesar operaciones
|
||||
- Ejecutar auditoria SENTINEL
|
||||
- Preparar datos para consolidacion
|
||||
|
||||
**Duracion tipica**: Minutos a horas
|
||||
|
||||
## 3.2 Franja Blockchain
|
||||
|
||||
Tiempo de NOTARIO para:
|
||||
- Agrupar registros en batches
|
||||
- Construir pruebas criptograficas
|
||||
- Publicar en blockchain
|
||||
- Confirmar transacciones
|
||||
|
||||
**Duracion tipica**: Horas a dias (segun volumen y costos)
|
||||
|
||||
---
|
||||
|
||||
# 4. Ciclo de Sellado
|
||||
|
||||
```
|
||||
1. RECOLECTAR
|
||||
- Query SYS_LOG WHERE audit_status = 'DEEP_PASS'
|
||||
- AND blockchain_pending = FALSE
|
||||
- AND blockchain_tx_ref IS NULL
|
||||
|
||||
2. AGRUPAR
|
||||
- Crear batch con ventana temporal (ej: 24h)
|
||||
- Asignar notario_batch_id
|
||||
|
||||
3. CONSTRUIR MERKLE
|
||||
- Ordenar registros por trace_id
|
||||
- Calcular hash de cada registro
|
||||
- Construir arbol binario
|
||||
- Obtener merkle_root
|
||||
|
||||
4. FIRMAR
|
||||
- Firmar merkle_root con llave de NOTARIO
|
||||
- Generar timestamp certificado
|
||||
|
||||
5. PUBLICAR
|
||||
- Enviar transaccion a blockchain
|
||||
- Esperar confirmaciones
|
||||
|
||||
6. ACTUALIZAR
|
||||
- UPDATE SYS_LOG SET blockchain_tx_ref = tx_hash
|
||||
- INSERT NOTARIO_BATCHES con detalles
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 5. Tabla NOTARIO_BATCHES
|
||||
|
||||
```sql
|
||||
CREATE TABLE NOTARIO_BATCHES (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
batch_id UUID UNIQUE NOT NULL,
|
||||
|
||||
-- Ventana temporal
|
||||
window_start TIMESTAMPTZ NOT NULL,
|
||||
window_end TIMESTAMPTZ NOT NULL,
|
||||
|
||||
-- Contenido
|
||||
records_count INTEGER NOT NULL,
|
||||
trace_ids UUID[] NOT NULL,
|
||||
|
||||
-- Merkle
|
||||
merkle_root CHAR(64) NOT NULL,
|
||||
merkle_tree JSONB,
|
||||
|
||||
-- Firma
|
||||
signature TEXT NOT NULL,
|
||||
signing_key_id VARCHAR(100),
|
||||
signed_at TIMESTAMPTZ NOT NULL,
|
||||
|
||||
-- Blockchain
|
||||
blockchain_network VARCHAR(50) DEFAULT 'ethereum',
|
||||
blockchain_tx_ref VARCHAR(100),
|
||||
blockchain_block BIGINT,
|
||||
blockchain_timestamp TIMESTAMPTZ,
|
||||
confirmations INTEGER DEFAULT 0,
|
||||
|
||||
-- Estado
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
|
||||
-- Metadata
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT valid_status CHECK (
|
||||
status IN ('PENDING', 'SUBMITTED', 'CONFIRMED', 'FAILED')
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_notario_status ON NOTARIO_BATCHES(status);
|
||||
CREATE INDEX idx_notario_window ON NOTARIO_BATCHES(window_start, window_end);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 6. Verificacion de Integridad
|
||||
|
||||
Para verificar que un registro no ha sido alterado:
|
||||
|
||||
```python
|
||||
def verify_record_integrity(trace_id, notario_batch_id):
|
||||
"""
|
||||
Verifica que un registro esta incluido en un batch sellado.
|
||||
"""
|
||||
# 1. Obtener batch
|
||||
batch = get_batch(notario_batch_id)
|
||||
|
||||
# 2. Verificar que trace_id esta en el batch
|
||||
assert trace_id in batch.trace_ids
|
||||
|
||||
# 3. Obtener registro
|
||||
record = get_syslog_record(trace_id)
|
||||
|
||||
# 4. Calcular hash del registro
|
||||
record_hash = sha256(serialize(record))
|
||||
|
||||
# 5. Verificar inclusion en merkle tree
|
||||
proof = get_merkle_proof(batch.merkle_tree, trace_id)
|
||||
assert verify_merkle_proof(record_hash, proof, batch.merkle_root)
|
||||
|
||||
# 6. Verificar firma del batch
|
||||
assert verify_signature(batch.merkle_root, batch.signature, batch.signing_key_id)
|
||||
|
||||
# 7. Verificar que merkle_root esta en blockchain
|
||||
tx = get_blockchain_tx(batch.blockchain_tx_ref)
|
||||
assert tx.data == batch.merkle_root
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 7. Integracion con S-CONTRACT
|
||||
|
||||
## 7.1 Campos en Response
|
||||
|
||||
```json
|
||||
"audit": {
|
||||
"blockchain_pending": true,
|
||||
"blockchain_tx_ref": null,
|
||||
"notario_batch_id": "uuid-batch"
|
||||
}
|
||||
```
|
||||
|
||||
## 7.2 Campos post-sellado
|
||||
|
||||
```json
|
||||
"audit": {
|
||||
"blockchain_pending": false,
|
||||
"blockchain_tx_ref": "0x1234...abcd",
|
||||
"notario_batch_id": "uuid-batch"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 8. Configuracion
|
||||
|
||||
```yaml
|
||||
notario:
|
||||
enabled: true
|
||||
|
||||
# Ventana de agregacion
|
||||
batch_window_hours: 24
|
||||
min_records_per_batch: 10
|
||||
max_records_per_batch: 10000
|
||||
|
||||
# Blockchain
|
||||
network: ethereum
|
||||
contract_address: "0x..."
|
||||
gas_limit: 100000
|
||||
|
||||
# Firma
|
||||
signing_key: kv://production/signing/notario
|
||||
|
||||
# Reintentos
|
||||
max_retries: 3
|
||||
retry_delay_minutes: 60
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 9. Checklist de Implementacion
|
||||
|
||||
- [ ] Crear tabla NOTARIO_BATCHES
|
||||
- [ ] Implementar recolector de registros
|
||||
- [ ] Implementar constructor Merkle tree
|
||||
- [ ] Configurar llave de firma
|
||||
- [ ] Integrar con proveedor blockchain
|
||||
- [ ] Implementar verificador de integridad
|
||||
- [ ] Crear workflow de sellado periodico
|
||||
- [ ] Configurar alertas para fallos
|
||||
|
||||
---
|
||||
|
||||
**Fin del Documento NOTARIO - Version 2.0**
|
||||
|
||||
*Sistema GRACE - "Lo que NOTARIO sella, nadie lo altera"*
|
||||
317
v4-archive/contratos-comunes/docs/PENNY.md
Normal file
317
v4-archive/contratos-comunes/docs/PENNY.md
Normal file
@@ -0,0 +1,317 @@
|
||||
# PENNY - Arquitectura de Asistente de Voz
|
||||
**Version:** 1.0
|
||||
**Estado:** Especificacion Tecnica
|
||||
|
||||
---
|
||||
|
||||
# 1. Modos de Operacion
|
||||
|
||||
PENNY soporta dos modos de operacion seleccionables al inicio de sesion:
|
||||
|
||||
| Modo | Latencia | Costo | Privacidad |
|
||||
|------|----------|-------|------------|
|
||||
| `SELF_HOSTED` | 2-4s | ~$0.01/min | Total |
|
||||
| `EXTERNAL` | ~300ms | ~$0.08/min | APIs externas |
|
||||
|
||||
---
|
||||
|
||||
# 2. Modo SELF_HOSTED (Modelos Locales)
|
||||
|
||||
Pipeline secuencial con modelos autoalojados en RunPod:
|
||||
|
||||
```
|
||||
Audio entrada
|
||||
|
|
||||
v
|
||||
+------------------+
|
||||
| Silero VAD | Detecta actividad de voz
|
||||
+------------------+
|
||||
|
|
||||
v
|
||||
+------------------+
|
||||
| Faster Whisper | ASR: Voz a texto (~500-1500ms)
|
||||
| Large V3 |
|
||||
+------------------+
|
||||
|
|
||||
v
|
||||
+------------------+
|
||||
| Qwen 2.5 7B | LLM: Genera respuesta (~500-2000ms)
|
||||
+------------------+
|
||||
|
|
||||
v
|
||||
+------------------+
|
||||
| XTTS-v2 | TTS: Texto a voz (~500-1500ms)
|
||||
+------------------+
|
||||
|
|
||||
v
|
||||
Audio salida
|
||||
```
|
||||
|
||||
**Latencia total**: 2-4 segundos
|
||||
**Modelos requeridos** (~20GB en Network Volume):
|
||||
- Silero VAD (~1MB)
|
||||
- Faster Whisper Large V3 (~3GB)
|
||||
- Qwen 2.5 7B Instruct (~15GB)
|
||||
- XTTS-v2 (~2GB)
|
||||
|
||||
---
|
||||
|
||||
# 3. Modo EXTERNAL: Arquitectura Portavoz + Cerebro
|
||||
|
||||
Para lograr latencia conversacional (<500ms), se usa una arquitectura hibrida donde:
|
||||
|
||||
- **GPT-4o Realtime** actua como "portavoz" - maneja la voz en tiempo real
|
||||
- **Claude** actua como "cerebro" - analiza en paralelo y alimenta contexto
|
||||
|
||||
## 3.1 Concepto
|
||||
|
||||
```
|
||||
+---------------------------------------------------------------------+
|
||||
| PRINCIPIO PORTAVOZ + CEREBRO |
|
||||
| |
|
||||
| "GPT es rapido pero limitado. Claude es inteligente pero lento. |
|
||||
| Usamos GPT como frontend de voz mientras Claude piensa detras." |
|
||||
+---------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
GPT-4o Realtime responde instantaneamente con la informacion que tiene.
|
||||
Claude analiza la conversacion en paralelo y actualiza el contexto de GPT.
|
||||
|
||||
## 3.2 Flujo de Operacion
|
||||
|
||||
```
|
||||
PENNY EXTERNAL
|
||||
|
|
||||
+-------------------+-------------------+
|
||||
| |
|
||||
v v
|
||||
+--------------------+ +--------------------+
|
||||
| GPT-4o Realtime | | Claude |
|
||||
| | | |
|
||||
| - Maneja voz | <------ | - Analiza contexto |
|
||||
| - Responde rapido | contexto | - Busca en KB |
|
||||
| - ~300ms latencia | | - Prepara info |
|
||||
+--------------------+ +--------------------+
|
||||
| |
|
||||
v |
|
||||
Audio respuesta |
|
||||
| |
|
||||
+---------------------------------------+
|
||||
|
|
||||
Actualiza system
|
||||
prompt de GPT
|
||||
```
|
||||
|
||||
## 3.3 Ciclo de Conversacion
|
||||
|
||||
```
|
||||
TURNO 1:
|
||||
Usuario habla -> GPT-4o transcribe + responde (con contexto inicial)
|
||||
-> Claude recibe transcripcion
|
||||
-> Claude analiza, busca en knowledge base
|
||||
-> Claude prepara contexto enriquecido
|
||||
|
||||
TURNO 2:
|
||||
Usuario habla -> GPT-4o responde (ahora con contexto de Claude)
|
||||
-> Claude sigue analizando...
|
||||
-> Claude actualiza contexto
|
||||
|
||||
TURNO N:
|
||||
El ciclo continua. GPT siempre tiene el ultimo contexto de Claude.
|
||||
```
|
||||
|
||||
## 3.4 Componentes
|
||||
|
||||
### GPT-4o Realtime (Portavoz)
|
||||
- **Funcion**: Frontend de voz con latencia minima
|
||||
- **API**: OpenAI Realtime API
|
||||
- **Latencia**: ~300ms end-to-end
|
||||
- **Responsabilidades**:
|
||||
- Transcripcion de voz (ASR integrado)
|
||||
- Generacion de respuesta
|
||||
- Sintesis de voz (TTS integrado)
|
||||
- **Limitaciones**: Contexto limitado, razonamiento superficial
|
||||
|
||||
### Claude (Cerebro)
|
||||
- **Funcion**: Analisis profundo en segundo plano
|
||||
- **API**: Anthropic Messages API
|
||||
- **Latencia**: 1-3s (no bloquea la conversacion)
|
||||
- **Responsabilidades**:
|
||||
- Analizar intencion del usuario
|
||||
- Buscar en knowledge base
|
||||
- Preparar datos relevantes
|
||||
- Generar instrucciones para GPT
|
||||
- Detectar cuando GPT necesita correccion
|
||||
|
||||
## 3.5 Actualizacion de Contexto
|
||||
|
||||
Claude genera un "folio" que se inyecta en el system prompt de GPT:
|
||||
|
||||
```json
|
||||
{
|
||||
"context_update": {
|
||||
"timestamp": "2025-12-18T10:30:00Z",
|
||||
"user_intent": "Consulta sobre factura pendiente",
|
||||
"relevant_data": {
|
||||
"factura_id": "F-2024-1234",
|
||||
"importe": 1500.00,
|
||||
"vencimiento": "2025-01-15",
|
||||
"estado": "pendiente"
|
||||
},
|
||||
"suggested_response_elements": [
|
||||
"Confirmar importe de la factura",
|
||||
"Mencionar fecha de vencimiento",
|
||||
"Ofrecer opciones de pago"
|
||||
],
|
||||
"tone_guidance": "profesional pero cercano",
|
||||
"warnings": [
|
||||
"Cliente tiene 2 facturas mas pendientes - no mencionar a menos que pregunte"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Este contexto se traduce a instrucciones en el system prompt de GPT:
|
||||
|
||||
```
|
||||
[CONTEXTO ACTUALIZADO - Turno 3]
|
||||
El usuario pregunta por una factura. Datos relevantes:
|
||||
- Factura F-2024-1234 por 1500 EUR
|
||||
- Vence el 15 de enero 2025
|
||||
- Estado: pendiente
|
||||
|
||||
En tu respuesta:
|
||||
- Confirma el importe
|
||||
- Menciona la fecha de vencimiento
|
||||
- Ofrece opciones de pago
|
||||
|
||||
Tono: profesional pero cercano
|
||||
Nota: El cliente tiene otras facturas pendientes, no las menciones a menos que pregunte.
|
||||
```
|
||||
|
||||
## 3.6 Manejo de Errores y Correcciones
|
||||
|
||||
Si Claude detecta que GPT dio informacion incorrecta:
|
||||
|
||||
```json
|
||||
{
|
||||
"correction_needed": true,
|
||||
"correction_type": "factual_error",
|
||||
"what_gpt_said": "La factura vence manana",
|
||||
"correct_info": "La factura vence el 15 de enero",
|
||||
"inject_correction": true
|
||||
}
|
||||
```
|
||||
|
||||
GPT recibe instruccion de corregirse naturalmente:
|
||||
```
|
||||
[CORRECCION NECESARIA]
|
||||
En tu respuesta anterior mencionaste que la factura vence manana.
|
||||
La fecha correcta es el 15 de enero.
|
||||
Corrige esto de forma natural en tu proxima respuesta, sin disculparte excesivamente.
|
||||
```
|
||||
|
||||
## 3.7 Configuracion de Sesion
|
||||
|
||||
Request de inicio de sesion PENNY EXTERNAL:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "session_start",
|
||||
"mode": "EXTERNAL",
|
||||
|
||||
"portavoz": {
|
||||
"provider": "openai",
|
||||
"model": "gpt-4o-realtime",
|
||||
"voice": "alloy",
|
||||
"language": "es",
|
||||
"initial_system_prompt": "Eres un asistente de voz profesional..."
|
||||
},
|
||||
|
||||
"cerebro": {
|
||||
"provider": "anthropic",
|
||||
"model": "claude-sonnet-4-20250514",
|
||||
"analysis_depth": "standard",
|
||||
"knowledge_base_ref": "kb://empresa/documentos",
|
||||
"update_frequency": "every_turn"
|
||||
},
|
||||
|
||||
"context": {
|
||||
"user_id": "uuid",
|
||||
"session_purpose": "atencion_cliente",
|
||||
"available_actions": ["consultar_factura", "programar_pago", "transferir_humano"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3.8 Costos Estimados
|
||||
|
||||
| Componente | Costo por minuto |
|
||||
|------------|------------------|
|
||||
| GPT-4o Realtime (audio) | ~$0.06 |
|
||||
| Claude Sonnet (analisis) | ~$0.02 |
|
||||
| **Total** | **~$0.08/min** |
|
||||
|
||||
Para una conversacion de 5 minutos: ~$0.40
|
||||
|
||||
---
|
||||
|
||||
# 4. Seleccion de Modo en DECK
|
||||
|
||||
DECK presenta la opcion al usuario al iniciar sesion de voz:
|
||||
|
||||
```yaml
|
||||
# deck/config/penny.yaml
|
||||
|
||||
penny:
|
||||
default_mode: SELF_HOSTED
|
||||
allow_user_selection: true
|
||||
|
||||
modes:
|
||||
SELF_HOSTED:
|
||||
label: "Privado (modelos locales)"
|
||||
description: "Mayor privacidad, latencia 2-4s"
|
||||
endpoint: "wss://api.runpod.ai/v2/${PENNY_ENDPOINT}/ws"
|
||||
|
||||
EXTERNAL:
|
||||
label: "Rapido (APIs externas)"
|
||||
description: "Conversacion fluida, latencia ~300ms"
|
||||
portavoz_provider: "openai"
|
||||
cerebro_provider: "anthropic"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 5. Comparativa de Modos
|
||||
|
||||
| Aspecto | SELF_HOSTED | EXTERNAL |
|
||||
|---------|-------------|----------|
|
||||
| Latencia | 2-4s | ~300ms |
|
||||
| Costo/min | ~$0.01 | ~$0.08 |
|
||||
| Privacidad | Total | Datos a OpenAI/Anthropic |
|
||||
| Calidad respuesta | Buena (Qwen 7B) | Excelente (Claude) |
|
||||
| Experiencia | Aceptable | Conversacional |
|
||||
| Cold start | 15-30s (primer uso) | Inmediato |
|
||||
| Dependencias | RunPod | OpenAI + Anthropic APIs |
|
||||
|
||||
---
|
||||
|
||||
# 6. Casos de Uso Recomendados
|
||||
|
||||
**SELF_HOSTED**:
|
||||
- Datos sensibles / confidenciales
|
||||
- Uso interno empresarial
|
||||
- Demostraciones sin conexion externa
|
||||
- Minimizar costos en alto volumen
|
||||
|
||||
**EXTERNAL**:
|
||||
- Atencion al cliente en tiempo real
|
||||
- Demos a inversores / clientes
|
||||
- Conversaciones donde la fluidez importa
|
||||
- Usuarios impacientes
|
||||
|
||||
---
|
||||
|
||||
**Fin del Documento PENNY - Version 1.0**
|
||||
|
||||
*Sistema PENNY - "Portavoz + Cerebro"*
|
||||
1125
v4-archive/contratos-comunes/docs/S-CONTRACT.md
Normal file
1125
v4-archive/contratos-comunes/docs/S-CONTRACT.md
Normal file
File diff suppressed because it is too large
Load Diff
1158
v4-archive/contratos-comunes/docs/SENTINEL.md
Normal file
1158
v4-archive/contratos-comunes/docs/SENTINEL.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user