Kiosque de réservation en libre-service
Un kiosque est un site web de réservation avec un modèle de confiance inversé : le client n'est pas authentifié par conception et est physiquement partagé, donc toute la confiance repose sur le serveur (prix, capacité, idempotence) et tout l'état est jetable (en mémoire, réinitialisation automatique, jamais persistant). Tout dans cette compétence découle de ces deux faits.
Quand l'utiliser
- Construire un terminal de réservation en libre-service pour une capacité basée sur des créneaux (stations × intervalles de temps) avec des options d'équipement et de consommables en complément.
- Ajouter un mode kiosque à une application qui propose déjà une réservation en ligne.
- Auditer un kiosque existant par rapport aux règles strictes ci-dessous ; provenance.md enregistre la raison derrière chacune.
Quand NE PAS l'utiliser
- Serveur de bascule hors ligne sur site — il s'agit de la compétence sœur
island-mode-server; cette compétence ne définit que le contrat de bascule côté client du kiosque. - Signalisation numérique / écrans d'affichage — capacités différentes (lecture, pas de saisie), compétence différente.
- Outils de vente ou de réservation destinés au personnel — le personnel est authentifié et de confiance ; le modèle de confiance de cette compétence ne leur convient pas.
- Un simple site web de réservation — la partie backend peut être utile, mais les mécanismes du kiosque (clavier, minuteries, durcissement tactile) sont superflus.
Architecture
KioskProvider (pur réducteur : étapes, sélections, panier, sessionId)
│ props : tranches de dictionnaire hooks : tarification · équipement · disponibilité
écrans : service→date→heure→participants→équipement→récapitulatif→confirmation
│ └─ flux secondaire : recherche-réservation → modification-réservation
▼ un encapsuleur de récupération (clé d'appareil + URL de base hors ligne de bascule)
/api/kiosk/booking/{create,lookup,add-items,edit} ← toutes les décisions de confiance
▼ Couture KioskBackend : tarification serveur · promotion · verrous de stock (TTL 15 min)
re-vérification transactionnelle de capacité · paiement au comptoir/en ligne · webhook
temps réel : location.lastBookingChangeAt → re-récupération silencieuse → REFRESH_SLOT
Faits critiques
- Les tapements de l'utilisateur naviguent ; les rafraîchissements en arrière-plan jamais.
SET_SLOTvsREFRESH_SLOTest la différence entre une disponibilité en direct et le fait de téléporter un client depuis l'écran récapitulatif en plein achat. - Le serveur fixe tous les prix. Aucune information monétaire ne traverse le câble en entrée ; le total client est un aperçu.
- Le paiement au comptoir est la voie de résilience — la réservation se confirme avec
PENDING_COUNTER_PAYMENT, aucune intégration de paiement dans la boucle ; le paiement en ligne sur un kiosque signifie un QR code que le client scanne, sans jamais faire naviguer le kiosque ailleurs. - Chaque saisie de texte ouvre le clavier virtuel et définit
inputMode="none". L'un sans l'autre rend l'écran inutilisable. - Les verrous de stock sont réservés avec TTL (15 min) et libérés sur chaque chemin d'échec — le job de nettoyage est le filet de sécurité, pas le mécanisme.
- Le sessionId client est la clé d'idempotence. Double tap, nouvelle tentative, réponse perdue : au plus une réservation.
Règles strictes
Ne jamais persister l'état de session du kiosque. Le client suivant ne doit pas voir le nom du précédent. En mémoire + réinitialisation après 120 s d'inactivité + 30 s après confirmation, vérifié sur le matériel.
Ne jamais faire confiance au client pour les prix, la capacité ou la validité des promos. Le serveur calcule chaque montant et répond à une promo invalide avec
PROMO_INVALID; un client à un kiosque n'a aucun moyen de vérifier le montant.
Un seul encapsuleur de récupération pour chaque requête du kiosque. L'encapsuleur porte l'en-tête de l'appareil, l'enveloppe d'erreur et l'URL de base de bascule, de sorte que l'authentification, les erreurs et la bascule hors ligne s'appliquent à chaque requête en une fois.
Si la clé d'appareil est configurée, un en-tête manquant est une erreur 401. Un rejet-uniquement- sur-mauvaise-clé équivaut à aucune authentification.
Libérer les verrous de stock sur chaque chemin d'échec après les avoir acquis. Une erreur 409 qui conserve la réservation fige le stock pendant toute la durée du TTL.
Démarrage rapide
- Lisez state-machine.md ; implémentez le réducteur et le fournisseur, exécutez leur suite de tests.
- Construisez les écrans selon le contrat dans screens.md avec le système de conception de l'hôte — clavier, minuteries, durcissement tactile.
- Implémentez les routes à partir de api-contract.md sur la couture booking-backend.md.
- Câblez la fraîcheur + la bascule hors ligne conformément à realtime-offline.md.
- Déployez et effectuez un test de fumée conformément à operations.md.
Contrat d'adaptation
| Couture | Cette compétence fournit | L'hôte fournit |
|---|---|---|
| Entités de domaine | service/station/équipement/consommable + table de renommage | son vocabulaire (court, kart, poste de travail…) |
| Périmètre locataire | locationId dans l'URL du kiosque, vérifié par le serveur | son modèle de lieu/site |
| Authentification appareil | contrat x-kiosk-api-key | gestion des clés ; tokens optionnels par appareil |
| Accès aux données | interface KioskBackend ; référence Firestore + esquisse SQL | son ORM/SDK |
| Paiements | statut de comptoir + contrat session-de-paiement/webhook | Stripe ou équivalent |
| Temps réel | interface SubscribeFreshness | Firestore/Supabase/SSE/polling |
| Hors ligne | contrat NetworkStatus | serveur LAN (island-mode-server) ou aucun |
| Primitives UI | structure, états, règles d'interaction | boutons, dialogue, spinner, aspect |
| Style | intention de mise en page, cibles tactiles, un jeton --primary | son système de conception |
| Chaînes | arbre de clés de dictionnaire, toutes les clés requises | ses fichiers i18n, toutes les locales |
| Validation | gardes sans dépendances | sa bibliothèque de schémas, le cas échéant |
Répertoire de références
| Scénario | Mots-clés déclencheurs | Référence |
|---|---|---|
| État, étapes, réducteur, session, tests | étape, réducteur, GO_BACK, REFRESH_SLOT, sessionId, réinitialisation | state-machine.md |
| Écrans, clavier, minuteries, tactile, clés i18n | clavier virtuel, inactivité, compte à rebours, QR, cible tactile, dictionnaire | screens.md |
| Routes, authentification, validation, idempotence, erreurs | x-kiosk-api-key, 401, 409, idempotence, PROMO_INVALID, recherche, PII | api-contract.md |
| Capacité, stock, paiements, webhook, crons | transaction, verrou de stock, TTL, PENDING_COUNTER_PAYMENT, webhook, remboursement | booking-backend.md |
| Actualisation en direct, mise en cache, bascule hors ligne | lastBookingChangeAt, onSnapshot, s-maxage, bannière hors ligne, LAN, sondage de santé | realtime-offline.md |
| Déploiement, contrôle, surface opérateur | Edge --kiosk, accès assigné, battement de cœur, barrière de fonctionnalité, test de fumée | operations.md |
| Pourquoi les modèles diffèrent de l'implémentation antérieure | audit, grand livre, conservé délibérément, ajouté | provenance.md |