Skip to content

One-time phone client: WebCrypto and the socket's open have no deadline #914

Description

@nedtwigg

Code: #handshake and #race in lib/src/remote/client/one-time-client.ts.

Failure path: connectOnce computes the room's hard deadline (expiry * 1000 + ONE_TIME_EXPIRY_GRACE_MS), but only #core.exchange and #core.exchangeControl enforce it. The steps before them, generateNoiseKeyPair, createNoiseInitiator, writeMessage and #openRendezvous, go through #race, which a failure or close() can interrupt but no timer can. A WebCrypto call that never settles, or a WebSocket that stays CONNECTING, leaves the page on its code screen with no ending. It ends only when the browser gives up on the socket or the person taps Cancel. one-time.md's failure table promises ONE_TIME_LINK_EXPIRED_MESSAGE for "no answer by the room's deadline".

Suggested fix: in connectOnce, arm one timer at the room's hard deadline that calls #fail(ONE_TIME_LINK_EXPIRED_MESSAGE), and clear it at the switch or in #teardown. #race then covers the WebCrypto and socket-open waits as well. To test it, stub createWebSocket with a socket that never opens, advance the clock past the deadline, and assert the expired copy.

Found while trimming #904, which had parked this as a spec "Known gap".

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions