Skip to content

Commit 14a4757

Browse files
chore: sync II spec to dfinity/internet-identity release-2026-09-11 (#393)
## Summary Automated sync of the Internet Identity specification from `dfinity/internet-identity`. **Release:** `release-2026-09-11` (pinned from `583ad16` → `3cd91d62`) **Changed upstream files:** - `src/internet_identity/internet_identity.did` - Ran `npm run sync:ii-spec` — regenerated `docs/references/internet-identity-spec.md` and `docs/references/verifiable-credentials-spec.md` - Build passed ✓ ## Checklist - [ ] Review the diff to `docs/references/internet-identity-spec.md` for content changes - [ ] Review the diff to `docs/references/verifiable-credentials-spec.md` for content changes - [ ] Check for new absolute `internetcomputer.org` link patterns (script exits non-zero if any were missed) - [ ] Verify any renamed or restructured sections are reflected correctly ## Sync recommendation `sync from dfinity/internet-identity — docs/ii-spec.mdx, docs/vc-spec.md, src/internet_identity/internet_identity.did` Co-authored-by: pr-automation-bot-public[bot] <pr-automation-bot-public[bot]@users.noreply.github.com>
1 parent ab609fa commit 14a4757

3 files changed

Lines changed: 194 additions & 2 deletions

File tree

‎.sources/VERSIONS‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@
3939
# -------------------------------------------------------
4040

4141
motoko v1.16.0 a2d0b69
42-
internetidentity release-2026-08-28 583ad166
42+
internetidentity release-2026-09-11 3cd91d62

‎.sources/internetidentity‎

Submodule internetidentity updated 136 files

‎public/references/internet-identity.did‎

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,169 @@ type IdentityAuthnInfo = record {
10061006
recovery_authn_methods : vec AuthnMethod;
10071007
};
10081008

1009+
// Which browser a sign-in came from, as a token rather than a name to show. Products
1010+
// get renamed — "Chrome OS" became "ChromeOS", "Mac OS X" became "macOS" — so the name
1011+
// the user reads is derived in the frontend, where a rename reaches every stored record
1012+
// at once. "Brand" is what the client hints call this, and BrowserInfo below is the
1013+
// entry it describes.
1014+
type BrowserBrand = variant {
1015+
Chrome; Safari; Firefox; Edge; Opera; SamsungInternet;
1016+
// A browser this list does not name, shown as the client resolved it. Worth seeing
1017+
// rather than hiding behind a generic label. Named variants are the six that hold
1018+
// 97% of the web between them, because a variant is what earns an icon.
1019+
Other : text;
1020+
};
1021+
1022+
type OperatingSystem = variant {
1023+
Macos; Ios; Ipados; Windows; Android; ChromeOs; Linux; Other : text;
1024+
};
1025+
1026+
// Reported where the client can state it and inferred where it cannot, so unknown is a
1027+
// real answer: the browsers exposing no client hints are the ones this is least sure of.
1028+
type FormFactor = variant { Desktop; Mobile; Tablet; Unknown };
1029+
1030+
// What a browser reported about itself when it registered. Self-reported, so it is
1031+
// something the user reads to recognise their own browser rather than evidence about
1032+
// where a session came from. The canister stores these and never interprets them.
1033+
type BrowserDescription = record {
1034+
brand : BrowserBrand;
1035+
os : OperatingSystem;
1036+
form_factor : FormFactor;
1037+
// The hardware, where the client can name it — Android is the only place that does.
1038+
model : opt text;
1039+
};
1040+
1041+
type BrowserInfo = record {
1042+
id : nat32;
1043+
// Fixed at registration. A sign-in reporting something else registers its own entry,
1044+
// so this describes a registration rather than the last sign-in.
1045+
description : BrowserDescription;
1046+
created_at : Timestamp;
1047+
// Advanced by a sign-in from this browser and by every session refresh it drives.
1048+
last_used : Timestamp;
1049+
// Sessions this browser holds. Zero means it is signed in to nothing.
1050+
session_count : nat32;
1051+
};
1052+
1053+
type PrepareAccountSessionRequest = record {
1054+
identity_number : UserNumber;
1055+
origin : FrontendHostname;
1056+
account_number : opt AccountNumber;
1057+
// The II frontend's own public key.
1058+
session_key : SessionKey;
1059+
// What this browser is, for the user's session list.
1060+
browser_description : BrowserDescription;
1061+
// The browser's own public key, DER-encoded, as the registry currently holds it. A
1062+
// key this anchor has not seen registers a browser under it.
1063+
current_browser_key : PublicKey;
1064+
// What the browser rotates to once this sign-in succeeds. Must differ from
1065+
// current_browser_key: a browser that never rotates keeps a leaked key useful.
1066+
next_browser_key : PublicKey;
1067+
// Signature over session_key and next_browser_key, verified with current_browser_key.
1068+
current_browser_key_signature : blob;
1069+
// Signature by next_browser_key over session_key and current_browser_key, proving the
1070+
// browser holds the key it is announcing.
1071+
next_browser_key_signature : blob;
1072+
// The consented access level, fixed for the session's life.
1073+
permissions : opt Permissions;
1074+
// Clamped to the session maximum.
1075+
valid_for : opt nat64;
1076+
// How long the session may go unminted before it is over, clamped to between
1077+
// 10 minutes and the session's own granted length. Absent leaves the
1078+
// canister's own default.
1079+
max_idle : opt nat64;
1080+
};
1081+
1082+
type PrepareAccountSessionResponse = record {
1083+
user_key : PublicKey;
1084+
// The session's valid_till.
1085+
expiration : Timestamp;
1086+
// Names the session this ceremony created, and is what get_account_session is given
1087+
// to collect the delegation signed for it. Not a credential: it names a session, it
1088+
// does not authorise one.
1089+
session_id : nat64;
1090+
// Which browser this sign-in was attributed to, so the settings list can mark the one
1091+
// the user is looking at, and so the browser knows which registration its key now
1092+
// belongs to. Not a credential: a caller never presents it.
1093+
browser_id : nat32;
1094+
// The principal apps see for this account, so the frontend can tell its own
1095+
// sessions apart without minting a delegation to learn it.
1096+
account_principal : principal;
1097+
};
1098+
1099+
type GetAccountSessionRequest = record {
1100+
identity_number : UserNumber;
1101+
origin : FrontendHostname;
1102+
account_number : opt AccountNumber;
1103+
session_key : SessionKey;
1104+
expiration : Timestamp;
1105+
// The session prepare_account_session created.
1106+
session_id : nat64;
1107+
};
1108+
1109+
type GetAccountSessionResponse = record {
1110+
signed_delegation : SignedDelegation;
1111+
};
1112+
1113+
type AccountSessionError = variant {
1114+
Unauthorized : principal;
1115+
NoSuchAccount;
1116+
NoSuchSession;
1117+
// The session is there, but no delegation was signed for the session_key and
1118+
// expiration asked for. Ask again with the ones prepare_account_session returned;
1119+
// signing in afresh is not the remedy.
1120+
NoSuchDelegation;
1121+
// The browser's key is unusable, or its signature does not verify against it.
1122+
InvalidBrowserKey;
1123+
// The browser presented a key it has already rotated away from, which happens when it
1124+
// never learned that its last sign-in succeeded. It holds the successor that does
1125+
// resolve, so the answer is to promote that one and present it.
1126+
StaleBrowserKey;
1127+
InternalCanisterError : text;
1128+
};
1129+
1130+
type AppPrepareDelegationRequest = record {
1131+
// The key the app delegation delegates to. Nothing about the account is named:
1132+
// the caller's own session chain is what identifies it.
1133+
session_key : SessionKey;
1134+
};
1135+
1136+
type AppPrepareDelegationResponse = record {
1137+
user_key : PublicKey;
1138+
expiration : Timestamp;
1139+
};
1140+
1141+
type AppGetDelegationRequest = record {
1142+
session_key : SessionKey;
1143+
// Must match the prepared value.
1144+
expiration : Timestamp;
1145+
};
1146+
1147+
1148+
type RevokeBrowserSessionsRequest = record {
1149+
identity_number : UserNumber;
1150+
browser_id : nat32;
1151+
};
1152+
1153+
type SessionRevokeError = variant {
1154+
Unauthorized : principal;
1155+
// Raised before the sweep writes anything, so a browser is never left signed out of
1156+
// some of its applications and not others.
1157+
InternalCanisterError : text;
1158+
};
1159+
1160+
type AppSessionError = variant {
1161+
// No usable session behind this caller: revoked, expired, pruned, or never one at
1162+
// all. One outcome, because which of those it is depends on whether a prune has run
1163+
// yet, and because an app can act on none of them differently.
1164+
NoSuchSession;
1165+
// The session is live, but nothing was signed for the session_key and expiration
1166+
// asked for — so the expiration is one app_prepare_delegation never returned. Prepare
1167+
// again and use what comes back; signing in afresh is not the remedy.
1168+
NoSuchDelegation;
1169+
InternalCanisterError : text;
1170+
};
1171+
10091172
type IdentityInfo = record {
10101173
authn_methods : vec AuthnMethodData;
10111174
authn_method_registration : opt AuthnMethodRegistrationInfo;
@@ -1026,6 +1189,10 @@ type IdentityInfo = record {
10261189
// shows a "limit reached" notice in the wizard when adding
10271190
// beyond the cap.
10281191
verified_emails : opt vec VerifiedEmail;
1192+
// Browsers this anchor has signed in from (absent when it has never
1193+
// created a session), so the Settings UI can offer "sign this browser
1194+
// out" without a separate call.
1195+
browsers : opt vec BrowserInfo;
10291196
// The anchor's synced trusted-MCP-server config (absent when the
10301197
// anchor never wrote one). Carried here rather than read from the
10311198
// mcp_get_config query so the Settings UI has a certified value to
@@ -1856,6 +2023,31 @@ service : (opt InternetIdentityInit) -> {
18562023
update : AccountUpdate
18572024
) -> (variant { Ok : AccountInfo; Err: UpdateAccountError });
18582025

2026+
// Creates or reuses a revocable session at one account and signs its identity to
2027+
// the II frontend's own key. Called only by the II frontend, which ships with the
2028+
// canister; requires an anchor access method, so a session can neither spawn nor
2029+
// extend itself.
2030+
prepare_account_session : (PrepareAccountSessionRequest) -> (variant { Ok : PrepareAccountSessionResponse; Err : AccountSessionError });
2031+
get_account_session : (GetAccountSessionRequest) -> (variant { Ok : GetAccountSessionResponse; Err : AccountSessionError }) query;
2032+
2033+
// Mints a short-lived app delegation from a live session. Called by app frontends
2034+
// with the session chain, so revoking the session ends access within one delegation
2035+
// lifetime.
2036+
app_prepare_delegation : (AppPrepareDelegationRequest) -> (variant { Ok : AppPrepareDelegationResponse; Err : AppSessionError });
2037+
app_get_delegation : (AppGetDelegationRequest) -> (variant { Ok : SignedDelegation; Err : AppSessionError }) query;
2038+
2039+
// Signs the calling session out. A session that is already gone is success, so a
2040+
// client that retries, or that signs out twice, does not have to reason about whether
2041+
// its session was still there. An app can revoke only its own session.
2042+
app_revoke_session : () -> (variant { Ok; Err : AppSessionError });
2043+
// Whether the calling session is still usable. For the II frontend's silent
2044+
// re-auth path, which must decide whether it can answer without rendering
2045+
// anything. Advisory: a query reply is not certified, and every mint enforces
2046+
// the same conditions regardless of the answer here.
2047+
check_session : () -> (bool) query;
2048+
2049+
revoke_browser_sessions : (RevokeBrowserSessionsRequest) -> (variant { Ok; Err : SessionRevokeError });
2050+
18592051
prepare_account_delegation : (
18602052
anchor_number : UserNumber,
18612053
origin : FrontendHostname,

0 commit comments

Comments
 (0)