Caputchin
Referencias

Métodos y eventos del widget

El widget de Caputchin incluye dos custom elements, y tu página interactúa con ellos en dos direcciones: llamas métodos en el elemento para conducirlo, y escuchas eventos que emite para reaccionar. Esta página es la referencia exhaustiva de ambas superficies.

Cada evento es un CustomEvent despachado con bubbles: true y composed: true, así que escapa del shadow DOM del widget y puedes escucharlo directamente en el elemento (o en cualquier ancestro). Los datos están siempre en event.detail.

Los dos elementos de un vistazo

ElementoPropósitoMétodos
<caputchin-widget>Solo verificación (proof-of-work / checkbox).start()
<caputchin-game>Anfitrión de juego, con verificación opcional.pass(), fail()

El widget de checkbox tiene solo start(); no expone pass() / fail(). El anfitrión de juego no tiene start() (su ronda se vuelve en vivo al montarse para inline, o al primer abrir del diálogo para modal / fullscreen). Ambos elementos emiten start, pass, error, y degraded; el anfitrión de juego además emite dialog-shown y dialog-hidden. La cobertura está en la tabla de eventos de abajo.

Métodos

start() (solo <caputchin-widget>)

Empieza la verificación de inmediato. Su propósito es el disparador manual: cuando el elemento tiene trigger="manual", llamas a start() para disparar la resolución de proof-of-work desde tu propio gesto (por ejemplo, al enviar tu formulario) en vez de la checkbox integrada. Con los disparadores auto / click por defecto el elemento cablea su propia activación, así que no llamas a esto.

const widget = document.querySelector("caputchin-widget");
widget.start();

El anfitrión de juego no tiene start(). Mira modo manual para el recorrido completo de conducirlo-tú-mismo.

pass(payload) (solo <caputchin-game>)

Libera el gate de verificación: el visitante tuvo éxito. Válido solo cuando trigger="manual"; llamarlo en un juego no-manual emite un error con el código invalid-call. El primer pass() canjea y bloquea el veredicto; las llamadas posteriores se ignoran en silencio (una ronda por sesión).

const widget = document.querySelector("caputchin-game");
widget.pass({ trace: roundRecord });
Campo de payloadTipoSignificado
tracestringEl registro opaco de ronda que tu juego produce. En una ronda con gate el servidor la repite para derivar el veredicto autoritativo; en una clave sin gate o solo-juego se acepta tal cual. Pasa una cadena vacía si tu interacción no tiene registro que repetir.

No hay campo score en este método, el gate es la repetición del trace por el servidor, no una puntuación declarada por el cliente. (Un score sí aparece en el evento pass, que es el widget reportándote de vuelta, no tú al widget.)

Llamar a pass() antes de que la ronda haya empezado (modal / fullscreen, diálogo aún no abierto) emite un error con el código invalid-call. En una clave solo-juego (sin sitekey) no hay gate que liberar, así que pass() simplemente emite el evento pass con token: null.

fail(payload?) (solo <caputchin-game>)

Aborta la ronda: una derrota definitiva. Válido solo cuando trigger="manual" (de lo contrario invalid-call). Opcional, una ronda sin terminar se trata como un no-pass de todos modos. Aborta la verificación en curso (las comprobaciones de proof-of-work e instrumentación) y hace aflorar un evento error con el código game-error-relayed.

widget.fail({ code: "out-of-moves", message: "no moves left" });
Campo de payloadTipoSignificado
codestring (opcional)Tu código de diagnóstico; aflorado como el originalCode del evento error. Por defecto game-failed.
messagestring (opcional)Motivo legible por humanos.

Eventos

Escucha con addEventListener(type, handler). Cada payload vive en event.detail.

EventoEmitido porevent.detailSe dispara cuando
startambos{ gameId: string | null }Empieza la verificación (auto al montarse, en la activación, o vía start()). gameId está fijado para una ronda de juego, null para el widget simple.
passambos{ token: string | null, score: number | null, durationMs: number | null }La verificación se libera. token es el token envuelto para enviar a tu backend; null en una clave solo-juego (sin sitekey).
errorambos{ code, message, severity, originalCode? }Cualquier cosa desde un warning de config benigno hasta un fallo duro. Mira el evento error.
degradedambos{ reason: "timeout" | "network" | "http" | "malformed" }El widget no pudo resolver a tiempo el tamaño / skin / locale que configuraste, así que renderizó con sus valores por defecto empaquetados. No es un error. Mira el evento degraded.
dialog-shown<caputchin-game>{ layout: "modal" | "fullscreen" }Un diálogo de juego en overlay se abre (programático o primer clic).
dialog-hidden<caputchin-game>{ layout: "modal" | "fullscreen" }Un diálogo de juego en overlay se cierra (programático, Escape, o clic en el fondo).

