En esta página
Propiedad de arquitectura
COADF P-1 enuncia el mínimo: un componente probabilístico devuelve un valor junto con una confianza y el método con el que se obtuvo el valor, nunca un valor desnudo, y nunca llega directamente a una salida. Este patrón trata de la segunda mitad, que es la que las implementaciones pierden. La respuesta de un modelo puede entrar en el sistema. Lo que no puede es convertirse, por ningún camino, en aquello que el sistema trata como establecido.
Tienen que cumplirse tres cosas a la vez:
- La salida tiene un tipo propio. Una propuesta y un registro autorizado son tipos distintos, tablas distintas o mensajes distintos. El código que tiene uno no puede pasarlo donde se espera el otro sin un paso explícito que alguien pueda revisar.
- La frontera valida en tiempo de ejecución. El contrato se comprueba cuando llega la respuesta, en el proceso que la recibe, diga lo que diga el emisor sobre lo que comprobó.
- La procedencia viaja con el valor. El método, el modelo y su versión, la versión del prompt y la ubicación en la fuente permanecen unidos a él en cada paso, serialización incluida. Sin ellos, P-4 no puede reconstruir y P-5 no puede declarar.
P-1 también exige que el componente informe una confianza. Cómo se expresa, se asigna y se usa la confianza corresponde a P-2, que COADF publica solo como principio. Este Companion no lo describe, y nada de lo que sigue depende de ello.
Por qué importa
La salida de un modelo procede de un proceso que no puede reproducirse a partir de sus entradas como sí puede la salida de un parser: el muestreo, las actualizaciones del modelo y los cambios de prompt la desplazan. Eso es aceptable para una propuesta e inaceptable para un hecho. El riesgo no es que un modelo se equivoque a veces; todo se equivoca a veces. El riesgo es perder la capacidad de decir qué valores vinieron de dónde, porque todo control posterior depende de ello. Una barrera solo detiene lo que puede ver, una declaración solo nombra lo que está marcado y una persona revisora solo comprueba lo que todavía apunta a su fuente.
La pérdida rara vez es una decisión. Ocurre en una línea de código corriente: una entidad del ORM rellenada con el JSON del modelo porque los nombres de los campos coincidían, un modelo de respuesta que descarta la procedencia porque nadie la añadió, una importación por lotes que evita el formulario donde vivía la validación. El patrón existe para que esa línea no pueda escribirse sin que nadie lo note.
Estrategias de implementación válidas
El aislamiento es arquitectónico, no necesariamente físico
No hacen falta microservicios. La propiedad se cumple cuando ningún camino de código permite al lado probabilístico producir un objeto autorizado, y un solo proceso puede mantenerla tan bien como una red. Conviene elegir la topología por sus propias razones (escalar por separado una carga de inferencia, aislar la biblioteca cliente de un proveedor, desplegar de forma independiente) y después construir la frontera en la forma elegida. Las cuatro figuras siguientes mantienen la misma propiedad en cuatro formas.
Arquitectura de ejemplo · No normativa
Monolito modular
- Flujo de datos en este ejemplo
- Opcional: puede no estar disponible
Descripción textual. Dentro de un solo proceso: un cliente del modelo, marcado como probabilístico, pasa su respuesta bruta a un módulo de frontera, que pasa una Proposal al núcleo de dominio. Un adaptador de clasificación, también dentro del proceso, puede pasar un enriquecimiento al núcleo de dominio, y consulta un servicio de clasificación externo, fuera del proceso. El núcleo de dominio escribe entradas en la traza de auditoría, una base de datos aparte. El único camino del cliente del modelo al núcleo de dominio pasa por la frontera.
Arquitectura de ejemplo · No normativa
Orientado a servicios
- Flujo de datos en este ejemplo
- Opcional: puede no estar disponible
Descripción textual. Un servicio de inferencia contiene un cliente del modelo, marcado como probabilístico, y una frontera que valida lo que envía. Envía por HTTP, bajo un contrato JSON, a un servicio de dominio, cuya propia frontera valida lo que recibe y pasa una Proposal al núcleo de dominio. El servicio de dominio contiene también un adaptador de clasificación, que consulta un servicio externo y puede pasar un enriquecimiento al núcleo de dominio, y la traza de auditoría, en la que el núcleo de dominio escribe entradas. El servicio de inferencia no tiene ninguna conexión con la traza de auditoría.
Arquitectura de ejemplo · No normativa
Orientado a eventos
- Flujo de datos en este ejemplo
Descripción textual. Un worker de inferencia contiene un cliente del modelo, marcado como probabilístico, y una frontera. Publica un mensaje en un tópico de propuestas. El cuerpo del mensaje lleva el trace_id de auditoría; sus cabeceras llevan el contexto de ejecución como un traceparent de W3C. Un consumidor de dominio lee el tópico, valida cada mensaje al recibirlo y pasa una Proposal al núcleo de dominio, que escribe entradas en la traza de auditoría.
Arquitectura de ejemplo · No normativa
Despliegue nativo de la nube
- Flujo de datos en este ejemplo
Descripción textual. En el namespace de inferencia, un pod de inferencia ejecuta el cliente del modelo y su frontera. Puede enviar al endpoint del modelo, en el namespace de servicio de modelos, y a la recepción de propuestas, en el namespace de registros, solo por su puerto de API. La recepción de propuestas valida lo que recibe y pasa una Proposal al núcleo de dominio, que escribe en la traza de auditoría y la base de datos de registros. Una nota indica que el namespace de inferencia no tiene ninguna ruta ni ninguna credencial hacia esa base de datos.
Los mismos cuatro elementos en cada topología
- Tipos distintos. El lado probabilístico puede construir una propuesta y nada más. El registro autorizado lo construye solo el código de dominio, a partir de una propuesta y de algo que el lado probabilístico no puede producir.
- Validación en tiempo de ejecución en cada lado receptor. Un esquema estricto: campos no declarados rechazados, sin conversión de tipos, vocabularios cerrados para los valores categóricos, longitudes acotadas. En una topología distribuida valida cada receptor, también el lado del dominio cuando el emisor es un servicio propio: “validamos antes de enviar” es una afirmación sobre otro desplegable, quizá sobre una versión anterior de él.
- La procedencia en el contrato. Declarada, obligatoria y preservada por cada mapeador y serializador en el camino de salida.
- Un paso de promoción explícito. La única vía de la propuesta al registro autorizado es una función, un endpoint o un comando que exige lo que el lado probabilístico no puede aportar. Para los valores derivados por un modelo de lenguaje, el fence público F-03 de COADF exige verificación humana antes de que lleguen a una salida publicada. La propia promoción queda registrada en la traza de auditoría.
Validación determinista en torno a una salida estocástica
Las comprobaciones que leen solo el valor (su forma, su vocabulario, su unidad, los rangos que define el propio dominio) se ejecutan antes de que ninguna persona lo mire. No hacen verdadero un valor. Hacen imposible un valor imposible, y lo hacen siempre de la misma manera, algo en lo que puede apoyarse la persona que revisa el valor.
Opciones de aplicación, de la más débil a la más fuerte
| Mecanismo | Detiene | No detiene |
|---|---|---|
| Separación de tipos | La promoción accidental en código que supera la comprobación de tipos | Casts, tipado dinámico, reflexión |
| Validación de esquemas en tiempo de ejecución | Respuestas mal formadas o que afirman de más | Un valor bien formado que es erróneo |
| Prueba de arquitectura sobre las importaciones | Que el módulo probabilístico importe código que escribe registros | Importaciones hechas por nombre en tiempo de ejecución; caminos de datos que no son importaciones |
| Permisos de base de datos por componente | Que un componente escriba en el almacén autorizado | Componentes que comparten credenciales |
| Despliegue separado y política de red | Que un componente desplegado por separado llegue siquiera al almacén | Cualquier cosa dentro de un mismo proceso; clústeres cuyo plugin de red no aplica la política |
La mayoría de los sistemas quiere los tres primeros siempre, y los dos últimos cuando el componente probabilístico se despliega por separado. El perfil de Python y FastAPI implementa los tres primeros; el perfil cloud-native añade los dos últimos.
Modos de fallo
La salida del modelo se escribe directamente en el almacenamiento autorizado
La respuesta se convierte en la entidad que el resto del sistema lee como hecho, porque los campos coincidían. Ninguna línea concreta es errónea. La frontera, sencillamente, no existe.
Propuestas indistinguibles de datos verificados
Una tabla, un tipo y un indicador que dice qué es cada cosa. El indicador toma por defecto el valor cómodo, o el propio JSON del modelo puede fijarlo.
La procedencia se pierde en el camino de salida
Un mapeador, un modelo de respuesta o una exportación omite el método y la fuente. Los frameworks que filtran la salida según un esquema declarado lo hacen sin ruido: FastAPI filtra una respuesta según su modelo de respuesta, y el serializador de Fastify omite las propiedades que un esquema de respuesta no enumera salvo que el esquema admita propiedades adicionales.
Validación solo en la interfaz de usuario
El formulario valida. La importación por lotes, el script de administración y el segundo cliente, no.
Los sistemas posteriores no distinguen lo inferido de lo verificado
El formato de exportación no tiene campo para el método, así que el sistema siguiente recibe un valor y nada más, y todos sus controles son ciegos a la diferencia.
Se confía en la respuesta en bruto sin validación en tiempo de ejecución
Un cast en TypeScript, un diccionario en Python, un mapeador permisivo en Java: el contrato existe en los tipos del código y en ninguna parte de su comportamiento. Las anotaciones de tipo de TypeScript se borran en la compilación, y sus tipados estándar declaran el resultado de
JSON.parsecomoany.La conversión de tipos oculta el error del modelo
Un análisis laxo convierte
"12"en12y"true"enTrue. El número parece correcto y nunca fue un número. El modo estricto de Pydantic rechaza esa conversión; la configuración por defecto del validador de Fastify activa la conversión de tipos. Hay que saber cuál de los dos se está ejecutando.Reparación silenciosa
La respuesta no supera la validación, así que se repite la llamada hasta que una respuesta la supera, y solo se conserva la última. Los fallos eran evidencia sobre el modelo, y han desaparecido.
Validación omitida por velocidad
Una optimización que construye objetos sin validar se convierte en el camino más fácil, y después en el atajo.
model_constructde Pydantic crea un modelo sin validarlo, exactamente como está documentado.
Verificación
Prueba unitaria
Pasa cuando: Cada respuesta mal formada se rechaza: un campo no declarado, un tipo convertible, una procedencia ausente, un atributo que nadie pidió.
Prueba de dientes: Se elimina una restricción en una copia de trabajo (por ejemplo, la regla que rechaza campos no declarados): la prueba correspondiente tiene que fallar.
Prueba de arquitectura
Pasa cuando: El módulo probabilístico no tiene ningún camino de importación hacia el código que escribe registros autorizados.
Prueba de dientes: Se añade la importación prohibida en una copia de trabajo: el contrato falla y la compilación se detiene.
Prueba de contrato
Pasa cuando: Productor y consumidor coinciden en el esquema de la propuesta, con los campos de procedencia obligatorios.
Prueba de dientes: Se quita un campo de procedencia del esquema del productor: la prueba de contrato del consumidor falla.
Prueba de integración
Pasa cuando: Cuando el componente probabilístico se despliega por separado, sus credenciales no pueden escribir en el almacén autorizado.
Prueba de dientes: Se intenta la escritura con esas credenciales: la base de datos la rechaza.
Prueba de extremo a extremo
Pasa cuando: No puede publicarse una salida cuyo atributo procede de una propuesta que nadie verificó.
Prueba de dientes: Se planta una propuesta sin verificar y se solicita la publicación: rechazada, y el rechazo figura en la traza de auditoría.
Realizaciones alternativas
- Interfaces solo de sugerencia. La salida del modelo se muestra a una persona como sugerencia y nunca se almacena como valor. Sencillo y robusto; renuncia a la trazabilidad de lo sugerido salvo que también se registren las sugerencias.
- Un contrato compartido y neutral respecto del lenguaje (JSON Schema, Protocol Buffers) en lugar de modelos nativos de cada lenguaje. Mejor entre lenguajes; traslada la cuestión de la estrictez al esquema, donde las propiedades adicionales y los formatos tienen que decidirse de forma explícita.
- Modos de salida estructurada de las API de modelos. Reducen las respuestas mal formadas en el productor. No eximen al consumidor de validar, porque el consumidor no puede verificar cómo se configuró el productor.
- Almacenamiento separado para propuestas y registros, dos tablas o dos almacenes en lugar de una tabla con un estado. Más pesado, y hace visible la separación en cada consulta que cualquiera escriba.
Limitaciones
- La frontera controla adónde puede ir la salida del modelo. No hace correcta la salida del modelo, y un valor erróneo bien formado supera todas las comprobaciones de este patrón.
- La separación de tipos detiene accidentes, no intenciones. Quien tiene acceso de escritura al dominio puede construir a mano un objeto autorizado; la revisión de código y la traza de auditoría son lo que lo hace visible.
- Este patrón no dice cuándo una propuesta necesita a una persona ni cómo se expresa la confianza. Eso corresponde a P-2 y P-3, que COADF publica solo como principios.
- La validación vale lo que vale el contrato. Un esquema permisivo, validado de forma estricta, sigue siendo permisivo.
Fuentes
- FastAPI: Response model: return type and data filtering · documentación oficial · FastAPI 0.141 · Comprobado el 2026-09-11
- Fastify: fast-json-stringify: additionalProperties · repositorio del proyecto · Comprobado el 2026-09-11
- TypeScript: The Basics: erased types · documentación oficial · Comprobado el 2026-09-11
- TypeScript: lib.es5.d.ts: JSON.parse · repositorio del proyecto · Comprobado el 2026-09-11
- Pydantic: Strict mode · documentación oficial · Pydantic 2.13 · Comprobado el 2026-09-11
- Fastify: Validation and serialization · documentación oficial · Fastify 5.12 · Comprobado el 2026-09-11
- Pydantic: Models: creating models without validation · documentación oficial · Pydantic 2.13 · Comprobado el 2026-09-11
