Manejo de Excepciones Normativas (Ley 21.719)
El SDK de Gen.IA.L CAPA implementa una jerarquía de excepciones tipadas que detienen la ejecución inmediatamente (Fail-Closed) ante violaciones de privacidad o pausan el flujo para solicitar consentimiento o intervención humana.
🏛️ Jerarquía de Excepciones
CapaSDKError (Base)
├── CapaPolicyViolationError (403 Forbidden - Fail-Closed)
│ ├── CapaDataResidencyError (Transferencia internacional no autorizada)
│ └── CapaPurposeMismatchError (Violación de minimización de finalidad)
├── CapaConsentRequiredError (422 Unprocessable Entity - Requiere firma)
├── CapaRightToErasureActiveError (403 Forbidden - Titular ejerció Derecho al Olvido)
├── CapaAnonymizationRequiredError (Delegación de sanitización de entidades complejas)
└── CapaRateLimitExceededError (429 Too Many Requests - Cuota excedida)
💻 Ejemplos de Implementación de Control de Errores
- Python (FastAPI)
- Node.js / TypeScript (NestJS / Express)
from fastapi import FastAPI, HTTPException, status
from genial_capa.exceptions import (
CapaPolicyViolationError,
CapaDataResidencyError,
CapaPurposeMismatchError,
CapaConsentRequiredError,
CapaRightToErasureActiveError,
CapaAnonymizationRequiredError,
)
app = FastAPI()
@app.post("/agente/ejecutar")
async def ejecutar_agente(payload: dict):
try:
resultado = await mi_funcion_protegida(payload)
return {"status": "success", "data": resultado}
except CapaDataResidencyError as e:
# Transferencia fuera de la región no permitida
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"Violación de Residencia de Datos hacia {e.destination}: {e}",
)
except CapaPurposeMismatchError as e:
# Finalidad no autorizada en el contrato
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"Desviación de finalidad no permitida: {e}",
)
except CapaConsentRequiredError as e:
# Se requiere autorización expresa del titular
return {
"status": "requires_consent",
"required_fields": e.required_for_fields,
"message": "Firma del titular requerida antes de procesar.",
}
except CapaRightToErasureActiveError as e:
# Titular ejerció derecho al olvido
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"Titular ejerció Derecho al Olvido: {e.identifier}",
)
except CapaAnonymizationRequiredError as e:
# Estructura compleja que requiere anonimización local
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=f"Debe anonimizar localmente: {e.fields_to_anonymize}",
)
import { Request, Response } from 'express';
import {
CapaPolicyViolationError,
CapaDataResidencyError,
CapaPurposeMismatchError,
CapaConsentRequiredError,
CapaRightToErasureActiveError,
CapaAnonymizationRequiredError,
} from '@genial-capa/node-sdk';
export async function handleAgentRequest(req: Request, res: Response) {
try {
const result = await miFuncionProtegida(req.body);
return res.json({ status: 'success', data: result });
} catch (error) {
if (error instanceof CapaDataResidencyError) {
return res.status(403).json({
error: 'DATA_RESIDENCY_VIOLATION',
destination: error.destination,
message: error.message,
});
}
if (error instanceof CapaConsentRequiredError) {
return res.status(422).json({
error: 'CONSENT_REQUIRED',
fields: error.requiredForFields,
message: 'Firma requerida.',
});
}
if (error instanceof CapaRightToErasureActiveError) {
return res.status(403).json({
error: 'RIGHT_TO_ERASURE_ACTIVE',
identifier: error.identifier,
});
}
if (error instanceof CapaAnonymizationRequiredError) {
return res.status(422).json({
error: 'ANONYMIZATION_REQUIRED',
fields: error.fieldsToAnonymize,
});
}
return res.status(500).json({ error: 'INTERNAL_ERROR' });
}
}