Notas técnicas
Correcciones breves de errores de categoría frecuentes.
No normativo
- Versión del Companion
- 1.0
- Corresponde a COADF Core
- 2.2
- Estado
- Vigente
- Última revisión
Cada nota corrige un error de categoría: dos cosas que se parecen y ofrecen cosas distintas.
OpenTelemetry no es una traza de auditoría
OpenTelemetry registra y propaga contexto de ejecución: qué llamadas hizo una petición, cuánto tardaron, dónde fallaron. Está diseñado para muestrearse, filtrarse y transformarse en el camino hacia un backend, y una traza que no se muestrea no se exporta; el filter processor del Collector descarta por configuración la telemetría que coincide. Su identidad es una ejecución, transportada en la cabecera W3C traceparent. Una traza de auditoría responde a otra pregunta sobre otra unidad: qué le ocurrió a una transacción de negocio, quién actuó y con qué evidencia, de forma completa y sin ediciones posteriores.
- No muestrear, filtrar ni encaminar nunca entradas de auditoría a través de una pipeline de telemetría.
- Correlacionar ambas: registrar el
trace_idde auditoría en los spans como atributo. No reutilizar un identificador de traza distribuida como identidad de auditoría. - Clasificar aquello con lo que se correlaciona. Un atributo de span sale del almacén de auditoría hacia exportadores, proveedores y una retención propia: una referencia opaca, nunca datos personales ni un secreto.
- Contar con que una transacción de negocio abarque varias trazas distribuidas: la petición de recepción, un job asíncrono, una decisión tomada días después.
- OpenTelemetry: Sampling · documentación oficial · Comprobado el 2026-09-11
- OpenTelemetry: Transforming telemetry · documentación oficial · Comprobado el 2026-09-11
- W3C: Trace Context, the traceparent header · especificación · W3C Recommendation, Level 1 · Comprobado el 2026-09-11
Las políticas de admisión de Kubernetes no sustituyen la validación en la aplicación
El control de admisión intercepta las peticiones al servidor de API de Kubernetes después de la autenticación y la autorización, antes de que el objeto se persista. Ve Deployments, Pods y ConfigMaps, y las peticiones de lectura lo eluden por completo. Nunca ve las peticiones HTTP que atiende un servicio, los mensajes que consume ni las respuestas que devuelve un modelo. Juzga las peticiones a medida que llegan, algo que Kubernetes explica de forma expresa para un plugin de admisión: cuando se añade un LimitRange, los pods que ya existen siguen sin cambios.
- Usar la admisión para propiedades de las cargas de trabajo: imágenes fijadas por digest, versiones nombradas, credenciales ausentes donde tienen que estar ausentes.
- Mantener la validación de frontera en la aplicación, en cada punto de entrada que tenga.
- Auditar por separado los objetos existentes, como hace la auditoría de Gatekeeper; la admisión solo ve cambios.
- Kubernetes: Admission control: what are they · documentación oficial · Kubernetes 1.37 · Comprobado el 2026-09-11
- Kubernetes: Limit Ranges: admission-time validation · documentación oficial · Kubernetes 1.37 · Comprobado el 2026-09-11
- Open Policy Agent Gatekeeper: Gatekeeper: audit · documentación oficial · Gatekeeper 3.23 · Comprobado el 2026-09-11
El event sourcing no es necesario para una evidencia de solo inserción
El event sourcing convierte un log de eventos de solo inserción en el sistema de registro y deriva el estado de él. Eso da una historia completa por construcción, a un precio considerable: cada modelo de lectura es una proyección, y cada cambio en la forma de un evento es una migración de la historia. Una traza de auditoría de solo inserción junto a un estado ordinario da lo que pide COADF P-4 (una historia a la que se añade y que nunca se reescribe, reconstruible en una consulta) sin cambiar cómo guarda su estado el resto del sistema. Los privilegios por operación y los triggers de rechazo bastan para construirla en PostgreSQL.
- Elegir el event sourcing por razones propias del dominio, no para obtener una traza de auditoría.
- Una tabla de solo inserción con un rol que solo puede insertar, triggers de rechazo y escrituras idempotentes realiza una evidencia de solo inserción sin event sourcing, dentro de la propia frontera de confianza de la base de datos.
- En ambos casos, la entrada se escribe en la misma transacción que el cambio que registra.
- PostgreSQL Global Development Group: Privileges · documentación oficial · PostgreSQL 18 · Comprobado el 2026-09-11
Los microservicios no son necesarios para el aislamiento probabilístico
La frontera probabilística es una propiedad de los caminos de código: ningún camino permite que la salida de un modelo se convierta en un objeto autorizado sin un paso explícito y registrado. Una frontera de módulo que el build hace cumplir mantiene esa propiedad dentro de un solo proceso, con contratos de importación en Python o reglas de arquitectura como pruebas unitarias en Java. Una frontera de red añade una aplicación a nivel de infraestructura y, con ella, versionado de contratos, fallos parciales, reintentos y propagación de contexto entre saltos, que son lugares nuevos donde la propiedad puede perderse.
- Desplegar el componente probabilístico por separado cuando lo pidan el escalado, el aislamiento de una biblioteca de un proveedor o las entregas independientes, no porque lo pida un principio.
- Hacer cumplir la frontera de módulo con una prueba de arquitectura en cualquier caso.
- Cuando la frontera es una red, validar de nuevo en el lado receptor.
- import-linter: Contract types · documentación oficial · import-linter 2.15 · Comprobado el 2026-09-11
- ArchUnit: ArchUnit user guide · documentación oficial · ArchUnit 1.5 · Comprobado el 2026-09-11
El tipado estático no sustituye la validación en tiempo de ejecución en las fronteras externas
Un sistema de tipos comprueba el código contra sí mismo. En una frontera externa, los datos vienen de fuera del código: un modelo, un cliente, una cola. Las anotaciones de tipo de TypeScript se borran antes de que el programa se ejecute y JSON.parse está tipado como si devolviera any; el runtime de Python no hace cumplir las anotaciones de tipo; y un tipo de Java describe lo que se le pidió producir a un deserializador, no lo que envió el emisor. El tipo es una promesa que la frontera tiene que cumplir, en tiempo de ejecución, con un esquema.
- Derivar el tipo estático del esquema de tiempo de ejecución siempre que el lenguaje lo permita.
- Validar en cada lado receptor, no solo en el punto de entrada web.
- Mantener los casts fuera del código de frontera: un cast es donde el sistema de tipos deja de comprobar.
- 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
- Python Software Foundation: typing: support for type hints · documentación del lenguaje · Python 3.14 · Comprobado el 2026-09-11
Una pipeline de CI en verde no demuestra que un control sea suficiente para la arquitectura
Una pipeline en verde demuestra que pasaron las comprobaciones que ejecutó. No dice nada de las comprobaciones que se omitieron y se notificaron como exitosas, de las selecciones que no correspondieron a ninguna prueba, de los fences colocados en el camino equivocado ni de las propiedades para las que nadie escribió una comprobación. El modelo de informe de controles de COADF enuncia la misma regla desde el otro lado: un control se informa como impuesto solo cuando su evidencia se ejecutó en la ejecución identificada y pasó.
- Registrar, en cada ejecución, qué comprobaciones se ejecutaron y cuántas aserciones se evaluaron.
- Demostrar los dientes de cada fence en su camino real, y volver a demostrarlos cuando el camino cambia.
- Revisar lo que no se comprueba con la misma seriedad que lo que sí.
- GitHub: Control jobs with conditions · documentación oficial · Comprobado el 2026-09-11
