Planteamiento y contexto
La plataforma permite que plugins de terceros procesen conversiones de archivos, validación de campos y reglas específicas de cada inquilino. Los plugins provienen de diferentes lenguajes y no se puede confiar en ellos directamente; un plugin fuera de control no debe derribar el proceso host. Diseña un runtime de Wasm Component Model que cubra la definición de interfaces, la carga, el aislamiento, los presupuestos de recursos, las actualizaciones compatibles y la recuperación.
El Component Model describe importaciones y exportaciones mediante componentes, interfaces y worlds. WIT es el lenguaje de definición de interfaces, mientras que la Canonical ABI define cómo los valores de nivel superior cruzan los límites de los lenguajes. La entrevista evalúa si puedes transformar estos estándares en una plataforma de plugins multiinquilino operable.
Qué evalúa el entrevistador
Cubre la gobernanza de interfaces y tipos, el privilegio mínimo, el aislamiento de instancias, los presupuestos de CPU y memoria, el tiempo de espera (timeout) y la cancelación, la firma y procedencia de componentes, la compatibilidad de versiones, la reproducibilidad, los registros (logs) y métricas, los canarios y el rollback.
Preguntas de clarificación para hacer
- ¿Se ejecuta un plugin dentro de una solicitud síncrona o de un trabajo asíncrono, y cuáles son los presupuestos de latencia y rendimiento (throughput)?
- ¿Qué capacidades de archivos, red, claves o reloj se requieren y cómo se aísla a los inquilinos?
- ¿Puede la interfaz utilizar recursos, streams y futures, o solo tipos de valor delimitados?
- ¿Deben los inquilinos antiguos seguir siendo reproducibles tras las actualizaciones y de cuánto tiempo es la ventana de compatibilidad?
- ¿Debe una infracción o timeout terminar de inmediato, reintentarse de forma aislada o utilizar un fallback del host?
Una respuesta de 30 segundos
“Define un world WIT acotado y versionado, exponiendo únicamente las capacidades de negocio requeridas. El plano de control verifica la procedencia, las firmas y las dependencias; el plano de datos ejecuta una instancia aislada de Wasm con límites de CPU, memoria, salida y plazos de ejecución (deadlines). Comprueba la compatibilidad de interfaces y realiza actualizaciones mediante canarios, mientras registras la versión, el inquilino, el consumo del presupuesto y los resúmenes de resultados. Un timeout o una infracción detiene únicamente a ese plugin y devuelve un valor predeterminado seguro del host”.
Análisis detallado paso a paso
Paso 1: Definir interfaces WIT y límites de datos
Prioriza records, variants, lists y results delimitados con enums de error explícitos, longitudes máximas y codificación clara. No expongas objetos del host ni estados globales ocultos; cada world debe contener únicamente las importaciones y exportaciones requeridas por esa clase de plugin.
world transform-v2 {
export transform: func(input: record { bytes: list<u8>, mime: string }) -> result<list<u8>, transform-error>
}El registro de interfaces guarda el nombre del paquete, la versión, las reglas de compatibilidad y la versión del toolchain de bindings. Define una interfaz de stream independiente con contrapresión (backpressure) para datos grandes en lugar de disfrazar una entrada no delimitada como una lista.
Paso 2: Construir el aislamiento de capacidades e inquilinos
Crea una instancia nueva por cada llamada. De forma predeterminada, no proporciones capacidades de red, sistema de archivos, entorno, aleatoriedad o claves. Cuando se requiera acceso, concede una función del host explícita vinculada a la identidad del inquilino, el plugin y la solicitud.
Los tokens de capacidad deben ser de corta duración, auditables y no reutilizables entre inquilinos. Mantén las API del host al mínimo; nunca entregues a un plugin punteros del proceso host ni identificadores de sistema (handles) sin filtrar.
Paso 3: Establecer presupuestos y terminación
Establece presupuestos de instrucciones o tiempo, límites de memoria lineal, límites de tabla y pila, topes de salida y cuotas de concurrencia. Propaga la cancelación con un deadline; termina una instancia que exceda su presupuesto y registra el motivo. Decide si un reintento es seguro solo después de verificar la idempotencia.
Utiliza una cola asíncrona y un lease para trabajos prolongados en lugar de mantener una espera no delimitada dentro de una solicitud de usuario. Mide y limita la tasa (rate-limit) tanto por inquilino como por plugin para que un solo inquilino no consuma el pool de ejecución compartido.
Paso 4: Manejar la compatibilidad de componentes y ABI
Antes del lanzamiento, analiza el world WIT y las dependencias, y comprueba las importaciones y exportaciones frente a las reglas de compatibilidad. La Canonical ABI estandariza la representación de valores, pero no garantiza la compatibilidad de negocio; las adiciones de enums, los significados de error modificados y los cambios de unidades aún requieren pruebas de contrato.
Conserva los ejecutores y bindings para worlds antiguos y permite que los plugins declaren las versiones de interfaz compatibles. Utiliza lecturas duales o ejecución en la sombra (shadow execution) para comparar resultados y cambios de recursos antes de cambiar la versión predeterminada.
Paso 5: Verificar la cadena de suministro y la carga
Genera un digest de artefacto inmutable y firma el componente, el world WIT, el lockfile de dependencias y los metadatos de compilación. El plano de control solo permite firmantes de confianza y dependencias analizadas; la carga vuelve a verificar el digest, la firma, la versión del runtime de destino y el estado de revocación.
Registra el alta, la aprobación, la revocación y el rollback en un registro de auditoría. Nunca descargues un componente no registrado en tiempo de ejecución. Direcciona la caché por digest para que una etiqueta modificada no pueda cambiar silenciosamente el código que se ejecuta.
Paso 6: Observar, desplegar en canario y recuperar
Registra el digest del plugin, la versión de la interfaz, el inquilino, la latencia, el uso de recursos, el estado del resultado y la clase de error en cada llamada. Los registros no deben contener payloads de usuario ni claves. Agrega métricas por plugin e inquilino, incluidos timeouts, agotamiento de memoria y tasa de rechazo.
Despliega una nueva versión en canario sobre tráfico sintético o un conjunto pequeño de inquilinos y compara las diferencias de resultados y la latencia de cola (tail latency). Ante una regresión, detén y revoca esa versión y regresa al digest anterior. El host proporciona un valor predeterminado seguro para que el fallo de un plugin no se propague a la lógica de negocio central.
Una respuesta de ejemplo sólida
Definiría un world WIT acotado y versionado con tipos delimitados y otorgaría únicamente las capacidades del host requeridas. Cada solicitud obtiene una instancia aislada con límites de CPU, memoria, salida, deadline y concurrencia; el plano de control verifica firmas, digests, dependencias y revocaciones. Las actualizaciones pasan por comprobaciones de contratos, ejecución en la sombra y un canario pequeño. La observabilidad se divide por plugin, inquilino y versión; un timeout o una infracción mata únicamente esa instancia y devuelve un valor predeterminado seguro del host.
Errores comunes
- Exponer objetos del host directamente → escalada de privilegios y filtraciones entre inquilinos → utilizar funciones del host mínimas.
- Limitar la memoria pero no el tiempo → un bucle infinito sigue consumiendo el pool → establecer presupuestos de CPU, deadline y concurrencia.
- Tratar la Canonical ABI como compatibilidad de negocio → las unidades y la semántica de errores aún pueden romper a los clientes → mantener pruebas de contrato y versiones de world.
- Almacenar en caché mediante etiquetas mutables → una etiqueta modificada ejecuta código desconocido → direccionar mediante digest inmutable y firma.
- Reintentar cada fallo → los efectos secundarios no idempotentes se repiten → declarar la idempotencia y clasificar los errores.
Preguntas de seguimiento y respuestas
Pregunta de seguimiento 1: ¿Por qué no usar procesos o contenedores?
Depende del modelo de amenazas y del presupuesto. Las instancias de Wasm inician rápidamente y exponen interfaces controladas, pero no reemplazan la aplicación de parches en tiempo de ejecución, el fortalecimiento (hardening) del host ni la defensa en profundidad; los plugins de alto riesgo aún pueden ejecutarse en una capa de aislamiento más fuerte.
Pregunta de seguimiento 2: ¿Cómo se admite la transmisión (streaming) de archivos grandes?
Define una interfaz de stream con contrapresión con límites en la concurrencia, el tamaño de los fragmentos (chunks) y la salida acumulada. Utiliza trabajos asíncronos para tareas de larga duración y audita la cancelación y el estado del lease.
Pregunta de seguimiento 3: ¿Cómo decides si dos versiones son equivalentes?
Ejecuta un corpus de entrada fijo a través de ejecuciones en la sombra y compara los resultados normalizados, las clases de error, la latencia y el uso de recursos. Permite diferencias declaradas de punto flotante o de ordenación y bloquea el lanzamiento ante diferencias inaceptables.
Pregunta de seguimiento 4: ¿Qué sucede si un plugin necesita acceso a la red?
Otórgale una capacidad de proxy con listas de permitidos por inquilino y por dominio, con límites de tiempo de espera, límites de tamaño de respuesta y registros de auditoría. Deniega direcciones arbitrarias de forma predeterminada e invalida los tokens de capacidad inmediatamente tras su revocación.