Quiosco de Reservas Autoservicio
Un quiosco es un sitio web de reservas con el modelo de confianza invertido: el cliente no está autenticado por diseño y es físicamente compartido, por lo que toda la confianza reside en el servidor (precios, capacidad, idempotencia) y todo el estado es desechable (en memoria, reinicio automático, nunca persistido). Todo en esta habilidad se deriva de esos dos hechos.
Cuándo usarlo
- Construir una terminal de reserva de autoservicio para capacidad basada en slots (estaciones × ventanas de tiempo) con complementos opcionales de equipo y consumibles.
- Añadir modo quiosco a una aplicación que ya tenga reservas en línea.
- Auditar un quiosco existente contra las reglas estrictas a continuación; provenance.md registra la razón detrás de cada una.
Cuándo NO usarlo
- Servidor de conmutación por error local sin conexión — ese es el
skill hermano
island-mode-server; este skill solo define el contrato de conmutación por error del lado del cliente del quiosco. - Pantallas de señalización digital / pantallas de visualización — capacidad diferente (reproducción, sin entrada), skill diferente.
- Herramientas de POS para personal o administración de reservas — el personal está autenticado y es de confianza; el modelo de confianza de este skill es incorrecto para ellos.
- Un sitio web de reservas normal — toma la interfaz del backend si es útil, pero la maquinaria del quiosco (teclado, temporizadores, endurecimiento táctil) es peso muerto allí.
Arquitectura
KioskProvider (reducer puro: pasos, selecciones, carrito, sessionId)
│ props: porciones de diccionario hooks: precios · equipo · disponibilidad
pantallas: servicio→fecha→hora→participantes→equipo→resumen→confirmación
│ └─ flujo lateral: búsqueda-de-reserva → edición-de-reserva
▼ un envoltorio de fetch (clave de dispositivo + URL base sin conexión por conmutación)
/api/kiosk/booking/{create,lookup,add-items,edit} ← todas las decisiones de confianza
▼ Interfaz KioskBackend: precios del servidor · promociones · bloqueos de existencias (TTL 15 min)
re-verificación transaccional de capacidad · pago en mostrador/en línea · webhook
en tiempo real: location.lastBookingChangeAt → re-obtener silenciosamente → REFRESH_SLOT
Hechos críticos
- Los toques del usuario navegan; las actualizaciones en segundo plano nunca lo hacen.
SET_SLOTvsREFRESH_SLOTes la diferencia entre disponibilidad en vivo y teletransportar a un cliente fuera de la pantalla de resumen en medio de la compra. - El servidor fija todos los precios. Nada con forma de dinero cruza el cable entrante; el total del cliente es una vista previa.
- El pago en mostrador es la ruta de resiliencia — la reserva se confirma con
PENDING_COUNTER_PAYMENT, sin integración de pago en el bucle; el pago en línea en un quiosco significa un código QR que el cliente escanea, nunca navegando el quiosco fuera de la aplicación. - Cada entrada de texto abre el teclado en pantalla y establece
inputMode="none". Sin ambos es una pantalla inutilizable. - Los bloqueos de existencias están reservados con TTL (15 min) y se liberan en cada ruta de fallo — el trabajo de barrido es la red de seguridad, no el mecanismo.
- El sessionId del cliente es la clave de idempotencia. Doble toque, reintento, respuesta perdida: como máximo una reserva.
Reglas estrictas
Nunca persistas el estado de sesión del quiosco. El siguiente cliente no debe ver el nombre del anterior. En memoria + reinicio por inactividad de 120 s + reinicio de confirmación de 30 s, verificado en hardware.
Nunca confíes en el cliente para precios, capacidad o validez de promociones. El servidor calcula cada cantidad y responde a una promoción inválida con
PROMO_INVALID; un cliente en un quiosco no tiene forma de verificar el monto.
Un envoltorio de fetch para cada solicitud del quiosco. El envoltorio lleva el encabezado del dispositivo, el envoltorio de error y la URL base de conmutación por error, por lo que la autenticación, los errores y la conmutación por error sin conexión se aplican a cada solicitud a la vez.
Si la clave del dispositivo está configurada, un encabezado faltante es un 401. Solo rechazar por clave incorrecta es lo mismo que no tener autenticación.
Libera los bloqueos de existencias en cada ruta de fallo después de adquirirlos. Un 409 que mantiene la reserva congela las existencias durante todo el TTL.
Inicio rápido
- Lee state-machine.md; implementa el reducer y el proveedor, ejecuta su conjunto de pruebas.
- Construye las pantallas según el contrato en screens.md con el sistema de diseño del anfitrión — teclado, temporizadores, endurecimiento táctil.
- Implementa las rutas de api-contract.md sobre la interfaz de booking-backend.md.
- Conecta frescura + sin conexión según realtime-offline.md.
- Despliega y haz pruebas de humo según operations.md.
Contrato de Adaptación
| Interfaz | Este skill entrega | El anfitrión proporciona |
|---|---|---|
| Entidades de dominio | servicio/estación/equipo/consumible + tabla de renombrado | su vocabulario (cancha, kart, bahía…) |
| Ámbito de inquilino | locationId en la URL del quiosco, verificado por el servidor | su modelo de ubicación/sitio |
| Autenticación del dispositivo | Contrato x-kiosk-api-key | gestión de claves; tokens por dispositivo opcionales |
| Acceso a datos | Interfaz KioskBackend; referencia de Firestore + esbozo SQL | su ORM/SDK |
| Pagos | Estado de mostrador + contrato de sesión de pago/webhook | Stripe o equivalente |
| Tiempo real | Interfaz SubscribeFreshness | Firestore/Supabase/SSE/polling |
| Sin conexión | Contrato NetworkStatus | Servidor LAN (island-mode-server) o ninguno |
| Primitivas de UI | estructura, estados, reglas de interacción | botones, diálogo, spinner, apariencia |
| Estilo | intención de diseño, objetivos táctiles, un token --primary | su sistema de diseño |
| Cadenas | árbol de claves de diccionario, todas las claves requeridas | sus archivos i18n, todas las locales |
| Validación | Guardias sin dependencias | su biblioteca de esquemas, si la hay |
Directorio de referencia
| Escenario | Palabras clave de activación | Referencia |
|---|---|---|
| Estado, pasos, reducer, sesión, pruebas | paso, reducer, GO_BACK, REFRESH_SLOT, sessionId, reset | state-machine.md |
| Pantallas, teclado, temporizadores, táctil, claves i18n | teclado en pantalla, inactividad, cuenta atrás, QR, objetivo táctil, diccionario | screens.md |
| Rutas, autenticación, validación, idempotencia, errores | x-kiosk-api-key, 401, 409, idempotencia, PROMO_INVALID, búsqueda, PII | api-contract.md |
| Capacidad, existencias, pagos, webhook, crons | transacción, bloqueo de existencias, TTL, PENDING_COUNTER_PAYMENT, webhook, reembolso | booking-backend.md |
| Actualización en vivo, caché, conmutación por error sin conexión | lastBookingChangeAt, onSnapshot, s-maxage, banner sin conexión, LAN, sondeo de salud | realtime-offline.md |
| Despliegue, control de acceso, superficie del operador | Edge --kiosk, acceso asignado, latido, compuerta de función, prueba de humo | operations.md |
| Por qué las plantillas difieren de la implementación anterior | auditoría, libro mayor, mantenido deliberadamente, añadido | provenance.md |