feat(be): sign a session to the II frontend at sign-in - #4268
Open
sea-snake wants to merge 4 commits into
Open
Conversation
This was referenced Aug 22, 2026
sea-snake
marked this pull request as ready for review
August 22, 2026 18:16
|
✅ No security or compliance issues detected. Reviewed everything up to a899c6b. Security Overview
Detected Code Changes
|
sea-snake
force-pushed
the
feat/sign-in-creates-a-session
branch
from
August 22, 2026 18:44
8a56cdc to
afa4f93
Compare
sea-snake
force-pushed
the
feat/sign-in-creates-a-session
branch
from
August 22, 2026 19:06
afa4f93 to
1ab21d9
Compare
sea-snake
force-pushed
the
feat/sign-in-creates-a-session
branch
from
August 22, 2026 19:25
1ab21d9 to
b0ccd19
Compare
`prepare_account_session` creates a session and signs its delegation to the frontend's key; `get_account_session` witnesses it. This is what gives the storage beneath a caller, so the `allow(dead_code)` it carried goes with it. The request carries the browser's key, the successor it rotates to, and both proofs, which are checked before anything is written. So is the account: an account the identity does not hold is the one failure a caller can provoke, and returning it after the writes would leave a browser registered for a sign-in that never happened. Every failure after the first write traps instead, rolling the whole message back, because on the IC returning an error commits. `valid_for` is the lifetime the user chose at consent, clamped by the canister to between ten minutes and thirty days. Every ceremony creates, so it always applies: the replacement's expiry is measured from the ceremony that made it, and no session is renewed in place. This is a separate pair from `prepare_account_delegation`, not an option on it. Both mint, but one proves a live session and identifies the account by its principal while the other proves an access method and names the anchor outright. Merging them would mean one method with two authorizers and two argument shapes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
sea-snake
force-pushed
the
feat/sign-in-creates-a-session
branch
from
August 22, 2026 19:49
b0ccd19 to
302a89d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Design: #4224. Overview: #4230. This is the caller #4266 and #4264 were waiting for, so it removes their
#[allow(dead_code)]annotations.prepare_account_session/get_account_session. The first creates a session and signs its delegation to the II frontend's key; the second witnesses it. A separate pair fromprepare_account_delegation, not an option on it: both mint, but one proves a live session and identifies the account by its principal while the other proves an access method and names the anchor outright. Merging them would mean one method with two authorizers and two argument shapes, and would drag the frontend's internal surface into the public API.The browser proof is checked before anything is written, using the verifier from #4264. So is the account: an account the identity does not hold is the one failure a caller can provoke, and returning it after the writes would leave a browser registered for a sign-in that never happened.
Every later failure traps rather than returning. On the IC, returning an error commits state and only a trap rolls the message back, so once the browser registration is written a failure has to trap or a caller could be told "no" and still have a browser enrolled.
valid_foris the lifetime the user chose at consent, clamped by the canister to between 10 minutes and 30 days. Every ceremony creates, so it always applies: the replacement's expiry is measured from the ceremony that made it, and no session is renewed in place.Tests:
integration/sessions.rs(18) drives the real ceremony — creating and verifying a session, a request for another identity refused, the registry cap dropping the least recently used and ending its sessions, the key proof's rejections at the endpoint, rotation keeping the entry, a retired key returning as a new browser, and the registration archived with the name redacted.