El evento pass y el token

El evento pass es tu señal de que la verificación tuvo éxito, pero no es la decisión de confianza. La decisión de confianza es tu backend confirmando detail.token. Verifica siempre el token en tu backend; nunca concedas acceso solo del evento del front-end. En un formulario, el widget también inyecta el token como un campo caputchin-token para que un POST normal de formulario lo lleve. El score y el durationMs de este evento son analítica reportada por el cliente y pueden ser null; nunca los trates como una señal de confianza.

El evento error

El evento error lleva un code estable, un message humano, una severity, y a veces un originalCode. Cada código tiene una severity por defecto fija para que puedas filtrar los warnings de "siguió corriendo" de los fallos de "de verdad se rompió" sin codificar a mano una tabla de código-a-severity, solo lee detail.severity. El conjunto completo de códigos:

codeseveritySignificado
invalid-configwarnUn atributo o combinación que el widget rechazó; degrada con gracia y sigue corriendo.
invalid-callwarnUn método llamado cuando no era válido (p. ej. pass() en un juego no-manual, o antes de que la ronda empezara).
verification-failederrorLa comprobación de proof-of-work o instrumentación (o el canje del token) falló; no se emitió token.
game-load-failederrorEl bundle del juego no se pudo resolver, cargar, o registrar.
gate-unavailableerrorEl servidor devolvió un rechazo autoritativo en el bootstrap (una clave con gate no pudo suministrar un juego válido).
game-error-relayederrorUn error afloró desde dentro del juego (retransmitido desde el iframe, o de un fail() manual).

detail.originalCode está presente cuando el code público es una generalización de un motivo interno más concreto (por ejemplo, un fallo de carga de iframe retransmitido como game-load-failed lleva el iframe-load-failed / iframe-script-blocked / game-not-registered crudo en originalCode). Usa code para ramificar y originalCode solo para diagnóstico.

El evento degraded

Al montarse, el widget hace una llamada corta a Caputchin para resolver el tamaño, skin y locale que configuraste (y, para un juego del marketplace, su footprint preferido). Si esa llamada falla o es demasiado lenta, el widget no se bloquea ni se rompe: renderiza con los valores horneados en el bundle y emite degraded para que el fallback nunca sea silencioso. El widget sigue plenamente funcional tras un evento degraded, solo que la presentación resuelta puede diferir de lo que configuraste (un juego puede aparecer en su tamaño por defecto, o el checkbox en su tema por defecto). El widget reintenta una resolución lenta antes de caer al fallback, así que degraded significa que los reintentos se agotaron, no que un solo intento fuera lento.

detail.reason te dice por qué la resolución cayó al fallback, para que puedas mostrarlo en tu propia telemetría:

reasonSignificado
timeoutLa resolución no respondió dentro de su presupuesto de tiempo (servicio lento o inalcanzable).
networkLa solicitud misma falló (offline, DNS, bloqueada, o conexión reiniciada).
httpEl servicio respondió con un estado de error.
malformedEl servicio respondió, pero el cuerpo no era válido.

degraded es un aviso, no un fallo, así que deliberadamente no es un evento error: una resolución lenta no debería disparar los handlers que cableas para fallos reales. Escúchalo solo si quieres observar los renders degradados, por ejemplo para alertar cuando tus visitantes están viendo la presentación de fallback.

Escuchar, en la práctica

const widget = document.querySelector("caputchin-game");

const onPass = (e) => {
  // send e.detail.token to your backend to verify
};
const onError = (e) => {
  if (e.detail.severity === "error") {
    console.error(e.detail.code, e.detail.message);
  }
};

widget.addEventListener("pass", onPass);
widget.addEventListener("error", onError);

// Clean up when you tear down your view:
widget.removeEventListener("pass", onPass);
widget.removeEventListener("error", onError);

Estos son CustomEvents nativos del DOM, así que en React los adjuntas con un ref y addEventListener (no props JSX onPass); los ejemplos de frontend muestran el cableado específico de cada framework. Como cada evento burbujea y es composed, también puedes delegar desde un elemento contenedor en vez de ligar cada widget individualmente.

Véase también

En esta página