ADR-0026: Anmeldung am Tisch mit dem Handy, über einen QR-Code pro Seite¶
- Status: accepted
- Datum: 2026-10-14
- Betrifft: Schnittstellen, Oberfläche, Konfiguration
- Bezug: setzt
0024-angemeldete-matches-ohne-operatorfür den Handy-Weg um, wie0025-fob-als-identitaetes für den Fob getan hat. Issue #329, stuttgart-things/zaehlwerk#116 (die andere Seite), stuttgart-things/zaehlwerk#92.
Kontext¶
ADR-0024 zählt zwei Wege als Nachweis, dass ein Spieler am Tisch steht: den Fob am Leser und das eigene, angemeldete Handy. Der Fob-Weg ist gebaut (#321, zaehlwerk#110). Für das Handy gibt es noch keine Route. ADR-0024 verlangt nur, dass die Anmeldung hier entsteht und nicht im Zählwerk.
Am Fob-Weg fragt das Zählwerk: Es liest eine UID und will wissen, wem sie gehört. Beim Handy ist es umgekehrt. Wer der Spieler ist, weiß diese Anwendung bereits aus dem Cookie. Das Zählwerk weiß davon nichts, bis man es ihm sagt.
Ein NFC-Aufkleber auf der Handyhülle ist kein dritter Weg. Für den Leser ist er ein Fob, und gekoppelt wird er wie einer (ADR-0025). Dafür braucht es nichts Neues.
Entscheidung¶
An jeder Tischseite hängt ein QR-Code. Er öffnet eine Seite dieser Anwendung. Dort bestätigt der angemeldete Spieler mit einem Knopf. Diese Anwendung legt die Anmeldung an und meldet sie danach selbst ans Zählwerk.
Der Weg¶
- Der QR-Code der linken Seite zeigt auf
/table/left, der der rechten auf/table/right. Gedruckt wird er auf/qr, neben dem Code, den es dort schon gibt. - Die Seite braucht einen angemeldeten Spieler. Wer auf diesem Handy noch nicht angemeldet ist, bekommt einen Link zur Anmeldung und scannt den Code danach noch einmal. Ein Rücksprung nach der Anmeldung wäre bequemer, aber Anmelden und Beitreten sind Fragmente der Startseite, und das passiert einmal pro Handy.
- Erst der Knopf meldet an, ein Aufruf des Links allein nicht. Der Knopf schickt einen POST. Vorschauen in Messengern, ein Scan im Vorbeigehen oder ein zweiter Tab legen also nichts an.
- Der POST legt eine Zeile in
checkinsan, mitmethod = 'phone'und der Seite. Danach ruft diese Anwendung das Zählwerk auf: „Spieler X mit Anmeldung Y belegt die linke Seite." - Die Seite zeigt die Antwort des Zählwerks in Worten: angemeldet, das Match startet, am Tisch läuft gerade ein Match, Zählwerk nicht erreichbar.
Ab da ist alles wie beim Fob. Sind beide Seiten belegt, startet das Zählwerk
das Match. Das Ergebnis kommt mit beiden Anmeldungen und ohne Operator zurück,
und POST /api/results prüft sie wie in ADR-0024. Eine Seite per Fob und die
andere per Handy ist ein gewöhnlicher Fall.
Die Kopplung¶
- Neu ist die Richtung. Bisher ruft nur das Zählwerk hier an. Jetzt ruft diese Anwendung auch das Zählwerk auf, und zwar an genau einer Stelle: wenn ein Spieler den Knopf drückt.
SP_ZAEHLWERK_URLgibt es schon. Über diese Adresse liest der Browser auf der Startseite den laufenden Spielstand. Dieselbe Adresse gilt jetzt auch für den Aufruf vom Server aus. Eine zweite Variable für dasselbe Gerät würde früher oder später auf ein anderes zeigen. Erreicht der Server die Adresse nicht, die der Browser benutzt, ist das ein Fehler in der Einrichtung, und die Seite sagt „Zählwerk nicht erreichbar".- Eingeschaltet ist es nur mit Adresse und Token zusammen. Fehlt eines
von beiden, gibt es
/table/*nicht,/qrdruckt keine Tischcodes, und beim Start steht eine Zeile im Log, die das sagt. So ist es auch beiSP_SCOREBOARD_TOKENundSP_RFID_UID_KEY(Invariante 2). - Das Geheimnis ist das, das beide Seiten schon teilen. Diese Anwendung
schickt
SP_SCOREBOARD_TOKENals Bearer, also dasselbe Token wie bisher, nur in die andere Richtung. Ein zweites Geheimnis müsste man verteilen, im Vault ablegen und rotieren, und es würde nichts schützen, was das erste nicht schützt: Wer es hat, kann ohnehin schon Ergebnisse eintragen. - Der Aufruf wartet kurz und wird nicht wiederholt. Antwortet das Zählwerk nicht, sagt die Seite das, und der Spieler drückt noch einmal. Eine Schleife, die im Hintergrund weiterversucht, würde einen Spieler anmelden, der längst gegangen ist.
- Das Zählwerk prüft nicht nach, und das muss es auch nicht. Es bekommt
Spieler und Anmeldung von der Stelle, die beide angelegt hat. Ob die Angaben
stimmen, prüft
POST /api/resultsohnehin noch einmal, bevor ein Ergebnis angenommen wird.
Was bleibt, wenn es schiefgeht¶
- Das Zählwerk lehnt ab oder ist nicht erreichbar: Die Anmeldung bleibt
als unbenutzte Zeile stehen. Allein beweist sie nichts, nach drei Stunden
trägt sie kein Ergebnis mehr (
checkin.Validity), und aufgeräumt werden muss nichts. Eine Zeile zu löschen, die einmal angelegt wurde, würde die Spur entfernen, dass jemand es versucht hat. - Ein Beobachter meldet sich nicht an (ADR-0022). Die Seite sagt das, und es entsteht keine Zeile.
- Zweimal tippen: Pro Spieler gilt ein Ratenlimit. Doppelt angelegte Zeilen schaden aber auch nicht, denn das Zählwerk ersetzt eine Anmeldung desselben Spielers auf derselben Seite durch die neuere.
Warum nicht anders¶
Der QR-Code öffnet eine Seite des Zählwerks. Das Zählwerk kennt keine Spieler und hat keine Sitzung. Es müsste den Spieler hierher schicken und wieder zurückholen. Die Anmeldung entstünde dann dort, wo ADR-0024 sie nicht haben will.
Das Handy spricht selbst mit dem Zählwerk. Dann bräuchte das Handy ein Geheimnis für das Zählwerk, oder das Zählwerk würde jedem glauben, der eine Spieler-ID schickt. Beides ist schlechter als ein Aufruf zwischen zwei Servern, die einander schon kennen.
Ein wechselnder Code auf dem Panel des Zählwerks statt eines festen QR-Codes. Wer den festen Link kennt, kann sich auch von außerhalb des Raums anmelden. Dagegen hilft nur ein Code, der sich ändert und nur am Tisch zu sehen ist. Das ist aber ein eigenes Stück Arbeit im Zählwerk und auf dem Panel. Der Schaden, den es verhindert, ist klein:
- Man kann nur sich selbst anmelden, nie einen Kollegen.
- Ein Match startet erst, wenn auch der Gegner angemeldet ist.
- Eine einzelne Anmeldung verfällt im Zählwerk nach wenigen Minuten.
Der wechselnde Code kommt, wenn sich zeigt, dass jemand den festen Link missbraucht.
Ein GET meldet an. Das spart einen Knopf. Ein Link, der schon beim Aufrufen etwas anlegt, wird aber auch von Vorschauen, Prefetch und dem Verlauf des Browsers ausgelöst.
Konsequenzen¶
- Keine neue Variable.
SP_ZAEHLWERK_URLundSP_SCOREBOARD_TOKENgibt es schon, in Code, kcl, Terraform und Compose. Neu ist, dass beide zusammen die Tischseiten einschalten. Das gehört indocs/deployment.mdund inkcl/README.md. /qrbekommt zwei Codes, je einen pro Seite, zum Ausdrucken und Aufkleben.- Das Zählwerk braucht eine Route, über die diese Anwendung eine Seite belegt (zaehlwerk#116). Ihre genaue Form legt das Zählwerk in einer eigenen ADR fest. Diese Anwendung schickt Seite, Spieler-ID und Anmeldungs-ID, und der Rest folgt dem Fob-Weg.
- Die Anmeldung kann jetzt von zwei Wegen kommen.
checkins.methodkenntphoneschon seit der Migration für den Fob, also braucht es keine neue.
Was ausdrücklich wartet¶
- Der wechselnde Code (siehe oben).
- Mehrere Tische (#280): Dann trägt der Pfad den Tisch, also
/table/{tisch}/left, und die Anmeldung trägt ihn auch. - Name und PIN am Touch-Display (harvester#432). ADR-0024 zählt das als Nachweis, aber es ist ein anderes Gerät und bekommt eine eigene Entscheidung.