fix(ST-1007): listen for SSE 'state' event so approve-during-connect resolves
De SSE-route in ST-1004 stuurt de catch-up payload als `event: state\ndata: …` om een race te dichten: tussen pair/start en SSE-open kan de mobiel approven, de pg_notify fired vóór onze LISTEN actief is en gaat verloren (Postgres queuet niet). De server compenseert door direct na connect een `state`-event te sturen met de huidige status uit de DB. Maar de client luisterde alleen op 'message'. EventSource routeert events met `event: <name>` enkel naar listeners voor die exacte naam — het catch-up event werd dus genegeerd. Gevolg bij een (zeldzame) race: QR blijft hangen tot expiry omdat noch de notify noch de catch-up doorkomt. Fix: dezelfde onMessage-handler ook aan 'state' binden (en netjes unsubscriben bij cleanup). Geen server-side wijziging nodig — protocol bleef bewust om de semantische scheiding 'initial state' vs 'live notify' te behouden voor toekomstige clients die er onderscheid in willen maken. Severity: middel-laag — kleine race-window, geen data/security-impact, alleen "QR doet niks" tot user op Vernieuwen klikt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5cbf543c16
commit
d6e71f915c
1 changed files with 9 additions and 0 deletions
|
|
@ -106,11 +106,20 @@ export function QrLoginButton() {
|
|||
// Geen actie nodig tenzij we definitief willen falen.
|
||||
}
|
||||
|
||||
// De server stuurt direct na connect een `event: state`-payload met de
|
||||
// huidige pairing-status (catch-up voor de race tussen pair/start en de
|
||||
// SSE-open: als de mobiel net daarvoor approvet komt de notify door
|
||||
// vóórdat onze LISTEN actief is en wordt 'ie verloren). EventSource
|
||||
// routeert events met `event: <name>` alleen naar listeners voor die
|
||||
// naam — niet naar 'message'. Dezelfde handler aan beide hangen vangt
|
||||
// de catch-up én reguliere notifies op.
|
||||
es.addEventListener('message', onMessage)
|
||||
es.addEventListener('state', onMessage as unknown as EventListener)
|
||||
es.addEventListener('error', onError)
|
||||
|
||||
return () => {
|
||||
es.removeEventListener('message', onMessage)
|
||||
es.removeEventListener('state', onMessage as unknown as EventListener)
|
||||
es.removeEventListener('error', onError)
|
||||
es.close()
|
||||
sseRef.current = null
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue