Skip to content

feat(sso): let a withdrawal reach the paired host that is serving it - #933

Merged
decrypto21 merged 6 commits into
mainfrom
nidish/sso-request-cancellation
Sep 23, 2026
Merged

decrypto21 merged 6 commits into
mainfrom
nidish/sso-request-cancellation

Conversation

@decrypto21

Copy link
Copy Markdown
Contributor

Part of #926.

A pairing host whose caller withdraws a request it has already published tells the paired host, so the phone stops prompting or allocating for a product that has stopped waiting. The design is in docs/rfcs/sso-request-cancellation.md.

  • The message. Cancel(Withdrawal { message_id }) is appended to v1::RemoteMessage at index 24. #[sso_service] generates its dispatch and name() arms beside Disconnected. Existing SCALE bytes and fixtures are unchanged, and WIRE_CODEC_VERSION does not move.
  • When the pairing host sends it. Only when the caller withdrew the request; a host timeout sends nothing. It goes alone in its own request statement, fire-and-forget, spawned so the call's unwind grace cannot drop it. The store keeps one statement per channel, so a Cancel replaces its target. It is sent only while its target is the newest statement built on the session's request channel, which is recorded and checked under one lock with every build on that channel, including Disconnected.
  • The Rust responder. serve_session feeds decoded pages to serve_pages, which serves requests one at a time and keeps reading, at most 64 ahead. A Cancel fires the running request's token, or stops a queued or not-yet-seen one from starting (up to 64 remembered). A withdrawn request posts no response and is recorded as handled in the replay ledger. A subscription error lets the request being served finish before the loop reports it.
  • Handlers. Confirmation prompts race the token, and resource allocation checks it before each resource, next to the session check.
  • Native. handle_sso_request accepts Cancel at any time and answers the withdrawn request Ignored. SsoRequestOutcome and the UniFFI surface are unchanged.
  • Macro. dispatch takes the context the caller built for the message, so the caller owns its cancellation.

A peer that predates Cancel logs it and serves the request as before; the Rust responder, iOS and Android were each checked for that.

Not in this PR

  • iOS queues every SSO message behind the one it is serving, so a Cancel reaches the core too late there. Its dispatcher needs to pass Cancel through (polkadot-ios-community).
  • Android runs its own Kotlin SSO stack and needs its own Cancel handling (polkadot-android-community).
  • The wasm bridge passes no AbortSignal, so a browser host keeps its prompt until answered; the answer authorizes nothing.
  • Cancel is not yet listed in the host-spec divergence D-B.5.6 the v1.rs header links.

Testing. New tests cover a Cancel withdrawing an open prompt, one arriving before its request, one read while its target is served, a subscription failure mid-request, the early-withdrawal cap, the pairing host sending Cancel, not sending it with a newer request behind, and not sending it on timeout. Each was mutation-checked by removing the line it guards and confirming that test fails. The macro's trybuild output is identical to main's.

@decrypto21
decrypto21 requested a review from a team September 23, 2026 12:35
@github-actions github-actions Bot added documentation Improvements or additions to documentation rfc labels Sep 23, 2026
@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

CI Status: 23 required jobs green, 21 passed and 2 skipped by path filter.

All job results
job result
android-bindings success
changes success
changeset-guard success
cli-package success
codegen success
e2e skipped
explorer success
headless-install success
host-android-bindings success
host-android-detekt success
host-wasm success
ios-bindings success
ios-swift success
licenses success
playground success
provider-android-bindings success
release-guard success
rust success
ts-client success
ts-debugger success
ts-host success
wasm-provider success
workflow-lint skipped

Signing credentials: null as of null, a release may fail

Commit 9c15ac32 · run log

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

iOS simulator preview

Built from 9c15ac328, stamped with it in TrUAPICommit.

gh run download 35920228753 --name simulator-preview-9c15ac328
unzip polkadot-app-*.app.zip
xcrun simctl install booted polkadot-app.app
xcrun simctl launch booted io.parity.polkadotapp.develop

Or download it in a browser, which arrives as a zip wrapping
the .app.zip, so it needs unzipping twice.

An arm64 simulator slice, so it needs an Apple Silicon Mac and does not
install on a device. Kept for 14 days, after which the link stops
resolving and a new push rebuilds it.

@TarikGul TarikGul left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approving. checked the wire change is append only with explicit indices and that main's decoder ignores an unknown statement and keeps the session, and pulled four of the guards out one at a time with every one failing a test. the send guard recording and building under one lock is the right call, and so is keying the send on Cancelled rather than any fired token.

Comment thread rust/crates/truapi-server/src/runtime/sso_service.rs Outdated
Comment thread rust/crates/truapi-server/src/runtime/signing_host/sso_responder.rs
@github-actions github-actions Bot added the rust Pull requests that update rust code label Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation rfc rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants