Archive: System v4 - Estado al 2024-12-24

This commit is contained in:
ARCHITECT
2025-12-24 17:28:34 +00:00
parent a92d41c846
commit 1b392803fd
81 changed files with 24560 additions and 0 deletions

View 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

View 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"*

View 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*

View 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 |

View 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"*

View 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*

View 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"*

View 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"*

View 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"*

View 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"*

View 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"*

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff