669 lines
16 KiB
Markdown
669 lines
16 KiB
Markdown
# 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"*
|