From 775ee9f88b6a0011d9c3a327d26e73d77b47d743 Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Wed, 10 Dec 2025 15:41:20 +0000 Subject: [PATCH 01/16] first --- src/internet_identity_frontend/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/internet_identity_frontend/README.md diff --git a/src/internet_identity_frontend/README.md b/src/internet_identity_frontend/README.md new file mode 100644 index 0000000000..8a8c1281bf --- /dev/null +++ b/src/internet_identity_frontend/README.md @@ -0,0 +1,5 @@ +This crate defines the new Internet Identity frontend (currently not used in production). + +The idea is to factor out the frontend part of the Internet Identity canister, so that the remaining +backend has a simpler Http API and the remaining frontend has a simpler Candid API. This will +make the development process more managable and better separate concerns. \ No newline at end of file From 32648d786eb2acd1baf2435f90b4011683b9a975 Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Wed, 10 Dec 2025 22:05:34 +0100 Subject: [PATCH 02/16] second --- Cargo.lock | 11 + Cargo.toml | 1 + dfx.json | 13 +- scripts/build | 73 ++++- src/frontend/src/lib/locales/de.po | 131 +++++++- src/frontend/src/lib/locales/en.po | 131 +++++++- src/frontend/src/lib/locales/es.po | 131 +++++++- src/frontend/src/lib/locales/id.po | 131 +++++++- src/internet_identity/Cargo.toml | 6 +- src/internet_identity_frontend/Cargo.toml | 22 ++ src/internet_identity_frontend/README.md | 2 +- .../internet_identity_frontend.did | 38 +++ src/internet_identity_frontend/src/http.rs | 281 ++++++++++++++++++ src/internet_identity_frontend/src/main.rs | 11 + 14 files changed, 947 insertions(+), 35 deletions(-) create mode 100644 src/internet_identity_frontend/Cargo.toml create mode 100644 src/internet_identity_frontend/internet_identity_frontend.did create mode 100644 src/internet_identity_frontend/src/http.rs create mode 100644 src/internet_identity_frontend/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 6d5c22a191..28c3ecc05e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2077,6 +2077,17 @@ dependencies = [ "sha2 0.10.9", ] +[[package]] +name = "internet_identity_frontend" +version = "0.1.0" +dependencies = [ + "candid", + "ic-cdk 0.16.0", + "ic-cdk-macros 0.16.0", + "internet_identity_interface", + "serde_bytes", +] + [[package]] name = "internet_identity_interface" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 524f703df6..9adfa34b19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "src/asset_util", "src/internet_identity", + "src/internet_identity_frontend", "src/canister_tests", "src/internet_identity_interface", "src/archive", diff --git a/dfx.json b/dfx.json index c3a673edd2..199cf40b3e 100644 --- a/dfx.json +++ b/dfx.json @@ -8,6 +8,13 @@ "init_arg": "(opt record { captcha_config = opt record { max_unsolved_captchas= 50:nat64; captcha_trigger = variant {Static = variant {CaptchaDisabled}}}; openid_google = opt opt record { client_id = \"775077467414-q1ajffledt8bjj82p2rl5a09co8cf4rf.apps.googleusercontent.com\" }; related_origins = opt vec { \"https://identity.internetcomputer.org\"; \"https://identity.ic0.app\" } })", "shrink": false }, + "internet_identity_frontend": { + "type": "custom", + "candid": "src/internet_identity_frontend/internet_identity_frontend.did", + "wasm": "internet_identity_frontend.wasm.gz", + "build": "bash -c 'II_DEV_CSP=1 II_FETCH_ROOT_KEY=1 II_DUMMY_CAPTCHA=${II_DUMMY_CAPTCHA:-1} scripts/build --frontend'", + "shrink": false + }, "test_app": { "type": "custom", "candid": "demos/test-app/test_app.did", @@ -20,7 +27,9 @@ "wasm": "demos/vc_issuer/vc_demo_issuer.wasm.gz", "build": "demos/vc_issuer/build.sh", "post_install": "bash -c 'demos/vc_issuer/provision'", - "dependencies": ["internet_identity"] + "dependencies": [ + "internet_identity" + ] } }, "defaults": { @@ -30,4 +39,4 @@ }, "dfx": "0.29.0", "version": 1 -} +} \ No newline at end of file diff --git a/scripts/build b/scripts/build index 5daf4e0381..d0e2110acc 100755 --- a/scripts/build +++ b/scripts/build @@ -18,12 +18,13 @@ function usage() { cat << EOF Usage: - $0 [--only-dependencies] [--internet-identity] [--archive] + $0 [--only-dependencies] [--internet-identity] [--archive] [--frontend] Options: --only-dependencies only build rust dependencies (no js build, no wasm optimization) --internet-identity build the internet_identity canister (alongside other specifically mentioned canisters), defaults to --internet-identity --archive build the archive canister (alongside other specifically mentioned canisters), defaults to --internet-identity + --frontend build the frontend (alongside other specifically mentioned canisters), defaults to --internet-identity EOF } @@ -61,6 +62,10 @@ do CANISTERS+=("archive") shift ;; + --frontend) + CANISTERS+=("frontend") + shift + ;; *) echo "ERROR: unknown argument $1" usage @@ -252,11 +257,77 @@ function build_internet_identity() { build_canister "internet_identity" ${extra_build_args[@]+"${extra_build_args[@]}"} } +function build_internet_identity_frontend() { + if [ "$ONLY_DEPS" != "1" ] + then + DIST_DIR="$SCRIPTS_DIR/../dist" + + # Compile frontend assets to dist + echo Compiling internet_identity frontend assets + npm run build + + # Add preload links for all css files in every html file + CSS_LINKS="" + TMP_HTML_FILE=$(mktemp) + while IFS= read -r css_file; do + css_file_relative="/${css_file#$DIST_DIR/}" + CSS_LINKS+="" + done < <(find "$DIST_DIR" -type f -name "*.css" | sort) + find "$DIST_DIR" -type f -name "*.html" | while read -r html_file; do + sed "s##${CSS_LINKS}#" "$html_file" > "$TMP_HTML_FILE" && mv "$TMP_HTML_FILE" "$html_file" + done + + # II canister only supports one content type per resource. + # That is why we only keep either compressed or uncompressed. + find "$DIST_DIR" -type f -name "*.gz" | while read -r gz_file; do + # Remove the .gz suffix to get the base filename + base_file="${gz_file%.gz}" + + # Generate the .br filename + br_file="${base_file}.br" + + # Delete the .br file if it exists + if [[ -f "$br_file" ]]; then + rm -f "$br_file" + fi + + # Keep files not ending in .js or .woff2 as uncompressed files + if [[ ! "$base_file" =~ \.(js|woff2)$ ]]; then + rm -f "$gz_file" + continue + fi + + # Delete the base file if it exists + if [[ -f "$base_file" ]]; then + rm -f "$base_file" + fi + done + fi + + # This enables the "dummy_captcha" feature which makes sure the captcha string + # is always "a". + # WARNING: this MUST be opt-in, because we DO NOT want this in production. + extra_build_args=() + + # This enables the "dev_csp" feature which weakens the content security policy to facilitate development. + # WARNING: this MUST be opt-in, because we DO NOT want this in production. + if [ "${II_DEV_CSP:-}" == "1" ] + then + echo "USING DEV CONTENT SECURITY POLICY" + extra_build_args+=( --features dev_csp ) + fi + # XXX: for bash > 4.4, empty arrays are considered unset, so do some substitution + build_canister "internet_identity_frontend" ${extra_build_args[@]+"${extra_build_args[@]}"} +} + for canister in "${CANISTERS[@]}" do if [ "$canister" == "internet_identity" ] then build_internet_identity + elif [ "$canister" == "frontend" ] + then + build_internet_identity_frontend else build_canister "$canister" fi diff --git a/src/frontend/src/lib/locales/de.po b/src/frontend/src/lib/locales/de.po index 3253c6a52f..93a8fae701 100644 --- a/src/frontend/src/lib/locales/de.po +++ b/src/frontend/src/lib/locales/de.po @@ -106,6 +106,9 @@ msgstr "Authentifizierung erfolgreich" msgid "Authorize new device" msgstr "Neues Gerät autorisieren" +msgid "Before you continue" +msgstr "" + msgid "By enabling this feature, you can create more than one account for a single app. Easily switch between accounts (e.g. work, personal, or demo)." msgstr "Wenn Sie diese Funktion aktivieren, können Sie mehr als ein Konto für eine einzelne App erstellen. Wechseln Sie einfach zwischen den Konten (z. B. Arbeit, Privat oder Demo)." @@ -124,6 +127,12 @@ msgstr "CAPTCHA-Zeichen" msgid "Characters are case-sensitive" msgstr "Groß- und Kleinschreibung beachten" +msgid "Checking recovery phrase" +msgstr "" + +msgid "Checking your order" +msgstr "" + msgid "Choose an account" msgstr "Wählen Sie ein Konto aus" @@ -139,6 +148,9 @@ msgstr "Methode auswählen" msgid "Clear all" msgstr "Alle löschen" +msgid "Click to reveal" +msgstr "" + msgid "Close" msgstr "Schließen" @@ -220,6 +232,9 @@ msgstr "Standard" msgid "Discoverable passkeys" msgstr "Entdeckbare Passkeys" +msgid "Do you want to continue?" +msgstr "" + msgid "Easy access" msgstr "Einfacher Zugang" @@ -235,6 +250,9 @@ msgstr "Mehrere Konten aktivieren" msgid "Enter characters" msgstr "Zeichen eingeben" +msgid "Enter each word in the correct order:" +msgstr "" + msgid "Enter your recovery phrase words in each box, spelled correctly and in order." msgstr "Geben Sie die Wörter Ihrer Wiederherstellungsphrase in jedes Feld ein, korrekt geschrieben und in der richtigen Reihenfolge." @@ -269,6 +287,12 @@ msgstr "Volle Eigentümerschaft" msgid "Generating code..." msgstr "Code wird generiert..." +msgid "Generating phrase..." +msgstr "" + +msgid "Get started" +msgstr "" + msgid "Give your identity a clear, simple, and memorable name you'll easily recognize." msgstr "Geben Sie Ihrer Identität einen klaren, einfachen und einprägsamen Namen, den Sie leicht erkennen." @@ -284,6 +308,9 @@ msgstr "Zur App gehen - (<0>{countdown})" msgid "Has not been used yet" msgstr "Noch nicht verwendet" +msgid "Have your recovery phrase ready before continuing. Keep it private. Don’t let anyone watch you enter it. You can reset it later in your dashboard if you want a new one." +msgstr "" + msgid "Help & FAQ" msgstr "Hilfe & FAQ" @@ -314,6 +341,15 @@ msgstr "So funktioniert's" msgid "How to stay secure" msgstr "So bleiben Sie sicher" +msgid "I Acknowledge" +msgstr "" + +msgid "I am responsible for my recovery phrase and it cannot be retrieved from Internet Identity if lost." +msgstr "" + +msgid "I have written it down" +msgstr "" + msgid "Identity already upgraded" msgstr "Identität bereits aktualisiert" @@ -332,9 +368,15 @@ msgstr "Wenn Sie fortfahren, können Sie sich nicht mehr mit Ihrem {name}-Konto msgid "In use on another account." msgstr "Wird auf einem anderen Konto verwendet." +msgid "Incorrect recovery phrase. Please try again." +msgstr "" + msgid "Incorrect spelling" msgstr "Falsche Schreibweise" +msgid "Incorrect word order. Review and try again." +msgstr "" + msgid "Incorrect. Try again with the new code." msgstr "Falsch. Versuchen Sie es erneut mit dem neuen Code." @@ -386,6 +428,9 @@ msgstr "Wird mein Face ID oder Fingerabdruck in Internet Identity gespeichert?" msgid "It can be used at any time to recover your identity." msgstr "Es kann jederzeit verwendet werden, um Ihre Identität wiederherzustellen." +msgid "It looks like you're trying to sign in from a social app. Follow these steps to continue:" +msgstr "" + msgid "It looks like you're trying to sign in from inside an app (such as X, Telegram, or Instagram). This app's built-in browser is not supported." msgstr "Es scheint, als ob Sie versuchen, sich aus einer App heraus anzumelden (wie z. B. X, Telegram oder Instagram). Der in dieser App integrierte Browser wird nicht unterstützt." @@ -425,12 +470,18 @@ msgstr "Limit erreicht" msgid "Link copied to clipboard" msgstr "Link in die Zwischenablage kopiert" +msgid "Locked legacy recovery phrase" +msgstr "" + msgid "Long-press the link that opened this page." msgstr "Drücken Sie lange auf den Link, der diese Seite geöffnet hat." msgid "Make sign-up and sign-in simple with Google, Apple, or Microsoft. The login you know with enhanced privacy." msgstr "Machen Sie die Anmeldung mit Google, Apple oder Microsoft einfach. Der Login, den Sie kennen, jetzt mit erhöhter Privatsphäre." +msgid "Make sure no one can see what's on your screen or what you are writing." +msgstr "" + msgid "Make sure to add a new access method so that you can sign in next time or reset your recovery phrase." msgstr "Stellen Sie sicher, dass Sie eine neue Zugriffsmethode hinzufügen, damit Sie sich beim nächsten Mal anmelden oder Ihre Wiederherstellungsphrase zurücksetzen können." @@ -500,6 +551,12 @@ msgstr "Anzahl der Zugriffsmethoden" msgid "Only enter the code from that device if you initiated this process <0>yourself." msgstr "Geben Sie den Code von diesem Gerät nur ein, wenn Sie diesen Vorgang <0>selbst gestartet haben." +msgid "Open in browser" +msgstr "" + +msgid "Open in browser to continue" +msgstr "" + msgid "Open menu" msgstr "Menü öffnen" @@ -551,6 +608,9 @@ msgstr "Unterstützt von Internet Identity" msgid "Real Privacy" msgstr "Echte Privatsphäre" +msgid "Recover your identity" +msgstr "" + msgid "Recovery phrase" msgstr "Wiederherstellungsphrase" @@ -560,6 +620,9 @@ msgstr "Wiederherstellungsphrase aktiviert" msgid "Recovery phrase not activated" msgstr "Wiederherstellungsphrase nicht aktiviert" +msgid "Recovery phrase not verified" +msgstr "" + msgid "Redirecting to the app" msgstr "Weiterleitung zur App..." @@ -590,21 +653,39 @@ msgstr "Dieses Konto umbenennen" msgid "Replace it anytime" msgstr "Jederzeit ersetzen" +msgid "Requires unlocking before it can be reset." +msgstr "" + msgid "Reset" msgstr "Zurücksetzen" +msgid "Reset your recovery phrase?" +msgstr "" + +msgid "Resetting recovery phrase..." +msgstr "" + +msgid "Resetting will invalidate your current recovery phrase, leaving only the new one usable." +msgstr "" + msgid "Retry" msgstr "Wiederholen" msgid "Return to app" msgstr "Zurück zur App" +msgid "Return to application" +msgstr "" + msgid "Right now" msgstr "Jetzt gerade" msgid "Save changes" msgstr "Änderungen speichern" +msgid "Save your recovery phrase" +msgstr "" + msgid "Saving changes..." msgstr "Änderungen werden gespeichert..." @@ -623,6 +704,9 @@ msgstr "Sehen Sie, wie viele Zugriffsmethoden Ihre Identität hat, und verwalten msgid "Select <0>Open in Safari or <1>Open in Chrome." msgstr "Wählen Sie <0>In Safari öffnen oder <1>In Chrome öffnen." +msgid "Select each word in the correct order:" +msgstr "" + msgid "Set as default sign-in" msgstr "Als Standardanmeldung festlegen" @@ -689,6 +773,12 @@ msgstr "Support" msgid "Switch identity" msgstr "Identität wechseln" +msgid "Tap on the <0>address bar and <1>open in browser." +msgstr "" + +msgid "Tap on the highlighted <0>back button." +msgstr "" + msgid "The <0>existing device is preparing to continue." msgstr "Das <0>bestehende Gerät bereitet die Fortsetzung vor." @@ -707,6 +797,9 @@ msgstr "Beim Verbinden mit der Anwendung ist ein Problem aufgetreten. Versuchen msgid "This identity has already been upgraded to the new experience." msgstr "Diese Identität wurde bereits auf die neue Version aktualisiert." +msgid "This may take a few seconds" +msgstr "" + msgid "This takes a few seconds." msgstr "Dies dauert einige Sekunden." @@ -752,6 +845,12 @@ msgstr "{name}-Konto-Verknüpfung aufheben" msgid "Unlinking {name} account..." msgstr "Verknüpfung mit {name}-Konto wird aufgehoben..." +msgid "Unlock and reset" +msgstr "" + +msgid "Unlock to continue" +msgstr "" + msgid "Unsupported Browser" msgstr "Nicht unterstützter Browser" @@ -791,6 +890,9 @@ msgstr "Überprüfen" msgid "Verify you are human" msgstr "Bestätigen Sie, dass Sie ein Mensch sind" +msgid "Verify your recovery phrase" +msgstr "" + msgid "Verifying..." msgstr "Überprüfung..." @@ -836,8 +938,14 @@ msgstr "Mit Passkeys können Sie jetzt Ihren Fingerabdruck, Ihr Gesicht oder Ihr msgid "with your Internet Identity" msgstr "mit Ihrer Internet Identity" -msgid "Write down all <0>24 words correctly and keep them <1>offline. Do <2>not store them in the cloud or on devices." -msgstr "Schreiben Sie alle <0>24 Wörter korrekt auf und bewahren Sie sie <1>offline auf. Speichern Sie sie <2>nicht in der Cloud oder auf Geräten." +msgid "Word {position}" +msgstr "" + +msgid "Write down all 24 words correctly and keep them offline. Do not store them in the cloud or on devices." +msgstr "" + +msgid "Write down your recovery phrase in order and verify it afterwards. Store it safely and do not share it. Losing it means you will lose access." +msgstr "" msgid "Wrong domain was set. Please try again." msgstr "Falsche Domain wurde festgelegt. Bitte versuchen Sie es erneut." @@ -851,12 +959,15 @@ msgstr "Sie haben bereits ein {name}-Konto verknüpft" msgid "You are upgrading ID <0>{identityNumber}" msgstr "Sie aktualisieren die ID <0>{identityNumber}" -msgid "You can <0>reset your recovery phrase at any time. This keeps your identity <1>secure if it is ever exposed." -msgstr "Sie können Ihre Wiederherstellungsphrase jederzeit <0>zurücksetzen. Dies hält Ihre Identität <1>sicher, falls sie jemals kompromittiert wird." - msgid "You can continue with <0>Use existing Passkey in the login process." msgstr "Sie können im Anmeldeprozess mit <0>Bestehenden Passkey verwenden fortfahren." +msgid "You can recover your identity now, verify you saved it correctly." +msgstr "" + +msgid "You can reset your recovery phrase at any time. This keeps your identity secure if it is ever exposed." +msgstr "" + msgid "You have reached the maximum number of passkeys" msgstr "Sie haben die maximale Anzahl von Passkeys erreicht." @@ -866,6 +977,9 @@ msgstr "Sie können diese Seite schließen." msgid "You no longer need to remember your identity number and can use your fingerprint, face or screen lock instead." msgstr "Sie müssen sich Ihre Identitätsnummer nicht mehr merken. Stattdessen können Sie Fingerabdruck, Gesicht oder Bildschirmsperre nutzen." +msgid "You're about to see your recovery phrase, which Internet Identity doesn't store and thus can't be retrieved if lost, so keep it safe offline." +msgstr "" + msgid "You're about to sign in on a <0>new device." msgstr "Sie sind dabei, sich auf einem <0>neuen Gerät anzumelden." @@ -896,8 +1010,11 @@ msgstr "" msgid "Your personal data, such as your name or email, is never shared. Each app gets a unique pseudonym to prevent tracking automatically." msgstr "Ihre persönlichen Daten, wie Ihr Name oder Ihre E-Mail, werden niemals geteilt. Jede App erhält automatisch ein eindeutiges Pseudonym, um Tracking zu verhindern." -msgid "Your recovery phrase gives <0>full control over your identity. <1>Never share it and <2>only use it on the official website." -msgstr "Ihre Wiederherstellungsphrase gibt Ihnen <0>volle Kontrolle über Ihre Identität. Teilen Sie sie <1>niemals und verwenden Sie sie <2>nur auf der offiziellen Website." +msgid "Your recovery phrase gives full control over your identity. Never share it and only use it on the official website." +msgstr "" + +msgid "Your recovery phrase is now active and can be reset anytime." +msgstr "" msgid "Your recovery phrase is valid but not for internet identity. You may have used the wrong seed phrase for the wrong product." msgstr "Ihre Wiederherstellungsphrase ist gültig, aber nicht für Internet Identity. Möglicherweise haben Sie die falsche Seed-Phrase für das falsche Produkt verwendet." diff --git a/src/frontend/src/lib/locales/en.po b/src/frontend/src/lib/locales/en.po index 5bebbef2e9..78bfdd7c61 100644 --- a/src/frontend/src/lib/locales/en.po +++ b/src/frontend/src/lib/locales/en.po @@ -106,6 +106,9 @@ msgstr "Authentication successful" msgid "Authorize new device" msgstr "Authorize new device" +msgid "Before you continue" +msgstr "Before you continue" + msgid "By enabling this feature, you can create more than one account for a single app. Easily switch between accounts (e.g. work, personal, or demo)." msgstr "By enabling this feature, you can create more than one account for a single app. Easily switch between accounts (e.g. work, personal, or demo)." @@ -124,6 +127,12 @@ msgstr "CAPTCHA characters" msgid "Characters are case-sensitive" msgstr "Characters are case-sensitive" +msgid "Checking recovery phrase" +msgstr "Checking recovery phrase" + +msgid "Checking your order" +msgstr "Checking your order" + msgid "Choose an account" msgstr "Choose an account" @@ -139,6 +148,9 @@ msgstr "Choose method" msgid "Clear all" msgstr "Clear all" +msgid "Click to reveal" +msgstr "Click to reveal" + msgid "Close" msgstr "Close" @@ -220,6 +232,9 @@ msgstr "Default" msgid "Discoverable passkeys" msgstr "Discoverable passkeys" +msgid "Do you want to continue?" +msgstr "Do you want to continue?" + msgid "Easy access" msgstr "Easy access" @@ -235,6 +250,9 @@ msgstr "Enable multiple accounts" msgid "Enter characters" msgstr "Enter characters" +msgid "Enter each word in the correct order:" +msgstr "Enter each word in the correct order:" + msgid "Enter your recovery phrase words in each box, spelled correctly and in order." msgstr "Enter your recovery phrase words in each box, spelled correctly and in order." @@ -269,6 +287,12 @@ msgstr "Full Ownership" msgid "Generating code..." msgstr "Generating code..." +msgid "Generating phrase..." +msgstr "Generating phrase..." + +msgid "Get started" +msgstr "Get started" + msgid "Give your identity a clear, simple, and memorable name you'll easily recognize." msgstr "Give your identity a clear, simple, and memorable name you'll easily recognize." @@ -284,6 +308,9 @@ msgstr "Go to the app - (<0>{countdown})" msgid "Has not been used yet" msgstr "Has not been used yet" +msgid "Have your recovery phrase ready before continuing. Keep it private. Don’t let anyone watch you enter it. You can reset it later in your dashboard if you want a new one." +msgstr "Have your recovery phrase ready before continuing. Keep it private. Don’t let anyone watch you enter it. You can reset it later in your dashboard if you want a new one." + msgid "Help & FAQ" msgstr "Help & FAQ" @@ -314,6 +341,15 @@ msgstr "How it works" msgid "How to stay secure" msgstr "How to stay secure" +msgid "I Acknowledge" +msgstr "I Acknowledge" + +msgid "I am responsible for my recovery phrase and it cannot be retrieved from Internet Identity if lost." +msgstr "I am responsible for my recovery phrase and it cannot be retrieved from Internet Identity if lost." + +msgid "I have written it down" +msgstr "I have written it down" + msgid "Identity already upgraded" msgstr "Identity already upgraded" @@ -332,9 +368,15 @@ msgstr "If you proceed, you will no longer be able to sign-in to your identity o msgid "In use on another account." msgstr "In use on another account." +msgid "Incorrect recovery phrase. Please try again." +msgstr "Incorrect recovery phrase. Please try again." + msgid "Incorrect spelling" msgstr "Incorrect spelling" +msgid "Incorrect word order. Review and try again." +msgstr "Incorrect word order. Review and try again." + msgid "Incorrect. Try again with the new code." msgstr "Incorrect. Try again with the new code." @@ -386,6 +428,9 @@ msgstr "Is my Face ID or Fingerprint stored in Internet Identity?" msgid "It can be used at any time to recover your identity." msgstr "It can be used at any time to recover your identity." +msgid "It looks like you're trying to sign in from a social app. Follow these steps to continue:" +msgstr "It looks like you're trying to sign in from a social app. Follow these steps to continue:" + msgid "It looks like you're trying to sign in from inside an app (such as X, Telegram, or Instagram). This app's built-in browser is not supported." msgstr "It looks like you're trying to sign in from inside an app (such as X, Telegram, or Instagram). This app's built-in browser is not supported." @@ -425,12 +470,18 @@ msgstr "Limit reached" msgid "Link copied to clipboard" msgstr "Link copied to clipboard" +msgid "Locked legacy recovery phrase" +msgstr "Locked legacy recovery phrase" + msgid "Long-press the link that opened this page." msgstr "Long-press the link that opened this page." msgid "Make sign-up and sign-in simple with Google, Apple, or Microsoft. The login you know with enhanced privacy." msgstr "Make sign-up and sign-in simple with Google, Apple, or Microsoft. The login you know with enhanced privacy." +msgid "Make sure no one can see what's on your screen or what you are writing." +msgstr "Make sure no one can see what's on your screen or what you are writing." + msgid "Make sure to add a new access method so that you can sign in next time or reset your recovery phrase." msgstr "Make sure to add a new access method so that you can sign in next time or reset your recovery phrase." @@ -500,6 +551,12 @@ msgstr "Number of access methods" msgid "Only enter the code from that device if you initiated this process <0>yourself." msgstr "Only enter the code from that device if you initiated this process <0>yourself." +msgid "Open in browser" +msgstr "Open in browser" + +msgid "Open in browser to continue" +msgstr "Open in browser to continue" + msgid "Open menu" msgstr "Open menu" @@ -551,6 +608,9 @@ msgstr "Powered by Internet Identity" msgid "Real Privacy" msgstr "Real Privacy" +msgid "Recover your identity" +msgstr "Recover your identity" + msgid "Recovery phrase" msgstr "Recovery phrase" @@ -560,6 +620,9 @@ msgstr "Recovery phrase activated" msgid "Recovery phrase not activated" msgstr "Recovery phrase not activated" +msgid "Recovery phrase not verified" +msgstr "Recovery phrase not verified" + msgid "Redirecting to the app" msgstr "Redirecting to the app" @@ -590,21 +653,39 @@ msgstr "Rename this account" msgid "Replace it anytime" msgstr "Replace it anytime" +msgid "Requires unlocking before it can be reset." +msgstr "Requires unlocking before it can be reset." + msgid "Reset" msgstr "Reset" +msgid "Reset your recovery phrase?" +msgstr "Reset your recovery phrase?" + +msgid "Resetting recovery phrase..." +msgstr "Resetting recovery phrase..." + +msgid "Resetting will invalidate your current recovery phrase, leaving only the new one usable." +msgstr "Resetting will invalidate your current recovery phrase, leaving only the new one usable." + msgid "Retry" msgstr "Retry" msgid "Return to app" msgstr "Return to app" +msgid "Return to application" +msgstr "Return to application" + msgid "Right now" msgstr "Right now" msgid "Save changes" msgstr "Save changes" +msgid "Save your recovery phrase" +msgstr "Save your recovery phrase" + msgid "Saving changes..." msgstr "Saving changes..." @@ -623,6 +704,9 @@ msgstr "See how many access methods are within your identity and manage your rec msgid "Select <0>Open in Safari or <1>Open in Chrome." msgstr "Select <0>Open in Safari or <1>Open in Chrome." +msgid "Select each word in the correct order:" +msgstr "Select each word in the correct order:" + msgid "Set as default sign-in" msgstr "Set as default sign-in" @@ -689,6 +773,12 @@ msgstr "Support" msgid "Switch identity" msgstr "Switch identity" +msgid "Tap on the <0>address bar and <1>open in browser." +msgstr "Tap on the <0>address bar and <1>open in browser." + +msgid "Tap on the highlighted <0>back button." +msgstr "Tap on the highlighted <0>back button." + msgid "The <0>existing device is preparing to continue." msgstr "The <0>existing device is preparing to continue." @@ -707,6 +797,9 @@ msgstr "There was an issue connecting with the application. Try a different brow msgid "This identity has already been upgraded to the new experience." msgstr "This identity has already been upgraded to the new experience." +msgid "This may take a few seconds" +msgstr "This may take a few seconds" + msgid "This takes a few seconds." msgstr "This takes a few seconds." @@ -752,6 +845,12 @@ msgstr "Unlink {name} account" msgid "Unlinking {name} account..." msgstr "Unlinking {name} account..." +msgid "Unlock and reset" +msgstr "Unlock and reset" + +msgid "Unlock to continue" +msgstr "Unlock to continue" + msgid "Unsupported Browser" msgstr "Unsupported Browser" @@ -791,6 +890,9 @@ msgstr "Verify" msgid "Verify you are human" msgstr "Verify you are human" +msgid "Verify your recovery phrase" +msgstr "Verify your recovery phrase" + msgid "Verifying..." msgstr "Verifying..." @@ -836,8 +938,14 @@ msgstr "With passkeys, you can now use your fingerprint, face, or screen lock to msgid "with your Internet Identity" msgstr "with your Internet Identity" -msgid "Write down all <0>24 words correctly and keep them <1>offline. Do <2>not store them in the cloud or on devices." -msgstr "Write down all <0>24 words correctly and keep them <1>offline. Do <2>not store them in the cloud or on devices." +msgid "Word {position}" +msgstr "Word {position}" + +msgid "Write down all 24 words correctly and keep them offline. Do not store them in the cloud or on devices." +msgstr "Write down all 24 words correctly and keep them offline. Do not store them in the cloud or on devices." + +msgid "Write down your recovery phrase in order and verify it afterwards. Store it safely and do not share it. Losing it means you will lose access." +msgstr "Write down your recovery phrase in order and verify it afterwards. Store it safely and do not share it. Losing it means you will lose access." msgid "Wrong domain was set. Please try again." msgstr "Wrong domain was set. Please try again." @@ -851,12 +959,15 @@ msgstr "You already have a {name} account linked" msgid "You are upgrading ID <0>{identityNumber}" msgstr "You are upgrading ID <0>{identityNumber}" -msgid "You can <0>reset your recovery phrase at any time. This keeps your identity <1>secure if it is ever exposed." -msgstr "You can <0>reset your recovery phrase at any time. This keeps your identity <1>secure if it is ever exposed." - msgid "You can continue with <0>Use existing Passkey in the login process." msgstr "You can continue with <0>Use existing Passkey in the login process." +msgid "You can recover your identity now, verify you saved it correctly." +msgstr "You can recover your identity now, verify you saved it correctly." + +msgid "You can reset your recovery phrase at any time. This keeps your identity secure if it is ever exposed." +msgstr "You can reset your recovery phrase at any time. This keeps your identity secure if it is ever exposed." + msgid "You have reached the maximum number of passkeys" msgstr "You have reached the maximum number of passkeys" @@ -866,6 +977,9 @@ msgstr "You may close this page." msgid "You no longer need to remember your identity number and can use your fingerprint, face or screen lock instead." msgstr "You no longer need to remember your identity number and can use your fingerprint, face or screen lock instead." +msgid "You're about to see your recovery phrase, which Internet Identity doesn't store and thus can't be retrieved if lost, so keep it safe offline." +msgstr "You're about to see your recovery phrase, which Internet Identity doesn't store and thus can't be retrieved if lost, so keep it safe offline." + msgid "You're about to sign in on a <0>new device." msgstr "You're about to sign in on a <0>new device." @@ -896,8 +1010,11 @@ msgstr "Your identity was restored, but the name could not be updated. Please tr msgid "Your personal data, such as your name or email, is never shared. Each app gets a unique pseudonym to prevent tracking automatically." msgstr "Your personal data, such as your name or email, is never shared. Each app gets a unique pseudonym to prevent tracking automatically." -msgid "Your recovery phrase gives <0>full control over your identity. <1>Never share it and <2>only use it on the official website." -msgstr "Your recovery phrase gives <0>full control over your identity. <1>Never share it and <2>only use it on the official website." +msgid "Your recovery phrase gives full control over your identity. Never share it and only use it on the official website." +msgstr "Your recovery phrase gives full control over your identity. Never share it and only use it on the official website." + +msgid "Your recovery phrase is now active and can be reset anytime." +msgstr "Your recovery phrase is now active and can be reset anytime." msgid "Your recovery phrase is valid but not for internet identity. You may have used the wrong seed phrase for the wrong product." msgstr "Your recovery phrase is valid but not for internet identity. You may have used the wrong seed phrase for the wrong product." diff --git a/src/frontend/src/lib/locales/es.po b/src/frontend/src/lib/locales/es.po index 342878fba1..11a40fd9dc 100644 --- a/src/frontend/src/lib/locales/es.po +++ b/src/frontend/src/lib/locales/es.po @@ -106,6 +106,9 @@ msgstr "Autenticación correcta" msgid "Authorize new device" msgstr "Autorizar nuevo dispositivo" +msgid "Before you continue" +msgstr "" + msgid "By enabling this feature, you can create more than one account for a single app. Easily switch between accounts (e.g. work, personal, or demo)." msgstr "Al activar esta función, puedes crear más de una cuenta por app. Cambia fácilmente entre cuentas (p. ej., trabajo, personal o demo)." @@ -124,6 +127,12 @@ msgstr "Caracteres del CAPTCHA" msgid "Characters are case-sensitive" msgstr "Distingue mayúsculas y minúsculas" +msgid "Checking recovery phrase" +msgstr "" + +msgid "Checking your order" +msgstr "" + msgid "Choose an account" msgstr "Elige una cuenta" @@ -139,6 +148,9 @@ msgstr "Elige un método" msgid "Clear all" msgstr "Borrar todo" +msgid "Click to reveal" +msgstr "" + msgid "Close" msgstr "Cerrar" @@ -220,6 +232,9 @@ msgstr "Predeterminada" msgid "Discoverable passkeys" msgstr "Passkeys detectables" +msgid "Do you want to continue?" +msgstr "" + msgid "Easy access" msgstr "Fácil acceso" @@ -235,6 +250,9 @@ msgstr "Activar cuentas múltiples" msgid "Enter characters" msgstr "Introduce los caracteres" +msgid "Enter each word in the correct order:" +msgstr "" + msgid "Enter your recovery phrase words in each box, spelled correctly and in order." msgstr "Escribe tus palabras de recuperación en cada campo, escritas correctamente y en orden." @@ -269,6 +287,12 @@ msgstr "Propiedad Total" msgid "Generating code..." msgstr "Generando código..." +msgid "Generating phrase..." +msgstr "" + +msgid "Get started" +msgstr "" + msgid "Give your identity a clear, simple, and memorable name you'll easily recognize." msgstr "Dale a tu identidad un nombre claro, simple y memorable que reconozcas fácilmente." @@ -284,6 +308,9 @@ msgstr "Ir a la app - (<0>{countdown})" msgid "Has not been used yet" msgstr "No se ha usado todavía" +msgid "Have your recovery phrase ready before continuing. Keep it private. Don’t let anyone watch you enter it. You can reset it later in your dashboard if you want a new one." +msgstr "" + msgid "Help & FAQ" msgstr "Ayuda y preguntas frecuentes" @@ -314,6 +341,15 @@ msgstr "Cómo funciona" msgid "How to stay secure" msgstr "Cómo mantenerse seguro" +msgid "I Acknowledge" +msgstr "" + +msgid "I am responsible for my recovery phrase and it cannot be retrieved from Internet Identity if lost." +msgstr "" + +msgid "I have written it down" +msgstr "" + msgid "Identity already upgraded" msgstr "Identidad ya actualizada" @@ -332,9 +368,15 @@ msgstr "Si continúas, ya no podrás iniciar sesión en tu identidad o dapps con msgid "In use on another account." msgstr "En uso en otra cuenta." +msgid "Incorrect recovery phrase. Please try again." +msgstr "" + msgid "Incorrect spelling" msgstr "Ortografía incorrecta" +msgid "Incorrect word order. Review and try again." +msgstr "" + msgid "Incorrect. Try again with the new code." msgstr "Incorrecto. Inténtalo de nuevo con el nuevo código." @@ -386,6 +428,9 @@ msgstr "¿Se almacena mi Face ID o huella digital en Internet Identity?" msgid "It can be used at any time to recover your identity." msgstr "Se puede usar en cualquier momento para recuperar tu identidad." +msgid "It looks like you're trying to sign in from a social app. Follow these steps to continue:" +msgstr "" + msgid "It looks like you're trying to sign in from inside an app (such as X, Telegram, or Instagram). This app's built-in browser is not supported." msgstr "Parece que estás intentando iniciar sesión desde dentro de una aplicación (como X, Telegram o Instagram). El navegador integrado de esta aplicación no es compatible." @@ -425,12 +470,18 @@ msgstr "Límite alcanzado" msgid "Link copied to clipboard" msgstr "Enlace copiado al portapapeles" +msgid "Locked legacy recovery phrase" +msgstr "" + msgid "Long-press the link that opened this page." msgstr "Mantén presionada la tecla de la página que abrió esta página." msgid "Make sign-up and sign-in simple with Google, Apple, or Microsoft. The login you know with enhanced privacy." msgstr "Tan simple como usar Google, Apple o Microsoft. El inicio de sesión que conoces, ahora con mayor privacidad." +msgid "Make sure no one can see what's on your screen or what you are writing." +msgstr "" + msgid "Make sure to add a new access method so that you can sign in next time or reset your recovery phrase." msgstr "Asegúrate de añadir un nuevo método de acceso para poder iniciar sesión la próxima vez o restablecer tu frase de recuperación." @@ -500,6 +551,12 @@ msgstr "Número de métodos de acceso" msgid "Only enter the code from that device if you initiated this process <0>yourself." msgstr "Introduce el código de ese dispositivo solo si iniciaste este proceso <0>tú mismo." +msgid "Open in browser" +msgstr "" + +msgid "Open in browser to continue" +msgstr "" + msgid "Open menu" msgstr "Abrir menú" @@ -551,6 +608,9 @@ msgstr "Con la tecnología de Internet Identity" msgid "Real Privacy" msgstr "Privacidad Verdadera" +msgid "Recover your identity" +msgstr "" + msgid "Recovery phrase" msgstr "Frase de recuperación" @@ -560,6 +620,9 @@ msgstr "Frase de recuperación activada" msgid "Recovery phrase not activated" msgstr "Frase de recuperación no activada" +msgid "Recovery phrase not verified" +msgstr "" + msgid "Redirecting to the app" msgstr "Redirigiendo a la app..." @@ -590,21 +653,39 @@ msgstr "Renombra esta cuenta" msgid "Replace it anytime" msgstr "Reemplázala en cualquier momento" +msgid "Requires unlocking before it can be reset." +msgstr "" + msgid "Reset" msgstr "Restablecer" +msgid "Reset your recovery phrase?" +msgstr "" + +msgid "Resetting recovery phrase..." +msgstr "" + +msgid "Resetting will invalidate your current recovery phrase, leaving only the new one usable." +msgstr "" + msgid "Retry" msgstr "Reintentar" msgid "Return to app" msgstr "Volver a la app" +msgid "Return to application" +msgstr "" + msgid "Right now" msgstr "Ahora mismo" msgid "Save changes" msgstr "Guardar cambios" +msgid "Save your recovery phrase" +msgstr "" + msgid "Saving changes..." msgstr "Guardando cambios..." @@ -623,6 +704,9 @@ msgstr "Consulta cuántos métodos de acceso hay en tu identidad y gestiona tu f msgid "Select <0>Open in Safari or <1>Open in Chrome." msgstr "Selectiona <0>Abrir en Safari o <1>Abrir en Chrome." +msgid "Select each word in the correct order:" +msgstr "" + msgid "Set as default sign-in" msgstr "Establecer como inicio de sesión predeterminado" @@ -689,6 +773,12 @@ msgstr "Soporte" msgid "Switch identity" msgstr "Cambiar de identidad" +msgid "Tap on the <0>address bar and <1>open in browser." +msgstr "" + +msgid "Tap on the highlighted <0>back button." +msgstr "" + msgid "The <0>existing device is preparing to continue." msgstr "El <0>dispositivo existente se está preparando para continuar." @@ -707,6 +797,9 @@ msgstr "Hubo un problema al conectar con la aplicación. Prueba con otro navegad msgid "This identity has already been upgraded to the new experience." msgstr "Esta identidad ya ha sido actualizada a la nueva experiencia." +msgid "This may take a few seconds" +msgstr "" + msgid "This takes a few seconds." msgstr "Esto tarda unos segundos." @@ -752,6 +845,12 @@ msgstr "Desvincular cuenta de {name}" msgid "Unlinking {name} account..." msgstr "Desvinculando cuenta de {name}..." +msgid "Unlock and reset" +msgstr "" + +msgid "Unlock to continue" +msgstr "" + msgid "Unsupported Browser" msgstr "Navegador no compatible" @@ -791,6 +890,9 @@ msgstr "Verificar" msgid "Verify you are human" msgstr "Verifica que eres humano" +msgid "Verify your recovery phrase" +msgstr "" + msgid "Verifying..." msgstr "Verificando..." @@ -836,8 +938,14 @@ msgstr "Con las passkeys, ahora puedes usar tu huella digital, rostro o bloqueo msgid "with your Internet Identity" msgstr "con tu Internet Identity" -msgid "Write down all <0>24 words correctly and keep them <1>offline. Do <2>not store them in the cloud or on devices." -msgstr "Anota las <0>24 palabras correctamente y guárdalas <1>sin conexión. <2>No las almacenes en la nube ni en dispositivos." +msgid "Word {position}" +msgstr "" + +msgid "Write down all 24 words correctly and keep them offline. Do not store them in the cloud or on devices." +msgstr "" + +msgid "Write down your recovery phrase in order and verify it afterwards. Store it safely and do not share it. Losing it means you will lose access." +msgstr "" msgid "Wrong domain was set. Please try again." msgstr "Se estableció un dominio incorrecto. Por favor, inténtalo de nuevo." @@ -851,12 +959,15 @@ msgstr "Ya tienes una cuenta de {name} vinculada" msgid "You are upgrading ID <0>{identityNumber}" msgstr "Estás actualizando el ID <0>{identityNumber}" -msgid "You can <0>reset your recovery phrase at any time. This keeps your identity <1>secure if it is ever exposed." -msgstr "Puedes <0>restablecer tu frase de recuperación en cualquier momento. Esto mantiene tu identidad <1>segura si alguna vez queda expuesta." - msgid "You can continue with <0>Use existing Passkey in the login process." msgstr "Puedes continuar con <0>Usar Passkey existente en el proceso de inicio de sesión." +msgid "You can recover your identity now, verify you saved it correctly." +msgstr "" + +msgid "You can reset your recovery phrase at any time. This keeps your identity secure if it is ever exposed." +msgstr "" + msgid "You have reached the maximum number of passkeys" msgstr "Has alcanzado el número máximo de passkeys" @@ -866,6 +977,9 @@ msgstr "Puedes cerrar esta página." msgid "You no longer need to remember your identity number and can use your fingerprint, face or screen lock instead." msgstr "Ya no necesitas recordar tu número de identidad y puedes usar tu huella, rostro o bloqueo de pantalla en su lugar." +msgid "You're about to see your recovery phrase, which Internet Identity doesn't store and thus can't be retrieved if lost, so keep it safe offline." +msgstr "" + msgid "You're about to sign in on a <0>new device." msgstr "Estás a punto de iniciar sesión en un <0>nuevo dispositivo." @@ -896,8 +1010,11 @@ msgstr "Tu identidad ha sido restaurada, pero el nombre no se pudo actualizar. P msgid "Your personal data, such as your name or email, is never shared. Each app gets a unique pseudonym to prevent tracking automatically." msgstr "Tus datos personales, como tu nombre o email, nunca se comparten. Cada app obtiene un seudónimo único para evitar el rastreo automáticamente." -msgid "Your recovery phrase gives <0>full control over your identity. <1>Never share it and <2>only use it on the official website." -msgstr "Tu frase de recuperación te da <0>control total sobre tu identidad. <1>Nunca la compartas y <2>solo úsala en el sitio web oficial." +msgid "Your recovery phrase gives full control over your identity. Never share it and only use it on the official website." +msgstr "" + +msgid "Your recovery phrase is now active and can be reset anytime." +msgstr "" msgid "Your recovery phrase is valid but not for internet identity. You may have used the wrong seed phrase for the wrong product." msgstr "Tu frase de recuperación es válida, pero no para Internet Identity. Es posible que hayas usado la frase incorrecta para el producto equivocado." diff --git a/src/frontend/src/lib/locales/id.po b/src/frontend/src/lib/locales/id.po index 4a8a2ea13b..b917dc6176 100644 --- a/src/frontend/src/lib/locales/id.po +++ b/src/frontend/src/lib/locales/id.po @@ -106,6 +106,9 @@ msgstr "Autentikasi berhasil" msgid "Authorize new device" msgstr "Otorisasi perangkat baru" +msgid "Before you continue" +msgstr "" + msgid "By enabling this feature, you can create more than one account for a single app. Easily switch between accounts (e.g. work, personal, or demo)." msgstr "Dengan mengaktifkan fitur ini, Anda dapat membuat lebih dari satu akun untuk satu aplikasi. Beralih antar akun dengan mudah (misalnya, kantor, pribadi, atau demo)." @@ -124,6 +127,12 @@ msgstr "Karakter CAPTCHA" msgid "Characters are case-sensitive" msgstr "Karakter membedakan huruf besar/kecil" +msgid "Checking recovery phrase" +msgstr "" + +msgid "Checking your order" +msgstr "" + msgid "Choose an account" msgstr "Pilih akun" @@ -139,6 +148,9 @@ msgstr "Pilih metode" msgid "Clear all" msgstr "Hapus semua" +msgid "Click to reveal" +msgstr "" + msgid "Close" msgstr "Tutup" @@ -220,6 +232,9 @@ msgstr "Default" msgid "Discoverable passkeys" msgstr "Passkey yang dapat ditemukan" +msgid "Do you want to continue?" +msgstr "" + msgid "Easy access" msgstr "Akses mudah" @@ -235,6 +250,9 @@ msgstr "Aktifkan banyak akun" msgid "Enter characters" msgstr "Masukkan karakter" +msgid "Enter each word in the correct order:" +msgstr "" + msgid "Enter your recovery phrase words in each box, spelled correctly and in order." msgstr "Masukkan kata-kata frasa pemulihan Anda di setiap kotak, dengan ejaan yang benar dan berurutan." @@ -269,6 +287,12 @@ msgstr "Kepemilikan penuh" msgid "Generating code..." msgstr "Membuat kode..." +msgid "Generating phrase..." +msgstr "" + +msgid "Get started" +msgstr "" + msgid "Give your identity a clear, simple, and memorable name you'll easily recognize." msgstr "Beri identitas Anda nama yang jelas, sederhana, dan mudah diingat agar mudah Anda kenali." @@ -284,6 +308,9 @@ msgstr "Buka aplikasi - (<0>{countdown})" msgid "Has not been used yet" msgstr "Belum digunakan" +msgid "Have your recovery phrase ready before continuing. Keep it private. Don’t let anyone watch you enter it. You can reset it later in your dashboard if you want a new one." +msgstr "" + msgid "Help & FAQ" msgstr "Bantuan & FAQ" @@ -314,6 +341,15 @@ msgstr "Cara kerja" msgid "How to stay secure" msgstr "Cara tetap aman" +msgid "I Acknowledge" +msgstr "" + +msgid "I am responsible for my recovery phrase and it cannot be retrieved from Internet Identity if lost." +msgstr "" + +msgid "I have written it down" +msgstr "" + msgid "Identity already upgraded" msgstr "Identitas sudah ditingkatkan" @@ -332,9 +368,15 @@ msgstr "Jika Anda melanjutkan, Anda tidak akan lagi dapat masuk ke identitas ata msgid "In use on another account." msgstr "Digunakan di akun lain." +msgid "Incorrect recovery phrase. Please try again." +msgstr "" + msgid "Incorrect spelling" msgstr "Ejaan salah" +msgid "Incorrect word order. Review and try again." +msgstr "" + msgid "Incorrect. Try again with the new code." msgstr "Salah. Coba lagi dengan kode baru." @@ -386,6 +428,9 @@ msgstr "Apakah Face ID atau sidik jari saya disimpan di Internet Identity?" msgid "It can be used at any time to recover your identity." msgstr "Ini dapat digunakan kapan saja untuk memulihkan identitas Anda." +msgid "It looks like you're trying to sign in from a social app. Follow these steps to continue:" +msgstr "" + msgid "It looks like you're trying to sign in from inside an app (such as X, Telegram, or Instagram). This app's built-in browser is not supported." msgstr "Tampaknya Anda mencoba masuk dari dalam aplikasi (seperti X, Telegram, atau Instagram). Peramban bawaan aplikasi ini tidak didukung." @@ -425,12 +470,18 @@ msgstr "Batas tercapai" msgid "Link copied to clipboard" msgstr "Tautan disalin ke papan klip" +msgid "Locked legacy recovery phrase" +msgstr "" + msgid "Long-press the link that opened this page." msgstr "Tekan lama tautan yang membuka halaman ini." msgid "Make sign-up and sign-in simple with Google, Apple, or Microsoft. The login you know with enhanced privacy." msgstr "Permudah pendaftaran dan masuk dengan Google, Apple, atau Microsoft. Login yang Anda kenal, kini dengan privasi yang lebih baik." +msgid "Make sure no one can see what's on your screen or what you are writing." +msgstr "" + msgid "Make sure to add a new access method so that you can sign in next time or reset your recovery phrase." msgstr "Pastikan untuk menambahkan metode akses baru agar Anda dapat masuk lain kali atau mengatur ulang frasa pemulihan Anda." @@ -500,6 +551,12 @@ msgstr "Jumlah metode akses" msgid "Only enter the code from that device if you initiated this process <0>yourself." msgstr "Masukkan kode dari perangkat itu hanya jika Anda yang memulai proses ini <0>sendiri." +msgid "Open in browser" +msgstr "" + +msgid "Open in browser to continue" +msgstr "" + msgid "Open menu" msgstr "Buka menu" @@ -551,6 +608,9 @@ msgstr "Didukung oleh Internet Identity" msgid "Real Privacy" msgstr "Privasi nyata" +msgid "Recover your identity" +msgstr "" + msgid "Recovery phrase" msgstr "Frasa pemulihan" @@ -560,6 +620,9 @@ msgstr "Frasa pemulihan diaktifkan" msgid "Recovery phrase not activated" msgstr "Frasa pemulihan tidak diaktifkan" +msgid "Recovery phrase not verified" +msgstr "" + msgid "Redirecting to the app" msgstr "Mengalihkan ke aplikasi..." @@ -590,21 +653,39 @@ msgstr "Ubah nama akun ini" msgid "Replace it anytime" msgstr "Ganti kapan saja" +msgid "Requires unlocking before it can be reset." +msgstr "" + msgid "Reset" msgstr "Setel ulang" +msgid "Reset your recovery phrase?" +msgstr "" + +msgid "Resetting recovery phrase..." +msgstr "" + +msgid "Resetting will invalidate your current recovery phrase, leaving only the new one usable." +msgstr "" + msgid "Retry" msgstr "Coba lagi" msgid "Return to app" msgstr "Kembali ke aplikasi" +msgid "Return to application" +msgstr "" + msgid "Right now" msgstr "Saat ini" msgid "Save changes" msgstr "Simpan perubahan" +msgid "Save your recovery phrase" +msgstr "" + msgid "Saving changes..." msgstr "Menyimpan perubahan..." @@ -623,6 +704,9 @@ msgstr "Lihat berapa banyak metode akses yang ada dalam identitas Anda dan kelol msgid "Select <0>Open in Safari or <1>Open in Chrome." msgstr "Pilih <0>Buka di Safari atau <1>Buka di Chrome." +msgid "Select each word in the correct order:" +msgstr "" + msgid "Set as default sign-in" msgstr "Atur sebagai metode masuk default" @@ -689,6 +773,12 @@ msgstr "Dukungan" msgid "Switch identity" msgstr "Ganti identitas" +msgid "Tap on the <0>address bar and <1>open in browser." +msgstr "" + +msgid "Tap on the highlighted <0>back button." +msgstr "" + msgid "The <0>existing device is preparing to continue." msgstr "<0>Perangkat yang ada sedang bersiap untuk melanjutkan." @@ -707,6 +797,9 @@ msgstr "Terjadi masalah saat menyambung ke aplikasi. Coba peramban lain; jika ma msgid "This identity has already been upgraded to the new experience." msgstr "Identitas ini sudah ditingkatkan ke pengalaman baru." +msgid "This may take a few seconds" +msgstr "" + msgid "This takes a few seconds." msgstr "Proses ini butuh beberapa detik." @@ -752,6 +845,12 @@ msgstr "Putuskan tautan akun {name}" msgid "Unlinking {name} account..." msgstr "Memutuskan tautan akun {name}..." +msgid "Unlock and reset" +msgstr "" + +msgid "Unlock to continue" +msgstr "" + msgid "Unsupported Browser" msgstr "Peramban Tidak Didukung" @@ -791,6 +890,9 @@ msgstr "Verifikasi" msgid "Verify you are human" msgstr "Verifikasi bahwa Anda manusia" +msgid "Verify your recovery phrase" +msgstr "" + msgid "Verifying..." msgstr "Memverifikasi..." @@ -836,8 +938,14 @@ msgstr "Dengan passkey, Anda sekarang dapat menggunakan sidik jari, wajah, atau msgid "with your Internet Identity" msgstr "dengan Internet Identity Anda" -msgid "Write down all <0>24 words correctly and keep them <1>offline. Do <2>not store them in the cloud or on devices." -msgstr "Tulis semua <0>24 kata dengan benar dan simpan <1>offline. <2>Jangan menyimpannya di cloud atau di perangkat." +msgid "Word {position}" +msgstr "" + +msgid "Write down all 24 words correctly and keep them offline. Do not store them in the cloud or on devices." +msgstr "" + +msgid "Write down your recovery phrase in order and verify it afterwards. Store it safely and do not share it. Losing it means you will lose access." +msgstr "" msgid "Wrong domain was set. Please try again." msgstr "Domain yang salah diatur. Silakan coba lagi." @@ -851,12 +959,15 @@ msgstr "Anda sudah memiliki akun {name} yang tertaut" msgid "You are upgrading ID <0>{identityNumber}" msgstr "Anda sedang meningkatkan ID <0>{identityNumber}" -msgid "You can <0>reset your recovery phrase at any time. This keeps your identity <1>secure if it is ever exposed." -msgstr "Anda dapat <0>mereset frasa pemulihan Anda kapan saja. Ini menjaga identitas Anda <1>tetap aman jika sewaktu-waktu terekspos." - msgid "You can continue with <0>Use existing Passkey in the login process." msgstr "Anda dapat melanjutkan dengan <0>Gunakan Passkey yang ada dalam proses masuk." +msgid "You can recover your identity now, verify you saved it correctly." +msgstr "" + +msgid "You can reset your recovery phrase at any time. This keeps your identity secure if it is ever exposed." +msgstr "" + msgid "You have reached the maximum number of passkeys" msgstr "Anda telah mencapai jumlah maksimum passkey" @@ -866,6 +977,9 @@ msgstr "Anda dapat menutup halaman ini." msgid "You no longer need to remember your identity number and can use your fingerprint, face or screen lock instead." msgstr "Anda tidak perlu lagi mengingat nomor identitas Anda dan dapat menggunakan sidik jari, wajah, atau kunci layar sebagai gantinya." +msgid "You're about to see your recovery phrase, which Internet Identity doesn't store and thus can't be retrieved if lost, so keep it safe offline." +msgstr "" + msgid "You're about to sign in on a <0>new device." msgstr "Anda akan masuk di <0>perangkat baru." @@ -896,8 +1010,11 @@ msgstr "" msgid "Your personal data, such as your name or email, is never shared. Each app gets a unique pseudonym to prevent tracking automatically." msgstr "Data pribadi Anda, seperti nama atau email, tidak pernah dibagikan. Setiap aplikasi mendapatkan pseudonim unik untuk mencegah pelacakan secara otomatis." -msgid "Your recovery phrase gives <0>full control over your identity. <1>Never share it and <2>only use it on the official website." -msgstr "Frasa pemulihan Anda memberikan <0>kontrol penuh atas identitas Anda. <1>Jangan pernah membagikannya dan <2>hanya gunakan di situs web resmi." +msgid "Your recovery phrase gives full control over your identity. Never share it and only use it on the official website." +msgstr "" + +msgid "Your recovery phrase is now active and can be reset anytime." +msgstr "" msgid "Your recovery phrase is valid but not for internet identity. You may have used the wrong seed phrase for the wrong product." msgstr "Frasa pemulihan Anda valid tetapi bukan untuk identitas internet. Anda mungkin telah menggunakan frasa benih yang salah untuk produk yang salah." diff --git a/src/internet_identity/Cargo.toml b/src/internet_identity/Cargo.toml index 7c86414a53..4671268b64 100644 --- a/src/internet_identity/Cargo.toml +++ b/src/internet_identity/Cargo.toml @@ -22,10 +22,10 @@ minicbor = { workspace = true, features = ["std", "derive"] } # Captcha deps lodepng = "*" -rand = { version = "*", default-features = false } +rand = { version = "0.8", default-features = false } -rand_core = { version = "*", default-features = false } -rand_chacha = { version = "*", default-features = false } +rand_core = { version = "0.6", default-features = false } +rand_chacha = { version = "0.3", default-features = false } captcha = { git = "https://github.com/dfinity/captcha", rev = "9c0d2dd9bf519e255eaa239d9f4e9fdc83f65391" } # OpenID deps diff --git a/src/internet_identity_frontend/Cargo.toml b/src/internet_identity_frontend/Cargo.toml new file mode 100644 index 0000000000..ec8c7ee38f --- /dev/null +++ b/src/internet_identity_frontend/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "internet_identity_frontend" +version = "0.1.0" +edition = "2021" + +[dependencies] +# Core dependencies for HTTP gateway functionality +internet_identity_interface.workspace = true +serde_bytes.workspace = true + +# IC canister dependencies +candid.workspace = true +ic-cdk.workspace = true +ic-cdk-macros.workspace = true + + +[features] +# The dev_csp feature weakens the CSP in oder to facilitate development with a locally deployed II instance. +# In particular, this allows +# * accessing II using http instead of https +# * II to connect to localhost both on http and https, which is useful when developint a vc issuer +dev_csp = [] diff --git a/src/internet_identity_frontend/README.md b/src/internet_identity_frontend/README.md index 8a8c1281bf..bd2c002700 100644 --- a/src/internet_identity_frontend/README.md +++ b/src/internet_identity_frontend/README.md @@ -2,4 +2,4 @@ This crate defines the new Internet Identity frontend (currently not used in pro The idea is to factor out the frontend part of the Internet Identity canister, so that the remaining backend has a simpler Http API and the remaining frontend has a simpler Candid API. This will -make the development process more managable and better separate concerns. \ No newline at end of file +make the development process more manageable and better separate concerns. diff --git a/src/internet_identity_frontend/internet_identity_frontend.did b/src/internet_identity_frontend/internet_identity_frontend.did new file mode 100644 index 0000000000..2c87ecc923 --- /dev/null +++ b/src/internet_identity_frontend/internet_identity_frontend.did @@ -0,0 +1,38 @@ +type HeaderField = record { + text; + text; +}; + +type HttpRequest = record { + method : text; + url : text; + headers : vec HeaderField; + body : blob; + certificate_version : opt nat16; +}; + +type HttpResponse = record { + status_code : nat16; + headers : vec HeaderField; + body : blob; + upgrade : opt bool; + streaming_strategy : opt StreamingStrategy; +}; + +type StreamingCallbackHttpResponse = record { + body : blob; + token : opt Token; +}; + +type Token = record {}; + +type StreamingStrategy = variant { + Callback : record { + callback : func(Token) -> (StreamingCallbackHttpResponse) query; + token : Token; + }; +}; + +service : (opt record {}) -> { + http_request : (request : HttpRequest) -> (HttpResponse) query; +}; diff --git a/src/internet_identity_frontend/src/http.rs b/src/internet_identity_frontend/src/http.rs new file mode 100644 index 0000000000..4c4636022d --- /dev/null +++ b/src/internet_identity_frontend/src/http.rs @@ -0,0 +1,281 @@ +use internet_identity_interface::http_gateway::{HeaderField, HttpRequest, HttpResponse}; +use serde_bytes::ByteBuf; + +fn http_options_request() -> HttpResponse { + // TODO: Restrict origin to just the II-specific origins. + let headers = vec![("Access-Control-Allow-Origin".to_string(), "*".to_string())]; + + HttpResponse { + // Indicates success without any additional content to be sent in the response content. + status_code: 204, + headers, + body: ByteBuf::from(vec![]), + upgrade: None, + streaming_strategy: None, + } +} + +fn http_get_request(url: String, certificate_version: Option) -> HttpResponse { + let parts: Vec<&str> = url.split('?').collect(); + + match parts[0] { + probably_an_asset => match get_asset(probably_an_asset, certificate_version) { + Some((status_code, content, headers)) => HttpResponse { + status_code, + headers, + body: ByteBuf::from(content), + upgrade: None, + streaming_strategy: None, + }, + None => HttpResponse { + status_code: 404, + headers: security_headers(vec![], None), + body: ByteBuf::from(format!("Asset {probably_an_asset} not found.")), + upgrade: None, + streaming_strategy: None, + }, + }, + } +} + +fn method_not_allowed(unsupported_method: &str) -> HttpResponse { + HttpResponse { + status_code: 405, + headers: vec![("Allow".into(), "GET, OPTIONS".into())], + body: ByteBuf::from(format!("Method {unsupported_method} not allowed.")), + upgrade: None, + streaming_strategy: None, + } +} + +pub fn http_request(req: HttpRequest) -> HttpResponse { + let HttpRequest { + method, + url, + certificate_version, + headers: _, + body: _, + } = req; + + match method.as_str() { + "OPTIONS" => http_options_request(), + "GET" => http_get_request(url, certificate_version), + unsupported_method => method_not_allowed(unsupported_method), + } +} + +/// List of recommended security headers as per https://owasp.org/www-project-secure-headers/ +/// These headers enable browser security features (like limit access to platform apis and set +/// iFrame policies, etc.). +/// +/// Integrity hashes for scripts must be specified. +pub fn security_headers( + integrity_hashes: Vec, + maybe_related_origins: Option>, +) -> Vec { + // Allow related origins to get WebAuthn credentials from one another + let public_key_credentials_get = maybe_related_origins + .clone() + .unwrap_or_default() + .iter() + .fold("self".to_string(), |acc, origin| { + acc + " \"" + origin + "\"" + }); + + vec![ + // X-Frame-Options: DENY + // Prevents the page from being displayed in a frame, iframe, embed or object + // This is a legacy header, also enforced by CSP frame-ancestors directive + ("X-Frame-Options".to_string(), "DENY".to_string()), + // X-Content-Type-Options: nosniff + // Prevents browsers from MIME-sniffing a response away from the declared content-type + // Reduces risk of drive-by downloads and serves as defense against MIME confusion attacks + ("X-Content-Type-Options".to_string(), "nosniff".to_string()), + // Content-Security-Policy (CSP) + // Comprehensive policy to prevent XSS attacks and data injection + // See content_security_policy_header() function for detailed explanation + ( + "Content-Security-Policy".to_string(), + content_security_policy_header(integrity_hashes, maybe_related_origins), + ), + // Strict-Transport-Security (HSTS) + // Forces browsers to use HTTPS for all future requests to this domain + // max-age=31536000: Valid for 1 year (31,536,000 seconds) + // includeSubDomains: Also applies to all subdomains of this domain + ( + "Strict-Transport-Security".to_string(), + "max-age=31536000 ; includeSubDomains".to_string(), + ), + // Referrer-Policy: same-origin + // Controls how much referrer information is sent with outgoing requests + // same-origin: Only send referrer to same-origin requests (no cross-origin leakage) + // Note: "no-referrer" would be more strict but breaks local dev deployment + ("Referrer-Policy".to_string(), "same-origin".to_string()), + // Permissions-Policy (formerly Feature-Policy) + // Controls which browser features and APIs can be used + // Most permissions are denied by default, with specific exceptions: + // - clipboard-write=(self): Allow copying to clipboard from same origin + // - publickey-credentials-get: Allow WebAuthn from self and related origins + // - sync-xhr=(self): Allow synchronous XMLHttpRequest from same origin + ( + "Permissions-Policy".to_string(), + format!( + "accelerometer=(),\ + ambient-light-sensor=(),\ + autoplay=(),\ + battery=(),\ + camera=(),\ + clipboard-read=(),\ + clipboard-write=(self),\ + conversion-measurement=(),\ + cross-origin-isolated=(),\ + display-capture=(),\ + document-domain=(),\ + encrypted-media=(),\ + execution-while-not-rendered=(),\ + execution-while-out-of-viewport=(),\ + focus-without-user-activation=(),\ + fullscreen=(),\ + gamepad=(),\ + geolocation=(),\ + gyroscope=(),\ + hid=(),\ + idle-detection=(),\ + interest-cohort=(),\ + keyboard-map=(),\ + magnetometer=(),\ + microphone=(),\ + midi=(),\ + navigation-override=(),\ + payment=(),\ + picture-in-picture=(),\ + publickey-credentials-get=({public_key_credentials_get}),\ + screen-wake-lock=(),\ + serial=(),\ + speaker-selection=(),\ + sync-script=(),\ + sync-xhr=(self),\ + trust-token-redemption=(),\ + usb=(),\ + vertical-scroll=(),\ + web-share=(),\ + window-placement=(),\ + xr-spatial-tracking=()" + ) + .to_string(), + ), + ] +} + +/// Full content security policy delivered via HTTP response header. +/// +/// CSP directives explained: +/// +/// default-src 'none': +/// Default policy for all resource types - deny everything by default +/// +/// connect-src 'self' https:: +/// Allow network requests to same origin and any HTTPS endpoint +/// - 'self': fetch JS bundles from same origin +/// - https://icp-api.io: official IC HTTP API domain for canister calls +/// - https://*.icp0.io: HTTP fetches for /.well-known/ii-alternative-origins +/// - https://*.ic0.app: legacy domain support for alternative origins +/// +/// img-src 'self' data: https://*.googleusercontent.com: +/// Allow images from same origin, data URIs, and Google profile pictures +/// +/// script-src with 'strict-dynamic': +/// - 'strict-dynamic': Only scripts with listed hashes can load, transitively loaded scripts inherit permission +/// - 'unsafe-eval': Required for WebAssembly modules used by agent-js for BLS signature validation +/// - 'unsafe-inline' https:: Backwards compatibility fallback (ignored by modern browsers) +/// +/// base-uri 'none': +/// Prevents injection of tags that could redirect relative URLs +/// +/// form-action 'none': +/// Prevents forms from being submitted anywhere (II doesn't use forms) +/// +/// style-src 'self' 'unsafe-inline': +/// Allow stylesheets from same origin and inline styles +/// 'unsafe-inline' needed due to how styles are currently handled in the app +/// +/// font-src 'self': +/// Allow fonts only from same origin +/// +/// frame-ancestors and frame-src: +/// Control embedding - allow self and related origins for cross-domain WebAuthn +/// +/// upgrade-insecure-requests (production only): +/// Automatically upgrade HTTP requests to HTTPS (omitted in dev for localhost) +fn content_security_policy_header( + integrity_hashes: Vec, + maybe_related_origins: Option>, +) -> String { + // Always include 'strict-dynamic', but only include integrity hashes if there are some + // (i.e. by default deny scripts and only allow whitelist) + let strict_dynamic = if integrity_hashes.is_empty() { + "'strict-dynamic'".to_string() + } else { + format!( + "'strict-dynamic' {}", + integrity_hashes + .into_iter() + .map(|x| format!("'{x}'")) + .collect::>() + .join(" ") + ) + }; + + let connect_src = "'self' https:"; + + // Allow connecting via http for development purposes + #[cfg(feature = "dev_csp")] + let connect_src = format!("{connect_src} http:"); + + // Allow related origins to embed one another for cross-domain WebAuthn + let frame_src = maybe_related_origins + .unwrap_or_default() + .iter() + .fold("'self'".to_string(), |acc, origin| acc + " " + origin); + + let csp = format!( + "default-src 'none';\ + connect-src {connect_src};\ + img-src 'self' data: https://*.googleusercontent.com;\ + script-src {strict_dynamic} 'unsafe-inline' 'unsafe-eval' https:;\ + base-uri 'none';\ + form-action 'none';\ + style-src 'self' 'unsafe-inline';\ + style-src-elem 'self' 'unsafe-inline';\ + font-src 'self';\ + frame-ancestors {frame_src};\ + frame-src {frame_src};" + ); + // For production builds, upgrade all HTTP connections to HTTPS + // Omitted in dev builds to allow localhost development + #[cfg(not(feature = "dev_csp"))] + let csp = format!("{csp}upgrade-insecure-requests;"); + csp +} + +/// Read an asset from memory, returning the associated HTTP code, content and full list of +/// headers that were certified with the asset. +fn get_asset( + _asset_name: &str, + _certificate_version: Option, +) -> Option<(u16, Vec, Vec)> { + // state::assets_and_signatures(|assets, sigs| { + // let asset = assets.get_certified_asset( + // asset_name, + // certificate_version, + // Some(pruned(labeled_hash(LABEL_SIG, &sigs.root_hash()))), + // )?; + // let shared_headers = assets.shared_headers.clone(); + + // let mut headers = asset.headers.clone(); + // headers.append(&mut shared_headers.to_vec()); + + // Some((asset.status_code, asset.content, headers)) + // }) + todo!() +} diff --git a/src/internet_identity_frontend/src/main.rs b/src/internet_identity_frontend/src/main.rs new file mode 100644 index 0000000000..794821da7c --- /dev/null +++ b/src/internet_identity_frontend/src/main.rs @@ -0,0 +1,11 @@ +use ic_cdk_macros::query; +use internet_identity_interface::http_gateway::{HttpRequest, HttpResponse}; + +mod http; + +#[query] +fn http_request(req: HttpRequest) -> HttpResponse { + http::http_request(req) +} + +fn main() {} From efaabc8460f298e2763998097ca0de6f81313a28 Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Wed, 10 Dec 2025 22:36:25 +0100 Subject: [PATCH 03/16] third --- Cargo.lock | 84 +++++- Cargo.toml | 8 +- src/internet_identity_frontend/Cargo.toml | 3 + src/internet_identity_frontend/src/http.rs | 281 --------------------- src/internet_identity_frontend/src/main.rs | 177 ++++++++++++- 5 files changed, 258 insertions(+), 295 deletions(-) delete mode 100644 src/internet_identity_frontend/src/http.rs diff --git a/Cargo.lock b/Cargo.lock index 28c3ecc05e..8c31604bbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,8 +126,8 @@ dependencies = [ "candid", "ic-cdk 0.16.0", "ic-cdk-macros 0.16.0", - "ic-certification 2.6.0", - "ic-representation-independent-hash", + "ic-certification 3.0.3", + "ic-representation-independent-hash 2.6.0", "include_dir", "internet_identity_interface", "lazy_static", @@ -360,6 +360,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -489,7 +499,7 @@ dependencies = [ "flate2", "hex", "ic-cdk 0.16.0", - "ic-representation-independent-hash", + "ic-representation-independent-hash 2.6.0", "ic-verifiable-credentials", "identity_jose", "internet_identity_interface", @@ -1216,6 +1226,19 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +[[package]] +name = "globset" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax 0.8.4", +] + [[package]] name = "group" version = "0.10.0" @@ -1477,6 +1500,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "ic-asset-certification" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43805022a5e4f408de44ca26396128697a2c39f83f4fdaf33f8aa3ac653d78e" +dependencies = [ + "globset", + "http 1.1.0", + "ic-certification 3.0.3", + "ic-http-certification 3.0.3", + "thiserror 1.0.63", +] + [[package]] name = "ic-canister-sig-creation" version = "1.1.0" @@ -1487,7 +1523,7 @@ dependencies = [ "hex", "ic-cdk 0.14.1", "ic-certification 2.6.0", - "ic-representation-independent-hash", + "ic-representation-independent-hash 2.6.0", "lazy_static", "serde", "serde_bytes", @@ -1657,12 +1693,29 @@ dependencies = [ "candid", "http 0.2.12", "ic-certification 2.6.0", - "ic-representation-independent-hash", + "ic-representation-independent-hash 2.6.0", "serde", "thiserror 1.0.63", "urlencoding", ] +[[package]] +name = "ic-http-certification" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1a65b0ffb568e954750067f660e254f4564394f5c064a88e0e93b2eea4a532" +dependencies = [ + "base64 0.22.1", + "candid", + "http 1.1.0", + "ic-certification 3.0.3", + "ic-representation-independent-hash 3.0.3", + "serde", + "serde_cbor", + "thiserror 1.0.63", + "urlencoding", +] + [[package]] name = "ic-management-canister-types" version = "0.3.2" @@ -1690,6 +1743,16 @@ dependencies = [ "sha2 0.10.9", ] +[[package]] +name = "ic-representation-independent-hash" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2800ba4910f21d9e1cb7b6ecbbbb0f76074bd2e127b4688c57d0936206caa6e" +dependencies = [ + "leb128", + "sha2 0.10.9", +] + [[package]] name = "ic-response-verification" version = "2.6.0" @@ -1704,8 +1767,8 @@ dependencies = [ "ic-cbor", "ic-certificate-verification", "ic-certification 2.6.0", - "ic-http-certification", - "ic-representation-independent-hash", + "ic-http-certification 2.6.0", + "ic-representation-independent-hash 2.6.0", "leb128", "log", "nom", @@ -2051,8 +2114,8 @@ dependencies = [ "ic-cdk 0.16.0", "ic-cdk-macros 0.16.0", "ic-cdk-timers", - "ic-certification 2.6.0", - "ic-http-certification", + "ic-certification 3.0.3", + "ic-http-certification 3.0.3", "ic-metrics-encoder", "ic-response-verification", "ic-stable-structures", @@ -2082,8 +2145,11 @@ name = "internet_identity_frontend" version = "0.1.0" dependencies = [ "candid", + "ic-asset-certification", "ic-cdk 0.16.0", "ic-cdk-macros 0.16.0", + "ic-http-certification 3.0.3", + "include_dir", "internet_identity_interface", "serde_bytes", ] diff --git a/Cargo.toml b/Cargo.toml index 9adfa34b19..7d5b73040c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,8 +28,12 @@ candid_parser = "0.1.2" ic-cdk = "0.16" ic-cdk-macros = "0.16" ic-cdk-timers = "0.10" -ic-certification = "2.6" -ic-http-certification = "2.6" + +# Certification +ic-certification = "3.0.3" +ic-http-certification = "3.0.3" +ic-asset-certification = "3.0.3" + ic-metrics-encoder = "1" ic-representation-independent-hash = "2.6" ic-response-verification = "2.6" diff --git a/src/internet_identity_frontend/Cargo.toml b/src/internet_identity_frontend/Cargo.toml index ec8c7ee38f..23af550bfb 100644 --- a/src/internet_identity_frontend/Cargo.toml +++ b/src/internet_identity_frontend/Cargo.toml @@ -13,6 +13,9 @@ candid.workspace = true ic-cdk.workspace = true ic-cdk-macros.workspace = true +ic-http-certification.workspace = true +ic-asset-certification.workspace = true +include_dir.workspace = true [features] # The dev_csp feature weakens the CSP in oder to facilitate development with a locally deployed II instance. diff --git a/src/internet_identity_frontend/src/http.rs b/src/internet_identity_frontend/src/http.rs deleted file mode 100644 index 4c4636022d..0000000000 --- a/src/internet_identity_frontend/src/http.rs +++ /dev/null @@ -1,281 +0,0 @@ -use internet_identity_interface::http_gateway::{HeaderField, HttpRequest, HttpResponse}; -use serde_bytes::ByteBuf; - -fn http_options_request() -> HttpResponse { - // TODO: Restrict origin to just the II-specific origins. - let headers = vec![("Access-Control-Allow-Origin".to_string(), "*".to_string())]; - - HttpResponse { - // Indicates success without any additional content to be sent in the response content. - status_code: 204, - headers, - body: ByteBuf::from(vec![]), - upgrade: None, - streaming_strategy: None, - } -} - -fn http_get_request(url: String, certificate_version: Option) -> HttpResponse { - let parts: Vec<&str> = url.split('?').collect(); - - match parts[0] { - probably_an_asset => match get_asset(probably_an_asset, certificate_version) { - Some((status_code, content, headers)) => HttpResponse { - status_code, - headers, - body: ByteBuf::from(content), - upgrade: None, - streaming_strategy: None, - }, - None => HttpResponse { - status_code: 404, - headers: security_headers(vec![], None), - body: ByteBuf::from(format!("Asset {probably_an_asset} not found.")), - upgrade: None, - streaming_strategy: None, - }, - }, - } -} - -fn method_not_allowed(unsupported_method: &str) -> HttpResponse { - HttpResponse { - status_code: 405, - headers: vec![("Allow".into(), "GET, OPTIONS".into())], - body: ByteBuf::from(format!("Method {unsupported_method} not allowed.")), - upgrade: None, - streaming_strategy: None, - } -} - -pub fn http_request(req: HttpRequest) -> HttpResponse { - let HttpRequest { - method, - url, - certificate_version, - headers: _, - body: _, - } = req; - - match method.as_str() { - "OPTIONS" => http_options_request(), - "GET" => http_get_request(url, certificate_version), - unsupported_method => method_not_allowed(unsupported_method), - } -} - -/// List of recommended security headers as per https://owasp.org/www-project-secure-headers/ -/// These headers enable browser security features (like limit access to platform apis and set -/// iFrame policies, etc.). -/// -/// Integrity hashes for scripts must be specified. -pub fn security_headers( - integrity_hashes: Vec, - maybe_related_origins: Option>, -) -> Vec { - // Allow related origins to get WebAuthn credentials from one another - let public_key_credentials_get = maybe_related_origins - .clone() - .unwrap_or_default() - .iter() - .fold("self".to_string(), |acc, origin| { - acc + " \"" + origin + "\"" - }); - - vec![ - // X-Frame-Options: DENY - // Prevents the page from being displayed in a frame, iframe, embed or object - // This is a legacy header, also enforced by CSP frame-ancestors directive - ("X-Frame-Options".to_string(), "DENY".to_string()), - // X-Content-Type-Options: nosniff - // Prevents browsers from MIME-sniffing a response away from the declared content-type - // Reduces risk of drive-by downloads and serves as defense against MIME confusion attacks - ("X-Content-Type-Options".to_string(), "nosniff".to_string()), - // Content-Security-Policy (CSP) - // Comprehensive policy to prevent XSS attacks and data injection - // See content_security_policy_header() function for detailed explanation - ( - "Content-Security-Policy".to_string(), - content_security_policy_header(integrity_hashes, maybe_related_origins), - ), - // Strict-Transport-Security (HSTS) - // Forces browsers to use HTTPS for all future requests to this domain - // max-age=31536000: Valid for 1 year (31,536,000 seconds) - // includeSubDomains: Also applies to all subdomains of this domain - ( - "Strict-Transport-Security".to_string(), - "max-age=31536000 ; includeSubDomains".to_string(), - ), - // Referrer-Policy: same-origin - // Controls how much referrer information is sent with outgoing requests - // same-origin: Only send referrer to same-origin requests (no cross-origin leakage) - // Note: "no-referrer" would be more strict but breaks local dev deployment - ("Referrer-Policy".to_string(), "same-origin".to_string()), - // Permissions-Policy (formerly Feature-Policy) - // Controls which browser features and APIs can be used - // Most permissions are denied by default, with specific exceptions: - // - clipboard-write=(self): Allow copying to clipboard from same origin - // - publickey-credentials-get: Allow WebAuthn from self and related origins - // - sync-xhr=(self): Allow synchronous XMLHttpRequest from same origin - ( - "Permissions-Policy".to_string(), - format!( - "accelerometer=(),\ - ambient-light-sensor=(),\ - autoplay=(),\ - battery=(),\ - camera=(),\ - clipboard-read=(),\ - clipboard-write=(self),\ - conversion-measurement=(),\ - cross-origin-isolated=(),\ - display-capture=(),\ - document-domain=(),\ - encrypted-media=(),\ - execution-while-not-rendered=(),\ - execution-while-out-of-viewport=(),\ - focus-without-user-activation=(),\ - fullscreen=(),\ - gamepad=(),\ - geolocation=(),\ - gyroscope=(),\ - hid=(),\ - idle-detection=(),\ - interest-cohort=(),\ - keyboard-map=(),\ - magnetometer=(),\ - microphone=(),\ - midi=(),\ - navigation-override=(),\ - payment=(),\ - picture-in-picture=(),\ - publickey-credentials-get=({public_key_credentials_get}),\ - screen-wake-lock=(),\ - serial=(),\ - speaker-selection=(),\ - sync-script=(),\ - sync-xhr=(self),\ - trust-token-redemption=(),\ - usb=(),\ - vertical-scroll=(),\ - web-share=(),\ - window-placement=(),\ - xr-spatial-tracking=()" - ) - .to_string(), - ), - ] -} - -/// Full content security policy delivered via HTTP response header. -/// -/// CSP directives explained: -/// -/// default-src 'none': -/// Default policy for all resource types - deny everything by default -/// -/// connect-src 'self' https:: -/// Allow network requests to same origin and any HTTPS endpoint -/// - 'self': fetch JS bundles from same origin -/// - https://icp-api.io: official IC HTTP API domain for canister calls -/// - https://*.icp0.io: HTTP fetches for /.well-known/ii-alternative-origins -/// - https://*.ic0.app: legacy domain support for alternative origins -/// -/// img-src 'self' data: https://*.googleusercontent.com: -/// Allow images from same origin, data URIs, and Google profile pictures -/// -/// script-src with 'strict-dynamic': -/// - 'strict-dynamic': Only scripts with listed hashes can load, transitively loaded scripts inherit permission -/// - 'unsafe-eval': Required for WebAssembly modules used by agent-js for BLS signature validation -/// - 'unsafe-inline' https:: Backwards compatibility fallback (ignored by modern browsers) -/// -/// base-uri 'none': -/// Prevents injection of tags that could redirect relative URLs -/// -/// form-action 'none': -/// Prevents forms from being submitted anywhere (II doesn't use forms) -/// -/// style-src 'self' 'unsafe-inline': -/// Allow stylesheets from same origin and inline styles -/// 'unsafe-inline' needed due to how styles are currently handled in the app -/// -/// font-src 'self': -/// Allow fonts only from same origin -/// -/// frame-ancestors and frame-src: -/// Control embedding - allow self and related origins for cross-domain WebAuthn -/// -/// upgrade-insecure-requests (production only): -/// Automatically upgrade HTTP requests to HTTPS (omitted in dev for localhost) -fn content_security_policy_header( - integrity_hashes: Vec, - maybe_related_origins: Option>, -) -> String { - // Always include 'strict-dynamic', but only include integrity hashes if there are some - // (i.e. by default deny scripts and only allow whitelist) - let strict_dynamic = if integrity_hashes.is_empty() { - "'strict-dynamic'".to_string() - } else { - format!( - "'strict-dynamic' {}", - integrity_hashes - .into_iter() - .map(|x| format!("'{x}'")) - .collect::>() - .join(" ") - ) - }; - - let connect_src = "'self' https:"; - - // Allow connecting via http for development purposes - #[cfg(feature = "dev_csp")] - let connect_src = format!("{connect_src} http:"); - - // Allow related origins to embed one another for cross-domain WebAuthn - let frame_src = maybe_related_origins - .unwrap_or_default() - .iter() - .fold("'self'".to_string(), |acc, origin| acc + " " + origin); - - let csp = format!( - "default-src 'none';\ - connect-src {connect_src};\ - img-src 'self' data: https://*.googleusercontent.com;\ - script-src {strict_dynamic} 'unsafe-inline' 'unsafe-eval' https:;\ - base-uri 'none';\ - form-action 'none';\ - style-src 'self' 'unsafe-inline';\ - style-src-elem 'self' 'unsafe-inline';\ - font-src 'self';\ - frame-ancestors {frame_src};\ - frame-src {frame_src};" - ); - // For production builds, upgrade all HTTP connections to HTTPS - // Omitted in dev builds to allow localhost development - #[cfg(not(feature = "dev_csp"))] - let csp = format!("{csp}upgrade-insecure-requests;"); - csp -} - -/// Read an asset from memory, returning the associated HTTP code, content and full list of -/// headers that were certified with the asset. -fn get_asset( - _asset_name: &str, - _certificate_version: Option, -) -> Option<(u16, Vec, Vec)> { - // state::assets_and_signatures(|assets, sigs| { - // let asset = assets.get_certified_asset( - // asset_name, - // certificate_version, - // Some(pruned(labeled_hash(LABEL_SIG, &sigs.root_hash()))), - // )?; - // let shared_headers = assets.shared_headers.clone(); - - // let mut headers = asset.headers.clone(); - // headers.append(&mut shared_headers.to_vec()); - - // Some((asset.status_code, asset.content, headers)) - // }) - todo!() -} diff --git a/src/internet_identity_frontend/src/main.rs b/src/internet_identity_frontend/src/main.rs index 794821da7c..69c9f9eb28 100644 --- a/src/internet_identity_frontend/src/main.rs +++ b/src/internet_identity_frontend/src/main.rs @@ -1,11 +1,182 @@ +use ic_asset_certification::{ + Asset, AssetConfig, AssetEncoding, AssetFallbackConfig, AssetMap, AssetRedirectKind, + AssetRouter, +}; +use ic_cdk::{init, post_upgrade}; use ic_cdk_macros::query; -use internet_identity_interface::http_gateway::{HttpRequest, HttpResponse}; +use ic_http_certification::{ + utils::add_v2_certificate_header, DefaultCelBuilder, HeaderField, HttpCertification, + HttpCertificationPath, HttpCertificationTree, HttpCertificationTreeEntry, HttpRequest, + HttpResponse, StatusCode, CERTIFICATE_EXPRESSION_HEADER_NAME, +}; +use include_dir::{include_dir, Dir}; +use std::{cell::RefCell, rc::Rc}; -mod http; +thread_local! { + static HTTP_TREE: Rc> = Default::default(); + + // initializing the asset router with an HTTP certification tree is optional. + // if direct access to the HTTP certification tree is not needed for certifying + // requests and responses outside of the asset router, then this step can be skipped + // and the asset router can be initialized like so: + // ``` + // static ASSET_ROUTER: RefCell> = Default::default(); + // ``` + static ASSET_ROUTER: RefCell> = RefCell::new(AssetRouter::with_tree(HTTP_TREE.with(|tree| tree.clone()))); +} + +static ASSETS_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/../../dist"); +const IMMUTABLE_ASSET_CACHE_CONTROL: &str = "public, max-age=31536000, immutable"; +const NO_CACHE_ASSET_CACHE_CONTROL: &str = "public, no-cache, no-store"; + +// Public methods +#[init] +fn init() { + certify_all_assets(); +} + +#[post_upgrade] +fn post_upgrade() { + certify_all_assets(); +} + +fn certify_all_assets() { + // 1. Define the asset certification configurations. + let encodings = vec![ + AssetEncoding::Brotli.default_config(), + AssetEncoding::Gzip.default_config(), + ]; + + let asset_configs = vec![ + AssetConfig::File { + path: "index.html".to_string(), + content_type: Some("text/html".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + NO_CACHE_ASSET_CACHE_CONTROL.to_string(), + )]), + fallback_for: vec![AssetFallbackConfig { + scope: "/".to_string(), + status_code: Some(StatusCode::OK), + }], + aliased_by: vec!["/".to_string()], + encodings: encodings.clone(), + }, + AssetConfig::Pattern { + pattern: "**/*.js".to_string(), + content_type: Some("text/javascript".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )]), + encodings: encodings.clone(), + }, + AssetConfig::Pattern { + pattern: "**/*.css".to_string(), + content_type: Some("text/css".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )]), + encodings, + }, + AssetConfig::Pattern { + pattern: "**/*.ico".to_string(), + content_type: Some("image/x-icon".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )]), + encodings: vec![], + }, + AssetConfig::Redirect { + from: "/old-url".to_string(), + to: "/".to_string(), + kind: AssetRedirectKind::Permanent, + headers: get_asset_headers(vec![ + ("content-type".to_string(), "text/plain".to_string()), + ( + "cache-control".to_string(), + NO_CACHE_ASSET_CACHE_CONTROL.to_string(), + ), + ]), + }, + ]; + + // 2. Collect all assets from the frontend build directory. + let mut assets = Vec::new(); + collect_assets(&ASSETS_DIR, &mut assets); + + // 3. Skip certification for the metrics endpoint. + HTTP_TREE.with(|tree| { + let mut tree = tree.borrow_mut(); + + let metrics_tree_path = HttpCertificationPath::exact("/metrics"); + let metrics_certification = HttpCertification::skip(); + let metrics_tree_entry = + HttpCertificationTreeEntry::new(metrics_tree_path, metrics_certification); + + tree.insert(&metrics_tree_entry); + }); + + ASSET_ROUTER.with_borrow_mut(|asset_router| { + // 4. Certify the assets using the `certify_assets` function from the `ic-asset-certification` crate. + if let Err(err) = asset_router.certify_assets(assets, asset_configs) { + ic_cdk::trap(&format!("Failed to certify assets: {}", err)); + } + + // 5. Set the canister's certified data. + ic_cdk::api::set_certified_data(&asset_router.root_hash()); + }); +} + +fn get_asset_headers(additional_headers: Vec) -> Vec { + // set up the default headers and include additional headers provided by the caller + let mut headers = vec![ + ("strict-transport-security".to_string(), "max-age=31536000; includeSubDomains".to_string()), + ("x-frame-options".to_string(), "DENY".to_string()), + ("x-content-type-options".to_string(), "nosniff".to_string()), + ("content-security-policy".to_string(), "default-src 'self'; img-src 'self' data:; form-action 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests; block-all-mixed-content".to_string()), + ("referrer-policy".to_string(), "no-referrer".to_string()), + ("permissions-policy".to_string(), "accelerometer=(),ambient-light-sensor=(),autoplay=(),battery=(),camera=(),display-capture=(),document-domain=(),encrypted-media=(),fullscreen=(),gamepad=(),geolocation=(),gyroscope=(),layout-animations=(self),legacy-image-formats=(self),magnetometer=(),microphone=(),midi=(),oversized-images=(self),payment=(),picture-in-picture=(),publickey-credentials-get=(),speaker-selection=(),sync-xhr=(self),unoptimized-images=(self),unsized-media=(self),usb=(),screen-wake-lock=(),web-share=(),xr-spatial-tracking=()".to_string()), + ("cross-origin-embedder-policy".to_string(), "require-corp".to_string()), + ("cross-origin-opener-policy".to_string(), "same-origin".to_string()), + ]; + headers.extend(additional_headers); + + headers +} + +/// Recursively collect all assets from the provided directory +fn collect_assets<'content, 'path>( + dir: &'content Dir<'path>, + assets: &mut Vec>, +) { + for file in dir.files() { + assets.push(Asset::new(file.path().to_string_lossy(), file.contents())); + } + + for dir in dir.dirs() { + collect_assets(dir, assets); + } +} #[query] fn http_request(req: HttpRequest) -> HttpResponse { - http::http_request(req) + serve_asset(&req) +} + +fn serve_asset(req: &HttpRequest) -> HttpResponse<'static> { + ASSET_ROUTER.with_borrow(|asset_router| { + if let Ok(response) = asset_router.serve_asset( + &ic_cdk::api::data_certificate().expect("No data certificate available"), + req, + ) { + response + } else { + ic_cdk::trap("Failed to serve asset"); + } + }) } fn main() {} From ee7c22006cdaa8daaba07127e58f614f251b10eb Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Wed, 10 Dec 2025 23:02:01 +0100 Subject: [PATCH 04/16] Add security policies from the old canister --- src/internet_identity_frontend/src/main.rs | 244 ++++++++++++++++++--- 1 file changed, 213 insertions(+), 31 deletions(-) diff --git a/src/internet_identity_frontend/src/main.rs b/src/internet_identity_frontend/src/main.rs index 69c9f9eb28..1e7c168f67 100644 --- a/src/internet_identity_frontend/src/main.rs +++ b/src/internet_identity_frontend/src/main.rs @@ -1,13 +1,9 @@ -use ic_asset_certification::{ - Asset, AssetConfig, AssetEncoding, AssetFallbackConfig, AssetMap, AssetRedirectKind, - AssetRouter, -}; +use ic_asset_certification::{Asset, AssetConfig, AssetEncoding, AssetFallbackConfig, AssetRouter}; use ic_cdk::{init, post_upgrade}; use ic_cdk_macros::query; use ic_http_certification::{ - utils::add_v2_certificate_header, DefaultCelBuilder, HeaderField, HttpCertification, - HttpCertificationPath, HttpCertificationTree, HttpCertificationTreeEntry, HttpRequest, - HttpResponse, StatusCode, CERTIFICATE_EXPRESSION_HEADER_NAME, + HeaderField, HttpCertification, HttpCertificationPath, HttpCertificationTree, + HttpCertificationTreeEntry, HttpRequest, HttpResponse, StatusCode, }; use include_dir::{include_dir, Dir}; use std::{cell::RefCell, rc::Rc}; @@ -62,8 +58,9 @@ fn certify_all_assets() { aliased_by: vec!["/".to_string()], encodings: encodings.clone(), }, + // Compressed JavaScript files AssetConfig::Pattern { - pattern: "**/*.js".to_string(), + pattern: "**/*.js.gz".to_string(), content_type: Some("text/javascript".to_string()), headers: get_asset_headers(vec![( "cache-control".to_string(), @@ -71,6 +68,7 @@ fn certify_all_assets() { )]), encodings: encodings.clone(), }, + // CSS files AssetConfig::Pattern { pattern: "**/*.css".to_string(), content_type: Some("text/css".to_string()), @@ -78,7 +76,54 @@ fn certify_all_assets() { "cache-control".to_string(), IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), )]), - encodings, + encodings: encodings.clone(), + }, + // Font files + AssetConfig::Pattern { + pattern: "**/*.woff2".to_string(), + content_type: Some("font/woff2".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )]), + encodings: vec![], + }, + AssetConfig::Pattern { + pattern: "**/*.woff".to_string(), + content_type: Some("font/woff".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )]), + encodings: vec![], + }, + // Image files + AssetConfig::Pattern { + pattern: "**/*.png".to_string(), + content_type: Some("image/png".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )]), + encodings: vec![], + }, + AssetConfig::Pattern { + pattern: "**/*.svg".to_string(), + content_type: Some("image/svg+xml".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )]), + encodings: encodings.clone(), + }, + AssetConfig::Pattern { + pattern: "**/*.webp".to_string(), + content_type: Some("image/webp".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )]), + encodings: vec![], }, AssetConfig::Pattern { pattern: "**/*.ico".to_string(), @@ -89,17 +134,25 @@ fn certify_all_assets() { )]), encodings: vec![], }, - AssetConfig::Redirect { - from: "/old-url".to_string(), - to: "/".to_string(), - kind: AssetRedirectKind::Permanent, - headers: get_asset_headers(vec![ - ("content-type".to_string(), "text/plain".to_string()), - ( - "cache-control".to_string(), - NO_CACHE_ASSET_CACHE_CONTROL.to_string(), - ), - ]), + // WebAssembly files + AssetConfig::Pattern { + pattern: "**/*.wasm".to_string(), + content_type: Some("application/wasm".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )]), + encodings: vec![], + }, + // JSON files + AssetConfig::Pattern { + pattern: "**/*.json".to_string(), + content_type: Some("application/json".to_string()), + headers: get_asset_headers(vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )]), + encodings: encodings.clone(), }, ]; @@ -131,29 +184,158 @@ fn certify_all_assets() { } fn get_asset_headers(additional_headers: Vec) -> Vec { - // set up the default headers and include additional headers provided by the caller + // List of recommended security headers as per https://owasp.org/www-project-secure-headers/ + // These headers enable browser security features (like limit access to platform apis and set + // iFrame policies, etc.) let mut headers = vec![ - ("strict-transport-security".to_string(), "max-age=31536000; includeSubDomains".to_string()), - ("x-frame-options".to_string(), "DENY".to_string()), - ("x-content-type-options".to_string(), "nosniff".to_string()), - ("content-security-policy".to_string(), "default-src 'self'; img-src 'self' data:; form-action 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests; block-all-mixed-content".to_string()), - ("referrer-policy".to_string(), "no-referrer".to_string()), - ("permissions-policy".to_string(), "accelerometer=(),ambient-light-sensor=(),autoplay=(),battery=(),camera=(),display-capture=(),document-domain=(),encrypted-media=(),fullscreen=(),gamepad=(),geolocation=(),gyroscope=(),layout-animations=(self),legacy-image-formats=(self),magnetometer=(),microphone=(),midi=(),oversized-images=(self),payment=(),picture-in-picture=(),publickey-credentials-get=(),speaker-selection=(),sync-xhr=(self),unoptimized-images=(self),unsized-media=(self),usb=(),screen-wake-lock=(),web-share=(),xr-spatial-tracking=()".to_string()), - ("cross-origin-embedder-policy".to_string(), "require-corp".to_string()), - ("cross-origin-opener-policy".to_string(), "same-origin".to_string()), + // X-Frame-Options: DENY + // Prevents the page from being displayed in a frame, iframe, embed or object + // This is a legacy header, also enforced by CSP frame-ancestors directive + ("X-Frame-Options".to_string(), "DENY".to_string()), + // X-Content-Type-Options: nosniff + // Prevents browsers from MIME-sniffing a response away from the declared content-type + // Reduces risk of drive-by downloads and serves as defense against MIME confusion attacks + ("X-Content-Type-Options".to_string(), "nosniff".to_string()), + // Content-Security-Policy (CSP) + // Comprehensive policy to prevent XSS attacks and data injection + ( + "Content-Security-Policy".to_string(), + get_content_security_policy(), + ), + // Strict-Transport-Security (HSTS) + // Forces browsers to use HTTPS for all future requests to this domain + // max-age=31536000: Valid for 1 year (31,536,000 seconds) + // includeSubDomains: Also applies to all subdomains of this domain + ( + "Strict-Transport-Security".to_string(), + "max-age=31536000 ; includeSubDomains".to_string(), + ), + // Referrer-Policy: same-origin + // Controls how much referrer information is sent with outgoing requests + // same-origin: Only send referrer to same-origin requests (no cross-origin leakage) + // Note: "no-referrer" would be more strict but breaks local dev deployment + ("Referrer-Policy".to_string(), "same-origin".to_string()), + // Permissions-Policy (formerly Feature-Policy) + // Controls which browser features and APIs can be used + // Most permissions are denied by default, with specific exceptions: + // - clipboard-write=(self): Allow copying to clipboard from same origin + // - publickey-credentials-get=(self): Allow WebAuthn from same origin + // - sync-xhr=(self): Allow synchronous XMLHttpRequest from same origin + ( + "Permissions-Policy".to_string(), + "accelerometer=(),\ + autoplay=(),\ + camera=(),\ + clipboard-read=(),\ + clipboard-write=(self),\ + display-capture=(),\ + encrypted-media=(),\ + fullscreen=(),\ + gamepad=(),\ + geolocation=(),\ + gyroscope=(),\ + hid=(),\ + idle-detection=(),\ + interest-cohort=(),\ + magnetometer=(),\ + microphone=(),\ + midi=(),\ + payment=(),\ + picture-in-picture=(),\ + publickey-credentials-get=(self),\ + screen-wake-lock=(),\ + serial=(),\ + sync-xhr=(self),\ + usb=(),\ + web-share=(),\ + xr-spatial-tracking=()" + .to_string(), + ), ]; headers.extend(additional_headers); headers } -/// Recursively collect all assets from the provided directory +/// Full content security policy delivered via HTTP response header. +/// +/// CSP directives explained: +/// +/// default-src 'none': +/// Default policy for all resource types - deny everything by default +/// +/// connect-src 'self' https: +/// Allow network requests to same origin and any HTTPS endpoint +/// - 'self': fetch JS bundles from same origin +/// - https://icp-api.io: official IC HTTP API domain for canister calls +/// - https://*.icp0.io: HTTP fetches for /.well-known/ii-alternative-origins +/// - https://*.ic0.app: legacy domain support for alternative origins +/// +/// img-src 'self' data: https://*.googleusercontent.com: +/// Allow images from same origin, data URIs, and Google profile pictures +/// +/// script-src 'unsafe-inline' 'unsafe-eval': +/// - 'unsafe-inline': Allow inline scripts (required for SvelteKit) +/// - 'unsafe-eval': Required for WebAssembly modules used by agent-js for BLS signature validation +/// +/// base-uri 'none': +/// Prevents injection of tags that could redirect relative URLs +/// +/// form-action 'none': +/// Prevents forms from being submitted anywhere (II doesn't use forms) +/// +/// style-src 'self' 'unsafe-inline': +/// Allow stylesheets from same origin and inline styles +/// 'unsafe-inline' needed due to how styles are currently handled in the app +/// +/// font-src 'self': +/// Allow fonts only from same origin +/// +/// frame-ancestors 'self': +/// Control embedding - only allow same origin +/// +/// upgrade-insecure-requests (production only): +/// Automatically upgrade HTTP requests to HTTPS (omitted in dev for localhost) +fn get_content_security_policy() -> String { + let connect_src = "'self' https:"; + + // Allow connecting via http for development purposes + #[cfg(feature = "dev_csp")] + let connect_src = format!("{connect_src} http:"); + + let csp = format!( + "default-src 'none';\ + connect-src {connect_src};\ + img-src 'self' data: https://*.googleusercontent.com;\ + script-src 'self' 'unsafe-inline' 'unsafe-eval';\ + base-uri 'none';\ + form-action 'none';\ + style-src 'self' 'unsafe-inline';\ + style-src-elem 'self' 'unsafe-inline';\ + font-src 'self';\ + frame-ancestors 'self';\ + frame-src 'self';" + ); + + // For production builds, upgrade all HTTP connections to HTTPS + // Omitted in dev builds to allow localhost development + #[cfg(not(feature = "dev_csp"))] + let csp = format!("{csp}upgrade-insecure-requests;"); + + csp +} + +/// Recursively collect all assets from the provided directory. +/// For .gz files, strip the extension and treat them as the base file +/// (since the build script deletes uncompressed .js and .woff2 files). fn collect_assets<'content, 'path>( dir: &'content Dir<'path>, assets: &mut Vec>, ) { for file in dir.files() { - assets.push(Asset::new(file.path().to_string_lossy(), file.contents())); + let path_str = file.path().to_string_lossy().to_string(); + + assets.push(Asset::new(path_str, file.contents())); } for dir in dir.dirs() { From 58e953e7439400b009f99b9a82fdd359db12475e Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Thu, 11 Dec 2025 13:15:35 +0100 Subject: [PATCH 05/16] save --- Cargo.lock | 20 +- src/internet_identity_frontend/Cargo.toml | 11 + src/internet_identity_frontend/src/main.rs | 376 +++++++++++++-------- 3 files changed, 264 insertions(+), 143 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c31604bbe..328f257c75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -199,7 +199,7 @@ dependencies = [ "addr2line", "cfg-if", "libc", - "miniz_oxide 0.8.0", + "miniz_oxide 0.8.9", "object", "rustc-demangle", "windows-targets", @@ -1053,12 +1053,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.33" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide 0.8.9", ] [[package]] @@ -2144,14 +2144,21 @@ dependencies = [ name = "internet_identity_frontend" version = "0.1.0" dependencies = [ + "asset_util", + "base64 0.22.1", "candid", + "flate2", "ic-asset-certification", "ic-cdk 0.16.0", "ic-cdk-macros 0.16.0", + "ic-cdk-timers", "ic-http-certification 3.0.3", "include_dir", "internet_identity_interface", + "lazy_static", "serde_bytes", + "serde_json", + "sha2 0.10.9", ] [[package]] @@ -2482,11 +2489,12 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] diff --git a/src/internet_identity_frontend/Cargo.toml b/src/internet_identity_frontend/Cargo.toml index 23af550bfb..6a9025679c 100644 --- a/src/internet_identity_frontend/Cargo.toml +++ b/src/internet_identity_frontend/Cargo.toml @@ -13,10 +13,21 @@ candid.workspace = true ic-cdk.workspace = true ic-cdk-macros.workspace = true +# Asset certification ic-http-certification.workspace = true ic-asset-certification.workspace = true include_dir.workspace = true +# Asset utilities and encoding +asset_util.workspace = true +base64.workspace = true +serde_json = { version = "1.0", default-features = false, features = ["std"] } +sha2.workspace = true +lazy_static.workspace = true +flate2 = "1.1.5" +ic-cdk-timers.workspace = true + + [features] # The dev_csp feature weakens the CSP in oder to facilitate development with a locally deployed II instance. # In particular, this allows diff --git a/src/internet_identity_frontend/src/main.rs b/src/internet_identity_frontend/src/main.rs index 1e7c168f67..fbb18fb23c 100644 --- a/src/internet_identity_frontend/src/main.rs +++ b/src/internet_identity_frontend/src/main.rs @@ -1,23 +1,25 @@ +use asset_util::{collect_assets, Asset as AssetUtilAsset, ContentEncoding, ContentType}; +use base64::engine::general_purpose::STANDARD as BASE64; +use base64::Engine; +use candid::Encode; +use flate2::read::GzDecoder; use ic_asset_certification::{Asset, AssetConfig, AssetEncoding, AssetFallbackConfig, AssetRouter}; -use ic_cdk::{init, post_upgrade}; +use ic_cdk::{api, init, post_upgrade}; use ic_cdk_macros::query; use ic_http_certification::{ - HeaderField, HttpCertification, HttpCertificationPath, HttpCertificationTree, - HttpCertificationTreeEntry, HttpRequest, HttpResponse, StatusCode, + HeaderField, HttpCertificationTree, HttpRequest, HttpResponse, StatusCode, }; use include_dir::{include_dir, Dir}; +use internet_identity_interface::internet_identity::types::InternetIdentityInit; +use lazy_static::lazy_static; +use serde_json::json; +use sha2::Digest; +use std::io::Read; + use std::{cell::RefCell, rc::Rc}; thread_local! { static HTTP_TREE: Rc> = Default::default(); - - // initializing the asset router with an HTTP certification tree is optional. - // if direct access to the HTTP certification tree is not needed for certifying - // requests and responses outside of the asset router, then this step can be skipped - // and the asset router can be initialized like so: - // ``` - // static ASSET_ROUTER: RefCell> = Default::default(); - // ``` static ASSET_ROUTER: RefCell> = RefCell::new(AssetRouter::with_tree(HTTP_TREE.with(|tree| tree.clone()))); } @@ -25,19 +27,89 @@ static ASSETS_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/../../dist"); const IMMUTABLE_ASSET_CACHE_CONTROL: &str = "public, max-age=31536000, immutable"; const NO_CACHE_ASSET_CACHE_CONTROL: &str = "public, no-cache, no-store"; -// Public methods +// Default configuration for the frontend canister +lazy_static! { + static ref DEFAULT_CONFIG: InternetIdentityInit = InternetIdentityInit { + assigned_user_number_range: None, + archive_config: None, + canister_creation_cycles_cost: None, + register_rate_limit: None, + captcha_config: Some(internet_identity_interface::internet_identity::types::CaptchaConfig { + max_unsolved_captchas: 50, + captcha_trigger: internet_identity_interface::internet_identity::types::CaptchaTrigger::Static( + internet_identity_interface::internet_identity::types::StaticCaptchaTrigger::CaptchaDisabled + ), + }), + related_origins: Some(vec![ + "https://identity.internetcomputer.org".to_string(), + "https://identity.ic0.app".to_string(), + ]), + new_flow_origins: None, + openid_configs: Some(vec![ + internet_identity_interface::internet_identity::types::OpenIdConfig { + name: "Google".to_string(), + logo: "https://www.google.com/favicon.ico".to_string(), + issuer: "https://accounts.google.com".to_string(), + client_id: "775077467414-q1ajffledt8bjj82p2rl5a09co8cf4rf.apps.googleusercontent.com".to_string(), + jwks_uri: "https://www.googleapis.com/oauth2/v3/certs".to_string(), + auth_uri: "https://accounts.google.com/o/oauth2/v2/auth".to_string(), + auth_scope: vec!["openid".to_string(), "email".to_string(), "profile".to_string()], + fedcm_uri: None, + }, + ]), + analytics_config: None, + fetch_root_key: None, + enable_dapps_explorer: None, + is_production: None, + dummy_auth: None, + }; +} + #[init] -fn init() { - certify_all_assets(); +fn init(init_arg: Option) { + let config = init_arg.unwrap_or_else(|| DEFAULT_CONFIG.clone()); + ic_cdk_timers::set_timer(std::time::Duration::from_secs(0), move || { + certify_all_assets(config) + }); } #[post_upgrade] fn post_upgrade() { - certify_all_assets(); + init(None); } -fn certify_all_assets() { - // 1. Define the asset certification configurations. +fn certify_all_assets(init: InternetIdentityInit) { + let static_assets = get_static_assets(&init); + + // 2. Extract integrity hashes for inline scripts from HTML files + let integrity_hashes = static_assets + .iter() + .filter(|asset| asset.content_type == ContentType::HTML) + .fold(vec![], |mut acc, e| { + let content = std::str::from_utf8(&e.content).unwrap().to_string(); + // We need to import extract_inline_scripts? It is defined in file (Line 396). + for inlined in extract_inline_scripts(content).iter() { + let hash = sha2::Sha384::digest(inlined.as_bytes()); + let hash = BASE64.encode(hash); + let hash = format!("sha384-{hash}"); + acc.push(hash); + } + acc + }); + + let mut router_assets = Vec::new(); + for asset in static_assets { + let content = if asset.encoding == ContentEncoding::GZip { + let mut decoder = GzDecoder::new(&asset.content[..]); + let mut s = Vec::new(); + decoder.read_to_end(&mut s).unwrap(); + s + } else { + asset.content + }; + router_assets.push(Asset::new(asset.url_path, content)); + } + let encodings = vec![ AssetEncoding::Brotli.default_config(), AssetEncoding::Gzip.default_config(), @@ -47,10 +119,13 @@ fn certify_all_assets() { AssetConfig::File { path: "index.html".to_string(), content_type: Some("text/html".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - NO_CACHE_ASSET_CACHE_CONTROL.to_string(), - )]), + headers: get_asset_headers( + integrity_hashes.clone(), + vec![( + "cache-control".to_string(), + NO_CACHE_ASSET_CACHE_CONTROL.to_string(), + )], + ), fallback_for: vec![AssetFallbackConfig { scope: "/".to_string(), status_code: Some(StatusCode::OK), @@ -58,132 +133,95 @@ fn certify_all_assets() { aliased_by: vec!["/".to_string()], encodings: encodings.clone(), }, - // Compressed JavaScript files - AssetConfig::Pattern { - pattern: "**/*.js.gz".to_string(), - content_type: Some("text/javascript".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )]), - encodings: encodings.clone(), - }, - // CSS files AssetConfig::Pattern { pattern: "**/*.css".to_string(), content_type: Some("text/css".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )]), + headers: get_asset_headers( + vec![], + vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )], + ), encodings: encodings.clone(), }, - // Font files AssetConfig::Pattern { - pattern: "**/*.woff2".to_string(), - content_type: Some("font/woff2".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )]), - encodings: vec![], + pattern: "**/*.js".to_string(), + content_type: Some("text/javascript".to_string()), + headers: get_asset_headers( + vec![], + vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )], + ), + encodings: encodings.clone(), }, AssetConfig::Pattern { - pattern: "**/*.woff".to_string(), - content_type: Some("font/woff".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )]), + pattern: "**/*.ico".to_string(), + content_type: Some("image/x-icon".to_string()), + headers: get_asset_headers( + vec![], + vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )], + ), encodings: vec![], }, - // Image files AssetConfig::Pattern { pattern: "**/*.png".to_string(), content_type: Some("image/png".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )]), + headers: get_asset_headers( + vec![], + vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )], + ), encodings: vec![], }, AssetConfig::Pattern { - pattern: "**/*.svg".to_string(), - content_type: Some("image/svg+xml".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )]), + pattern: "**/*.woff2".to_string(), + content_type: Some("font/woff2".to_string()), + headers: get_asset_headers( + vec![], + vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )], + ), encodings: encodings.clone(), }, - AssetConfig::Pattern { - pattern: "**/*.webp".to_string(), - content_type: Some("image/webp".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )]), - encodings: vec![], - }, - AssetConfig::Pattern { - pattern: "**/*.ico".to_string(), - content_type: Some("image/x-icon".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )]), - encodings: vec![], - }, - // WebAssembly files - AssetConfig::Pattern { - pattern: "**/*.wasm".to_string(), - content_type: Some("application/wasm".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )]), - encodings: vec![], - }, - // JSON files AssetConfig::Pattern { pattern: "**/*.json".to_string(), content_type: Some("application/json".to_string()), - headers: get_asset_headers(vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )]), - encodings: encodings.clone(), + headers: get_asset_headers( + vec![], + vec![( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + )], + ), + encodings: vec![], }, ]; - // 2. Collect all assets from the frontend build directory. - let mut assets = Vec::new(); - collect_assets(&ASSETS_DIR, &mut assets); - - // 3. Skip certification for the metrics endpoint. - HTTP_TREE.with(|tree| { - let mut tree = tree.borrow_mut(); - - let metrics_tree_path = HttpCertificationPath::exact("/metrics"); - let metrics_certification = HttpCertification::skip(); - let metrics_tree_entry = - HttpCertificationTreeEntry::new(metrics_tree_path, metrics_certification); - - tree.insert(&metrics_tree_entry); - }); - - ASSET_ROUTER.with_borrow_mut(|asset_router| { - // 4. Certify the assets using the `certify_assets` function from the `ic-asset-certification` crate. - if let Err(err) = asset_router.certify_assets(assets, asset_configs) { + ASSET_ROUTER.with(|asset_router| { + if let Err(err) = asset_router + .borrow_mut() + .certify_assets(router_assets, asset_configs) + { ic_cdk::trap(&format!("Failed to certify assets: {}", err)); } - - // 5. Set the canister's certified data. - ic_cdk::api::set_certified_data(&asset_router.root_hash()); + ic_cdk::api::set_certified_data(&asset_router.borrow().root_hash()); }); } -fn get_asset_headers(additional_headers: Vec) -> Vec { +fn get_asset_headers( + integrity_hashes: Vec, + additional_headers: Vec, +) -> Vec { // List of recommended security headers as per https://owasp.org/www-project-secure-headers/ // These headers enable browser security features (like limit access to platform apis and set // iFrame policies, etc.) @@ -200,7 +238,7 @@ fn get_asset_headers(additional_headers: Vec) -> Vec { // Comprehensive policy to prevent XSS attacks and data injection ( "Content-Security-Policy".to_string(), - get_content_security_policy(), + get_content_security_policy(integrity_hashes), ), // Strict-Transport-Security (HSTS) // Forces browsers to use HTTPS for all future requests to this domain @@ -296,18 +334,32 @@ fn get_asset_headers(additional_headers: Vec) -> Vec { /// /// upgrade-insecure-requests (production only): /// Automatically upgrade HTTP requests to HTTPS (omitted in dev for localhost) -fn get_content_security_policy() -> String { +fn get_content_security_policy(integrity_hashes: Vec) -> String { let connect_src = "'self' https:"; // Allow connecting via http for development purposes #[cfg(feature = "dev_csp")] let connect_src = format!("{connect_src} http:"); + // Build script-src with integrity hashes if provided + let script_src = if integrity_hashes.is_empty() { + "'self' 'unsafe-inline' 'unsafe-eval'".to_string() + } else { + format!( + "'self' 'unsafe-inline' 'unsafe-eval' {}", + integrity_hashes + .into_iter() + .map(|x| format!("'{x}'")) + .collect::>() + .join(" ") + ) + }; + let csp = format!( "default-src 'none';\ connect-src {connect_src};\ img-src 'self' data: https://*.googleusercontent.com;\ - script-src 'self' 'unsafe-inline' 'unsafe-eval';\ + script-src {script_src};\ base-uri 'none';\ form-action 'none';\ style-src 'self' 'unsafe-inline';\ @@ -325,22 +377,72 @@ fn get_content_security_policy() -> String { csp } -/// Recursively collect all assets from the provided directory. -/// For .gz files, strip the extension and treat them as the base file -/// (since the build script deletes uncompressed .js and .woff2 files). -fn collect_assets<'content, 'path>( - dir: &'content Dir<'path>, - assets: &mut Vec>, -) { - for file in dir.files() { - let path_str = file.path().to_string_lossy().to_string(); +/// Gets the static assets with HTML fixup and well-known endpoints +fn get_static_assets(config: &InternetIdentityInit) -> Vec { + // Collect assets and fix up HTML files + let mut assets: Vec = collect_assets(&ASSETS_DIR, None) + .into_iter() + .map(|mut asset| { + if asset.content_type == ContentType::HTML { + asset.content = fixup_html(std::str::from_utf8(&asset.content).unwrap(), config) + .as_bytes() + .to_vec(); + } + asset + }) + .collect(); - assets.push(Asset::new(path_str, file.contents())); - } + // Add .well-known/ic-domains for custom domain support + let ic_domains_content = b"identity.internetcomputer.org\nbeta.identity.ic0.app\nbeta.identity.internetcomputer.org\nid.ai\nbeta.id.ai\nwww.id.ai".to_vec(); + assets.push(AssetUtilAsset { + url_path: "/.well-known/ic-domains".to_string(), + content: ic_domains_content, + encoding: ContentEncoding::Identity, + content_type: ContentType::OCTETSTREAM, + }); - for dir in dir.dirs() { - collect_assets(dir, assets); + // Add .well-known/webauthn for passkey sharing if related_origins is configured + if let Some(related_origins) = &config.related_origins { + let content = json!({ + "origins": related_origins, + }) + .to_string() + .into_bytes(); + assets.push(AssetUtilAsset { + url_path: "/.well-known/webauthn".to_string(), + content, + encoding: ContentEncoding::Identity, + content_type: ContentType::JSON, + }); } + + assets +} + +/// Fix up HTML pages by injecting canister ID and canister config +fn fixup_html(html: &str, config: &InternetIdentityInit) -> String { + let canister_id = api::id(); + // Encode config to base64-encoded Candid to avoid JSON escaping issues + let encoded_config = BASE64.encode(Encode!(config).unwrap()); + html.replace( + r#" Vec { + content + .match_indices("').unwrap(); + let inline_start = tag_open_start + tag_open_len + 1; + let tag_close_start = content[inline_start..].find("").unwrap(); + content[(inline_start)..(inline_start + tag_close_start)].to_string() + }) + .collect() } #[query] @@ -348,9 +450,9 @@ fn http_request(req: HttpRequest) -> HttpResponse { serve_asset(&req) } -fn serve_asset(req: &HttpRequest) -> HttpResponse<'static> { - ASSET_ROUTER.with_borrow(|asset_router| { - if let Ok(response) = asset_router.serve_asset( +fn serve_asset<'a>(req: &'a HttpRequest<'a>) -> HttpResponse<'static> { + ASSET_ROUTER.with(|asset_router| { + if let Ok(response) = asset_router.borrow().serve_asset( &ic_cdk::api::data_certificate().expect("No data certificate available"), req, ) { From a632761dec469110ae7b46a20fd6a8689a4d6401 Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 12 Dec 2025 20:12:06 +0100 Subject: [PATCH 06/16] Save first working ii 2.0 frontend --- src/internet_identity_frontend/src/main.rs | 28 +++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/internet_identity_frontend/src/main.rs b/src/internet_identity_frontend/src/main.rs index fbb18fb23c..811883b5ae 100644 --- a/src/internet_identity_frontend/src/main.rs +++ b/src/internet_identity_frontend/src/main.rs @@ -1,7 +1,7 @@ use asset_util::{collect_assets, Asset as AssetUtilAsset, ContentEncoding, ContentType}; use base64::engine::general_purpose::STANDARD as BASE64; use base64::Engine; -use candid::Encode; +use candid::{Encode, Principal}; use flate2::read::GzDecoder; use ic_asset_certification::{Asset, AssetConfig, AssetEncoding, AssetFallbackConfig, AssetRouter}; use ic_cdk::{api, init, post_upgrade}; @@ -68,9 +68,7 @@ lazy_static! { #[init] fn init(init_arg: Option) { let config = init_arg.unwrap_or_else(|| DEFAULT_CONFIG.clone()); - ic_cdk_timers::set_timer(std::time::Duration::from_secs(0), move || { - certify_all_assets(config) - }); + certify_all_assets(config); } #[post_upgrade] @@ -133,6 +131,18 @@ fn certify_all_assets(init: InternetIdentityInit) { aliased_by: vec!["/".to_string()], encodings: encodings.clone(), }, + AssetConfig::Pattern { + pattern: "**/*.html".to_string(), + content_type: Some("text/html".to_string()), + headers: get_asset_headers( + integrity_hashes.clone(), + vec![( + "cache-control".to_string(), + NO_CACHE_ASSET_CACHE_CONTROL.to_string(), + )], + ), + encodings: vec![AssetEncoding::Identity.default_config()], + }, AssetConfig::Pattern { pattern: "**/*.css".to_string(), content_type: Some("text/css".to_string()), @@ -421,7 +431,7 @@ fn get_static_assets(config: &InternetIdentityInit) -> Vec { /// Fix up HTML pages by injecting canister ID and canister config fn fixup_html(html: &str, config: &InternetIdentityInit) -> String { - let canister_id = api::id(); + let canister_id = Principal::from_text("u6s2n-gx777-77774-qaaba-cai").unwrap(); // Encode config to base64-encoded Candid to avoid JSON escaping issues let encoded_config = BASE64.encode(Encode!(config).unwrap()); html.replace( @@ -446,15 +456,11 @@ fn extract_inline_scripts(content: String) -> Vec { } #[query] -fn http_request(req: HttpRequest) -> HttpResponse { - serve_asset(&req) -} - -fn serve_asset<'a>(req: &'a HttpRequest<'a>) -> HttpResponse<'static> { +fn http_request(request: HttpRequest) -> HttpResponse { ASSET_ROUTER.with(|asset_router| { if let Ok(response) = asset_router.borrow().serve_asset( &ic_cdk::api::data_certificate().expect("No data certificate available"), - req, + &request, ) { response } else { From c0acbf31840834da848d5b4101829c6a1e24aefb Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Wed, 17 Dec 2025 12:03:12 +0100 Subject: [PATCH 07/16] Run e2e tests for the new ii frontend canister --- .github/workflows/canister-tests.yml | 6 +- src/internet_identity_frontend/src/main.rs | 12 ++-- vite.config.ts | 77 +++++++++++++--------- 3 files changed, 58 insertions(+), 37 deletions(-) diff --git a/.github/workflows/canister-tests.yml b/.github/workflows/canister-tests.yml index 414a0df809..9359ac1fb7 100644 --- a/.github/workflows/canister-tests.yml +++ b/.github/workflows/canister-tests.yml @@ -540,7 +540,11 @@ jobs: - name: Run dev server id: dev-server-start run: | - TLS_DEV_SERVER=1 NO_HOT_RELOAD=1 npm run dev | tee -a > dev-server-logs.txt & + # -------------------- + # !!! DO NOT MERGE !!! + # TODO: Remove SEPARATE_FRONTEND_CANISTER=1 + # -------------------- + SEPARATE_FRONTEND_CANISTER=1 TLS_DEV_SERVER=1 NO_HOT_RELOAD=1 npm run dev | tee -a > dev-server-logs.txt & dev_server_pid=$! echo "dev_server_pid=$dev_server_pid" >> "$GITHUB_OUTPUT" diff --git a/src/internet_identity_frontend/src/main.rs b/src/internet_identity_frontend/src/main.rs index 811883b5ae..09c8abc32b 100644 --- a/src/internet_identity_frontend/src/main.rs +++ b/src/internet_identity_frontend/src/main.rs @@ -4,13 +4,15 @@ use base64::Engine; use candid::{Encode, Principal}; use flate2::read::GzDecoder; use ic_asset_certification::{Asset, AssetConfig, AssetEncoding, AssetFallbackConfig, AssetRouter}; -use ic_cdk::{api, init, post_upgrade}; +use ic_cdk::{init, post_upgrade}; use ic_cdk_macros::query; use ic_http_certification::{ HeaderField, HttpCertificationTree, HttpRequest, HttpResponse, StatusCode, }; use include_dir::{include_dir, Dir}; -use internet_identity_interface::internet_identity::types::InternetIdentityInit; +use internet_identity_interface::internet_identity::types::{ + DummyAuthConfig, InternetIdentityInit, +}; use lazy_static::lazy_static; use serde_json::json; use sha2::Digest; @@ -61,7 +63,9 @@ lazy_static! { fetch_root_key: None, enable_dapps_explorer: None, is_production: None, - dummy_auth: None, + dummy_auth: Some(Some( + DummyAuthConfig { prompt_for_index: true } + )), }; } @@ -431,7 +435,7 @@ fn get_static_assets(config: &InternetIdentityInit) -> Vec { /// Fix up HTML pages by injecting canister ID and canister config fn fixup_html(html: &str, config: &InternetIdentityInit) -> String { - let canister_id = Principal::from_text("u6s2n-gx777-77774-qaaba-cai").unwrap(); + let canister_id = Principal::from_text("uxrrr-q7777-77774-qaaaq-cai").unwrap(); // Encode config to base64-encoded Candid to avoid JSON escaping issues let encoded_config = BASE64.encode(Encode!(config).unwrap()); html.replace( diff --git a/vite.config.ts b/vite.config.ts index c0a1e56d63..d262da7d1d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -75,15 +75,28 @@ export default defineConfig(({ command, mode }): UserConfig => { }, ...(process.env.NO_HOT_RELOAD === "1" ? [ - { - hosts: [ - "id.ai", - "identity.ic0.app", - "identity.internetcomputer.org", - ], - canisterName: "internet_identity", - }, - ] + { + hosts: process.env.SEPARATE_FRONTEND_CANISTER === "1" ? [ + "identity.ic0.app", + "identity.internetcomputer.org", + ] : [ + "id.ai", + "identity.ic0.app", + "identity.internetcomputer.org", + ], + canisterName: "internet_identity", + }, + ] + : []), + ...(process.env.NO_HOT_RELOAD === "1" && process.env.SEPARATE_FRONTEND_CANISTER === "1" + ? [ + { + hosts: [ + "id.ai", + ], + canisterName: "internet_identity_frontend", + }, + ] : []), ], }), @@ -101,29 +114,29 @@ export default defineConfig(({ command, mode }): UserConfig => { command !== "serve" ? {} : { - https: process.env.TLS_DEV_SERVER === "1" ? {} : undefined, - proxy: { - "/api": `http://127.0.0.1:${readReplicaPort()}`, - }, - allowedHosts: ["icp-api.io"], - cors: { - origin: [ - "https://id.ai", - "https://identity.internetcomputer.org", - "https://identity.ic0.app", - "https://nice-name.com", - "https://nice-issuer-custom-orig.com", - "https://be2us-64aaa-aaaaa-qaabq-cai.icp0.io", - // Test app - "https://bd3sg-teaaa-aaaaa-qaaba-cai.icp0.io", - // Test app - "https://bd3sg-teaaa-aaaaa-qaaba-cai.ic0.app", - // Issuer - "https://bkyz2-fmaaa-aaaaa-qaaaq-cai.icp0.io", - // Issuer - "https://bkyz2-fmaaa-aaaaa-qaaaq-cai.ic0.app", - ], - }, + https: process.env.TLS_DEV_SERVER === "1" ? {} : undefined, + proxy: { + "/api": `http://127.0.0.1:${readReplicaPort()}`, + }, + allowedHosts: ["icp-api.io"], + cors: { + origin: [ + "https://id.ai", + "https://identity.internetcomputer.org", + "https://identity.ic0.app", + "https://nice-name.com", + "https://nice-issuer-custom-orig.com", + "https://be2us-64aaa-aaaaa-qaabq-cai.icp0.io", + // Test app + "https://bd3sg-teaaa-aaaaa-qaaba-cai.icp0.io", + // Test app + "https://bd3sg-teaaa-aaaaa-qaaba-cai.ic0.app", + // Issuer + "https://bkyz2-fmaaa-aaaaa-qaaaq-cai.icp0.io", + // Issuer + "https://bkyz2-fmaaa-aaaaa-qaaaq-cai.ic0.app", + ], }, + }, }; }); From 0eaec04ac6b50932cf044754e3cf09bac65f184f Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 19 Dec 2025 13:56:07 +0100 Subject: [PATCH 08/16] first --- Cargo.lock | 138 ++++++++++-------- Cargo.toml | 10 +- demos/test-app/Cargo.lock | 6 +- demos/vc_issuer/Cargo.lock | 2 +- src/archive/archive.did | 1 - src/archive/src/main.rs | 3 - src/internet_identity/internet_identity.did | 1 - src/internet_identity/src/http.rs | 6 - .../tests/integration/http.rs | 16 +- src/internet_identity_interface/Cargo.toml | 1 + .../src/http_gateway.rs | 67 ++++++++- 11 files changed, 156 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d5c22a191..764bf0bf22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,8 +126,8 @@ dependencies = [ "candid", "ic-cdk 0.16.0", "ic-cdk-macros 0.16.0", - "ic-certification 2.6.0", - "ic-representation-independent-hash", + "ic-certification 3.0.3", + "ic-representation-independent-hash 3.0.3", "include_dir", "internet_identity_interface", "lazy_static", @@ -223,12 +223,6 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -386,29 +380,29 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cached" -version = "0.47.0" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b0116662497bc24e4b177c90eaf8870e39e2714c3fcfa296327a93f593fc21" +checksum = "9718806c4a2fe9e8a56fd736f97b340dd10ed1be8ed733ed50449f351dc33cae" dependencies = [ "ahash", "cached_proc_macro", "cached_proc_macro_types", "hashbrown 0.14.5", - "instant", "once_cell", "thiserror 1.0.63", + "web-time", ] [[package]] name = "cached_proc_macro" -version = "0.18.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c878c71c2821aa2058722038a59a67583a4240524687c6028571c9b395ded61f" +checksum = "2f42a145ed2d10dce2191e1dcf30cfccfea9026660e143662ba5eec4017d5daa" dependencies = [ "darling", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] @@ -489,7 +483,7 @@ dependencies = [ "flate2", "hex", "ic-cdk 0.16.0", - "ic-representation-independent-hash", + "ic-representation-independent-hash 3.0.3", "ic-verifiable-credentials", "identity_jose", "internet_identity_interface", @@ -586,7 +580,7 @@ dependencies = [ "clap_lex", "indexmap 1.9.3", "once_cell", - "strsim", + "strsim 0.10.0", "termcolor", "textwrap", ] @@ -753,9 +747,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.14.4" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -763,27 +757,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.14.4" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim", - "syn 1.0.109", + "strsim 0.11.1", + "syn 2.0.87", ] [[package]] name = "darling_macro" -version = "0.14.4" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] @@ -1261,7 +1255,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.1.0", + "http", "indexmap 2.5.0", "slab", "tokio", @@ -1357,17 +1351,6 @@ version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.1.0" @@ -1386,7 +1369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http", ] [[package]] @@ -1397,7 +1380,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http", "http-body", "pin-project-lite", ] @@ -1424,7 +1407,7 @@ dependencies = [ "futures-channel", "futures-util", "h2", - "http 1.1.0", + "http", "http-body", "httparse", "itoa", @@ -1441,7 +1424,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http 1.1.0", + "http", "hyper", "hyper-util", "rustls", @@ -1464,7 +1447,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "http 1.1.0", + "http", "http-body", "hyper", "ipnet", @@ -1487,7 +1470,7 @@ dependencies = [ "hex", "ic-cdk 0.14.1", "ic-certification 2.6.0", - "ic-representation-independent-hash", + "ic-representation-independent-hash 2.6.0", "lazy_static", "serde", "serde_bytes", @@ -1498,12 +1481,12 @@ dependencies = [ [[package]] name = "ic-cbor" -version = "2.6.0" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b0e48b4166c891e79d624f3a184b4a7c145d307576872d9a46dedb8c73ea8f" +checksum = "a0efada960a6c9fb023f45ed95801b757a033dafba071e4f386c6c112ca186d9" dependencies = [ "candid", - "ic-certification 2.6.0", + "ic-certification 3.0.3", "leb128", "nom", "thiserror 1.0.63", @@ -1607,14 +1590,14 @@ dependencies = [ [[package]] name = "ic-certificate-verification" -version = "2.6.0" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "586e09b06a93d930f6a33f5f909bb11d2e4a06be3635dd5da1eb0e6554b7dae4" +checksum = "546dfd75c4da975b9f1c55ef3da461321ab4313a66da653af321ed6dc7319b61" dependencies = [ "cached", "candid", "ic-cbor", - "ic-certification 2.6.0", + "ic-certification 3.0.3", "lazy_static", "leb128", "miracl_core_bls12381", @@ -1650,15 +1633,17 @@ dependencies = [ [[package]] name = "ic-http-certification" -version = "2.6.0" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff0b97e949845039149dc5e7ea6a7c12ee4333bb402e37bc507904643c7b3e41" +checksum = "3d1a65b0ffb568e954750067f660e254f4564394f5c064a88e0e93b2eea4a532" dependencies = [ + "base64 0.22.1", "candid", - "http 0.2.12", - "ic-certification 2.6.0", - "ic-representation-independent-hash", + "http", + "ic-certification 3.0.3", + "ic-representation-independent-hash 3.0.3", "serde", + "serde_cbor", "thiserror 1.0.63", "urlencoding", ] @@ -1690,22 +1675,32 @@ dependencies = [ "sha2 0.10.9", ] +[[package]] +name = "ic-representation-independent-hash" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2800ba4910f21d9e1cb7b6ecbbbb0f76074bd2e127b4688c57d0936206caa6e" +dependencies = [ + "leb128", + "sha2 0.10.9", +] + [[package]] name = "ic-response-verification" -version = "2.6.0" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef02ef84189d61a7d39889b7e9a3ae212d45c3df293513f7b2568027fd08a8" +checksum = "9dda1e3e44089054b2dd05c49467cda769d08df7862c4235c3d8869f8a3f9f19" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "candid", "flate2", "hex", - "http 0.2.12", + "http", "ic-cbor", "ic-certificate-verification", - "ic-certification 2.6.0", + "ic-certification 3.0.3", "ic-http-certification", - "ic-representation-independent-hash", + "ic-representation-independent-hash 3.0.3", "leb128", "log", "nom", @@ -2051,7 +2046,7 @@ dependencies = [ "ic-cdk 0.16.0", "ic-cdk-macros 0.16.0", "ic-cdk-timers", - "ic-certification 2.6.0", + "ic-certification 3.0.3", "ic-http-certification", "ic-metrics-encoder", "ic-response-verification", @@ -2083,6 +2078,7 @@ version = "0.1.0" dependencies = [ "candid", "ic-cdk 0.16.0", + "ic-http-certification", "serde", "serde_bytes", ] @@ -3094,7 +3090,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 1.1.0", + "http", "http-body", "http-body-util", "hyper", @@ -3682,6 +3678,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "strum" version = "0.25.0" @@ -3999,7 +4001,7 @@ dependencies = [ "bitflags 2.6.0", "bytes", "futures-util", - "http 1.1.0", + "http", "http-body", "iri-string", "pin-project-lite", @@ -4336,6 +4338,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.26.5" diff --git a/Cargo.toml b/Cargo.toml index 524f703df6..3b058a1047 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,11 +27,7 @@ candid_parser = "0.1.2" ic-cdk = "0.16" ic-cdk-macros = "0.16" ic-cdk-timers = "0.10" -ic-certification = "2.6" -ic-http-certification = "2.6" ic-metrics-encoder = "1" -ic-representation-independent-hash = "2.6" -ic-response-verification = "2.6" ic-stable-structures = "0.6" ic-verifiable-credentials = { git = "https://github.com/dfinity/verifiable-credentials-sdk", rev = "b74c746ea5361af3da207a2c957be4a951f7a72c" } ic-canister-sig-creation = "1.1" @@ -48,3 +44,9 @@ serde_cbor = "0.11" sha2 = "0.10" rsa = "0.9.7" minicbor = "1.0.0" + +# Certification +ic-certification = "3.0.3" +ic-http-certification = "3.0.3" +ic-representation-independent-hash = "3.0.3" +ic-response-verification = "3.0.3" \ No newline at end of file diff --git a/demos/test-app/Cargo.lock b/demos/test-app/Cargo.lock index 2aaecd3c21..663a8e820d 100644 --- a/demos/test-app/Cargo.lock +++ b/demos/test-app/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "anyhow" @@ -233,9 +233,9 @@ dependencies = [ [[package]] name = "ic-certification" -version = "2.6.0" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64ee3d8b6e81b51f245716d3e0badb63c283c00f3c9fb5d5219afc30b5bf821" +checksum = "ffb40d73f9f8273dc6569a68859003bbd467c9dc6d53c6fd7d174742f857209d" dependencies = [ "hex", "serde", diff --git a/demos/vc_issuer/Cargo.lock b/demos/vc_issuer/Cargo.lock index ec6a1b28e2..8ebc62c932 100644 --- a/demos/vc_issuer/Cargo.lock +++ b/demos/vc_issuer/Cargo.lock @@ -100,7 +100,7 @@ dependencies = [ "candid", "ic-cdk 0.16.0", "ic-cdk-macros 0.16.0", - "ic-certification 2.6.0", + "ic-certification 3.0.3", "ic-representation-independent-hash", "include_dir", "internet_identity_interface", diff --git a/src/archive/archive.did b/src/archive/archive.did index 1a0d72a28b..e25d5948de 100644 --- a/src/archive/archive.did +++ b/src/archive/archive.did @@ -191,7 +191,6 @@ type HttpResponse = record { headers : vec HeaderField; body : blob; upgrade : opt bool; - streaming_strategy : opt StreamingStrategy; }; type StreamingCallbackHttpResponse = record { diff --git a/src/archive/src/main.rs b/src/archive/src/main.rs index d8cece7ee0..ae35164555 100644 --- a/src/archive/src/main.rs +++ b/src/archive/src/main.rs @@ -552,7 +552,6 @@ fn http_request(req: HttpRequest) -> HttpResponse { headers, body: ByteBuf::from(body), upgrade: None, - streaming_strategy: None, } } Err(err) => HttpResponse { @@ -560,7 +559,6 @@ fn http_request(req: HttpRequest) -> HttpResponse { headers: vec![], body: ByteBuf::from(format!("Failed to encode metrics: {err}")), upgrade: None, - streaming_strategy: None, }, } } @@ -569,7 +567,6 @@ fn http_request(req: HttpRequest) -> HttpResponse { headers: vec![], body: ByteBuf::from(format!("Asset {path} not found.")), upgrade: None, - streaming_strategy: None, }, } } diff --git a/src/internet_identity/internet_identity.did b/src/internet_identity/internet_identity.did index 22ea667f9d..592680f39b 100644 --- a/src/internet_identity/internet_identity.did +++ b/src/internet_identity/internet_identity.did @@ -27,7 +27,6 @@ type HttpResponse = record { headers : vec HeaderField; body : blob; upgrade : opt bool; - streaming_strategy : opt StreamingStrategy; }; type StreamingCallbackHttpResponse = record { diff --git a/src/internet_identity/src/http.rs b/src/internet_identity/src/http.rs index cac29d0ff6..d414fe58fe 100644 --- a/src/internet_identity/src/http.rs +++ b/src/internet_identity/src/http.rs @@ -17,7 +17,6 @@ fn http_options_request() -> HttpResponse { headers, body: ByteBuf::from(vec![]), upgrade: None, - streaming_strategy: None, } } @@ -40,7 +39,6 @@ fn http_get_request(url: String, certificate_version: Option) -> HttpRespon headers, body: ByteBuf::from(body), upgrade: None, - streaming_strategy: None, } } Err(err) => HttpResponse { @@ -48,7 +46,6 @@ fn http_get_request(url: String, certificate_version: Option) -> HttpRespon headers: security_headers(vec![], None), body: ByteBuf::from(format!("Failed to encode metrics: {err}")), upgrade: None, - streaming_strategy: None, }, }, probably_an_asset => match get_asset(probably_an_asset, certificate_version) { @@ -57,14 +54,12 @@ fn http_get_request(url: String, certificate_version: Option) -> HttpRespon headers, body: ByteBuf::from(content), upgrade: None, - streaming_strategy: None, }, None => HttpResponse { status_code: 404, headers: security_headers(vec![], None), body: ByteBuf::from(format!("Asset {probably_an_asset} not found.")), upgrade: None, - streaming_strategy: None, }, }, } @@ -76,7 +71,6 @@ fn method_not_allowed(unsupported_method: &str) -> HttpResponse { headers: vec![("Allow".into(), "GET, OPTIONS".into())], body: ByteBuf::from(format!("Method {unsupported_method} not allowed.")), upgrade: None, - streaming_strategy: None, } } diff --git a/src/internet_identity/tests/integration/http.rs b/src/internet_identity/tests/integration/http.rs index 8f8de6ee88..6381e3fa4e 100644 --- a/src/internet_identity/tests/integration/http.rs +++ b/src/internet_identity/tests/integration/http.rs @@ -1393,18 +1393,10 @@ fn verify_response_certification( min_certification_version: u16, ) -> VerificationInfo { verify_request_response_pair( - ic_http_certification::HttpRequest { - method: request.method, - url: request.url, - headers: request.headers, - body: request.body.into_vec(), - }, - ic_http_certification::HttpResponse { - status_code: http_response.status_code, - headers: http_response.headers, - body: http_response.body.into_vec(), - upgrade: None, - }, + request.try_into().expect("Cannot represent HttpRequest"), + http_response + .try_into() + .expect("Cannot represent HttpResponse"), canister_id.as_slice(), time(env) as u128, Duration::from_secs(300).as_nanos(), diff --git a/src/internet_identity_interface/Cargo.toml b/src/internet_identity_interface/Cargo.toml index c98ae82d8c..e8bcdd74ef 100644 --- a/src/internet_identity_interface/Cargo.toml +++ b/src/internet_identity_interface/Cargo.toml @@ -10,3 +10,4 @@ serde_bytes.workspace = true candid.workspace = true serde.workspace = true ic-cdk.workspace = true +ic-http-certification.workspace = true \ No newline at end of file diff --git a/src/internet_identity_interface/src/http_gateway.rs b/src/internet_identity_interface/src/http_gateway.rs index 2784678879..c5bfdfd248 100644 --- a/src/internet_identity_interface/src/http_gateway.rs +++ b/src/internet_identity_interface/src/http_gateway.rs @@ -1,7 +1,10 @@ //! Types as defined by the HTTP gateway spec. //! See https://internetcomputer.org/docs/current/references/ic-interface-spec/#http-gateway-interface +use std::borrow::Cow; + use candid::{define_function, CandidType, Deserialize}; +use ic_http_certification; use serde_bytes::ByteBuf; pub type HeaderField = (String, String); @@ -34,11 +37,73 @@ pub struct HttpRequest { pub certificate_version: Option, } +impl TryFrom for ic_http_certification::HttpRequest<'_> { + type Error = String; + + fn try_from(request: HttpRequest) -> Result { + let HttpRequest { + method, + url, + headers, + body, + certificate_version, + } = request; + + let method = ic_http_certification::Method::from_bytes(&method.as_bytes()) + .map_err(|_| format!("Invalid HTTP method: {}", method))? + .into(); + + let body = Cow::Owned(body.into_vec()); + + let mut builder = Self::builder() + .with_method(method) + .with_url(url) + .with_headers(headers) + .with_body(body); + + if let Some(certificate_version) = certificate_version { + builder = builder.with_certificate_version(certificate_version); + } + + Ok(builder.build()) + } +} + +impl TryFrom for ic_http_certification::HttpResponse<'_> { + type Error = String; + + fn try_from( + response: HttpResponse, + ) -> Result, Self::Error> { + let HttpResponse { + status_code, + headers, + body, + upgrade, + } = response; + + let body = Cow::Owned(body.into_vec()); + + let status_code = ic_http_certification::StatusCode::from_u16(status_code) + .map_err(|_| "Invalid HTTP status code".to_string())?; + + let mut builder = ic_http_certification::HttpResponse::builder() + .with_status_code(status_code) + .with_headers(headers) + .with_body(body); + + if let Some(upgrade) = upgrade { + builder = builder.with_upgrade(upgrade); + } + + Ok(builder.build()) + } +} + #[derive(Clone, Debug, CandidType, Deserialize)] pub struct HttpResponse { pub status_code: u16, pub headers: Vec, pub body: ByteBuf, pub upgrade: Option, - pub streaming_strategy: Option, } From 7c6758c9f57e8f753845120cd47b291c3d8d307a Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 19 Dec 2025 14:12:14 +0100 Subject: [PATCH 09/16] lint --- src/internet_identity_interface/src/http_gateway.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/internet_identity_interface/src/http_gateway.rs b/src/internet_identity_interface/src/http_gateway.rs index c5bfdfd248..d34aba6276 100644 --- a/src/internet_identity_interface/src/http_gateway.rs +++ b/src/internet_identity_interface/src/http_gateway.rs @@ -49,9 +49,8 @@ impl TryFrom for ic_http_certification::HttpRequest<'_> { certificate_version, } = request; - let method = ic_http_certification::Method::from_bytes(&method.as_bytes()) - .map_err(|_| format!("Invalid HTTP method: {}", method))? - .into(); + let method = ic_http_certification::Method::from_bytes(method.as_bytes()) + .map_err(|_| format!("Invalid HTTP method: {}", method))?; let body = Cow::Owned(body.into_vec()); From 19b48ef7b6930cc0425e044bc060468cdc319e5d Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 19 Dec 2025 14:23:57 +0100 Subject: [PATCH 10/16] Fix demos --- demos/vc_issuer/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/vc_issuer/Cargo.toml b/demos/vc_issuer/Cargo.toml index 5c1abca859..75652254e2 100644 --- a/demos/vc_issuer/Cargo.toml +++ b/demos/vc_issuer/Cargo.toml @@ -15,7 +15,7 @@ candid = "0.10" ic-canister-sig-creation = "1.1" ic-cdk = "0.16" ic-cdk-macros = "0.16" -ic-certification = "2.6" +ic-certification = "3.0.3" ic-stable-structures = "0.6" ic-verifiable-credentials = {git = "https://github.com/dfinity/verifiable-credentials-sdk", rev = "b74c746ea5361af3da207a2c957be4a951f7a72c"} # unfortunately required because we have a transitive dependency on getrandom From 272f1074972c2d00bd4bf5290689cda8588a1bc4 Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 19 Dec 2025 14:45:18 +0100 Subject: [PATCH 11/16] address ai review comments --- src/internet_identity_interface/src/http_gateway.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internet_identity_interface/src/http_gateway.rs b/src/internet_identity_interface/src/http_gateway.rs index d34aba6276..0ec8ea6417 100644 --- a/src/internet_identity_interface/src/http_gateway.rs +++ b/src/internet_identity_interface/src/http_gateway.rs @@ -37,7 +37,7 @@ pub struct HttpRequest { pub certificate_version: Option, } -impl TryFrom for ic_http_certification::HttpRequest<'_> { +impl TryFrom for ic_http_certification::HttpRequest<'static> { type Error = String; fn try_from(request: HttpRequest) -> Result { @@ -84,7 +84,7 @@ impl TryFrom for ic_http_certification::HttpResponse<'_> { let body = Cow::Owned(body.into_vec()); let status_code = ic_http_certification::StatusCode::from_u16(status_code) - .map_err(|_| "Invalid HTTP status code".to_string())?; + .map_err(|_| format!("Invalid HTTP status code: {}", status_code))?; let mut builder = ic_http_certification::HttpResponse::builder() .with_status_code(status_code) From 42313330a0907e9ad858b64d9a95df061407eca8 Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 19 Dec 2025 14:51:26 +0100 Subject: [PATCH 12/16] nit --- src/internet_identity_interface/src/http_gateway.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internet_identity_interface/src/http_gateway.rs b/src/internet_identity_interface/src/http_gateway.rs index 0ec8ea6417..c4f5d8eaa2 100644 --- a/src/internet_identity_interface/src/http_gateway.rs +++ b/src/internet_identity_interface/src/http_gateway.rs @@ -68,7 +68,7 @@ impl TryFrom for ic_http_certification::HttpRequest<'static> { } } -impl TryFrom for ic_http_certification::HttpResponse<'_> { +impl TryFrom for ic_http_certification::HttpResponse<'static> { type Error = String; fn try_from( From 225c2da5e7c5ec73e5fbaa79426dc493c04775e9 Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 19 Dec 2025 14:59:26 +0100 Subject: [PATCH 13/16] Update Cargo.lock --- demos/vc_issuer/Cargo.lock | 44 +++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/demos/vc_issuer/Cargo.lock b/demos/vc_issuer/Cargo.lock index 8ebc62c932..cb62202829 100644 --- a/demos/vc_issuer/Cargo.lock +++ b/demos/vc_issuer/Cargo.lock @@ -101,7 +101,7 @@ dependencies = [ "ic-cdk 0.16.0", "ic-cdk-macros 0.16.0", "ic-certification 3.0.3", - "ic-representation-independent-hash", + "ic-representation-independent-hash 3.0.3", "include_dir", "internet_identity_interface", "lazy_static", @@ -457,7 +457,7 @@ dependencies = [ "flate2", "hex", "ic-cdk 0.16.0", - "ic-representation-independent-hash", + "ic-representation-independent-hash 3.0.3", "ic-verifiable-credentials", "identity_jose", "internet_identity_interface", @@ -1387,7 +1387,7 @@ dependencies = [ "hex", "ic-cdk 0.14.1", "ic-certification 2.6.0", - "ic-representation-independent-hash", + "ic-representation-independent-hash 2.6.0", "lazy_static", "serde", "serde_bytes", @@ -1550,12 +1550,29 @@ dependencies = [ "candid", "http 0.2.12", "ic-certification 2.6.0", - "ic-representation-independent-hash", + "ic-representation-independent-hash 2.6.0", "serde", "thiserror 1.0.63", "urlencoding", ] +[[package]] +name = "ic-http-certification" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1a65b0ffb568e954750067f660e254f4564394f5c064a88e0e93b2eea4a532" +dependencies = [ + "base64 0.22.1", + "candid", + "http 1.1.0", + "ic-certification 3.0.3", + "ic-representation-independent-hash 3.0.3", + "serde", + "serde_cbor", + "thiserror 1.0.63", + "urlencoding", +] + [[package]] name = "ic-management-canister-types" version = "0.3.2" @@ -1577,6 +1594,16 @@ dependencies = [ "sha2 0.10.9", ] +[[package]] +name = "ic-representation-independent-hash" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2800ba4910f21d9e1cb7b6ecbbbb0f76074bd2e127b4688c57d0936206caa6e" +dependencies = [ + "leb128", + "sha2 0.10.9", +] + [[package]] name = "ic-response-verification" version = "2.6.0" @@ -1591,8 +1618,8 @@ dependencies = [ "ic-cbor", "ic-certificate-verification", "ic-certification 2.6.0", - "ic-http-certification", - "ic-representation-independent-hash", + "ic-http-certification 2.6.0", + "ic-representation-independent-hash 2.6.0", "leb128", "log", "nom", @@ -1871,6 +1898,7 @@ version = "0.1.0" dependencies = [ "candid", "ic-cdk 0.16.0", + "ic-http-certification 3.0.3", "serde", "serde_bytes", ] @@ -3843,9 +3871,9 @@ dependencies = [ "ic-canister-sig-creation", "ic-cdk 0.16.0", "ic-cdk-macros 0.16.0", - "ic-certification 2.6.0", + "ic-certification 3.0.3", "ic-crypto-getrandom-for-wasm", - "ic-http-certification", + "ic-http-certification 2.6.0", "ic-response-verification", "ic-stable-structures", "ic-verifiable-credentials", From d04d215b3f31f2cbf53c2ccf2d433ffc94cf0855 Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 19 Dec 2025 16:38:23 +0100 Subject: [PATCH 14/16] Commit lock files --- Cargo.lock | 4960 +++++++++++++++++++++++++++++++++++++ demos/test-app/Cargo.lock | 50 +- 2 files changed, 5008 insertions(+), 2 deletions(-) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000..5970c52b90 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4960 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "ar_archive_writer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a" +dependencies = [ + "object", +] + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "archive" +version = "0.1.0" +dependencies = [ + "candid", + "candid_parser", + "canister_tests", + "hex", + "ic-cdk 0.16.1", + "ic-cdk-macros 0.16.0", + "ic-cdk-timers", + "ic-metrics-encoder", + "ic-stable-structures", + "internet_identity_interface", + "pocket-ic", + "regex", + "serde", + "serde_bytes", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + +[[package]] +name = "asset_util" +version = "0.1.0" +dependencies = [ + "base64 0.22.1", + "candid", + "ic-cdk 0.16.1", + "ic-cdk-macros 0.16.0", + "ic-certification 3.0.3", + "ic-representation-independent-hash", + "include_dir", + "internet_identity_interface", + "lazy_static", + "serde", + "serde_cbor", + "sha2 0.10.9", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.5.0", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "getrandom 0.2.16", + "instant", + "rand 0.8.5", +] + +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base256emoji" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e9430d9a245a77c92176e649af6e275f20839a48389859d1661e9a128d077c" +dependencies = [ + "const-str", + "match-lookup", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "binread" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16598dfc8e6578e9b597d9910ba2e73618385dc9f4b1d43dd92c349d6be6418f" +dependencies = [ + "binread_derive", + "lazy_static", + "rustversion", +] + +[[package]] +name = "binread_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9672209df1714ee804b1f4d4f68c8eb2a90b1f7a07acf472f88ce198ef1fed" +dependencies = [ + "either", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bls12_381" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3c196a77437e7cc2fb515ce413a6401291578b5afc8ecb29a3c7ab957f05941" +dependencies = [ + "digest 0.9.0", + "ff 0.12.1", + "group 0.12.1", + "pairing 0.22.0", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "bls12_381_plus" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdcbc984ce4bbbba587f9415ecfd5ed15c59b33defe276482c517b26a6a6716" +dependencies = [ + "arrayref", + "elliptic-curve", + "ff 0.13.1", + "group 0.13.0", + "hex", + "pairing 0.23.0", + "rand_core 0.6.4", + "serde", + "sha2 0.10.9", + "subtle", + "zeroize", +] + +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" + +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" + +[[package]] +name = "cached" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9718806c4a2fe9e8a56fd736f97b340dd10ed1be8ed733ed50449f351dc33cae" +dependencies = [ + "ahash", + "cached_proc_macro", + "cached_proc_macro_types", + "hashbrown 0.14.5", + "once_cell", + "thiserror 1.0.69", + "web-time", +] + +[[package]] +name = "cached_proc_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f42a145ed2d10dce2191e1dcf30cfccfea9026660e143662ba5eec4017d5daa" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "cached_proc_macro_types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" + +[[package]] +name = "camino" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +dependencies = [ + "serde_core", +] + +[[package]] +name = "candid" +version = "0.10.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8037a01ec09d6c06883a38bad4f47b8d06158ad360b841e0ae5707c9884dfaf6" +dependencies = [ + "anyhow", + "binread", + "byteorder", + "candid_derive", + "hex", + "ic_principal", + "leb128", + "num-bigint", + "num-traits", + "paste", + "pretty", + "serde", + "serde_bytes", + "stacker", + "thiserror 1.0.69", +] + +[[package]] +name = "candid_derive" +version = "0.10.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb45f4d5eff3805598ee633dd80f8afb306c023249d34b5b7dfdc2080ea1df2e" +dependencies = [ + "lazy_static", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "candid_parser" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48a3da76f989cd350b7342c64c6c6008341bb6186f6832ef04e56dc50ba0fd76" +dependencies = [ + "anyhow", + "candid", + "codespan-reporting", + "convert_case", + "hex", + "lalrpop", + "lalrpop-util", + "logos", + "num-bigint", + "pretty", + "thiserror 1.0.69", +] + +[[package]] +name = "canister_tests" +version = "0.1.0" +dependencies = [ + "base64 0.22.1", + "candid", + "flate2", + "hex", + "ic-cdk 0.16.1", + "ic-representation-independent-hash", + "ic-verifiable-credentials", + "identity_jose", + "internet_identity_interface", + "lazy_static", + "pocket-ic", + "regex", + "serde", + "serde_bytes", + "serde_cbor", + "sha2 0.10.9", + "url", +] + +[[package]] +name = "captcha" +version = "0.0.9" +source = "git+https://github.com/dfinity/captcha?rev=9c0d2dd9bf519e255eaa239d9f4e9fdc83f65391#9c0d2dd9bf519e255eaa239d9f4e9fdc83f65391" +dependencies = [ + "base64 0.13.1", + "hound", + "image", + "lodepng", + "rand 0.8.5", + "serde_json", +] + +[[package]] +name = "cargo-license" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653542a7f5db653bf79ee4b6455c23f8e6b8a9c38c6310fbe14528728c14bd19" +dependencies = [ + "ansi_term", + "anyhow", + "atty", + "cargo_metadata", + "clap", + "csv", + "getopts", + "semver", + "serde", + "serde_derive", + "serde_json", + "toml", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "cc" +version = "1.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "atty", + "bitflags 1.3.2", + "clap_derive", + "clap_lex", + "indexmap 1.9.3", + "once_cell", + "strsim 0.10.0", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +dependencies = [ + "heck 0.4.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width 0.1.14", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-str" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + +[[package]] +name = "csv-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" +dependencies = [ + "memchr", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.111", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + +[[package]] +name = "data-encoding-macro" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" +dependencies = [ + "data-encoding", + "syn 2.0.111", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +dependencies = [ + "powerfmt", + "serde_core", +] + +[[package]] +name = "did_url_parser" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8095a051342f829a19c51eca6949da516b4de2b324e94a1e0dc8c5eb87ebe439" +dependencies = [ + "form_urlencoded", + "serde", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff 0.13.1", + "generic-array", + "group 0.13.0", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "ena" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" +dependencies = [ + "serde", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "ff" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "bitvec", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "libz-rs-sys", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getopts" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +dependencies = [ + "unicode-width 0.2.2", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "globset" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax 0.8.8", +] + +[[package]] +name = "group" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" +dependencies = [ + "byteorder", + "ff 0.10.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff 0.12.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.12.1", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hound" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "humantime" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "ic-asset-certification" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43805022a5e4f408de44ca26396128697a2c39f83f4fdaf33f8aa3ac653d78e" +dependencies = [ + "globset", + "http", + "ic-certification 3.0.3", + "ic-http-certification", + "thiserror 1.0.69", +] + +[[package]] +name = "ic-canister-sig-creation" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b2a507d1bebb111fc8c76098468e4de9c745e9b9ef160a079568ae1d6f7fef" +dependencies = [ + "candid", + "hex", + "ic-certification 3.0.3", + "ic-representation-independent-hash", + "ic0 1.0.1", + "lazy_static", + "serde", + "serde_bytes", + "serde_cbor", + "sha2 0.10.9", + "thiserror 2.0.17", +] + +[[package]] +name = "ic-cbor" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0efada960a6c9fb023f45ed95801b757a033dafba071e4f386c6c112ca186d9" +dependencies = [ + "candid", + "ic-certification 3.0.3", + "leb128", + "nom", + "thiserror 1.0.69", +] + +[[package]] +name = "ic-cdk" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c4f1eea1e5ca52801fbc8363cfb67c3218741afaa63fc001b80a0d283d60ca" +dependencies = [ + "candid", + "ic-cdk-executor", + "ic-cdk-macros 0.13.2", + "ic0 0.23.0", + "serde", + "serde_bytes", +] + +[[package]] +name = "ic-cdk" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a50afd39a4c2022ca6cbdf15dbd653b33eeaae9010748b74006bbd717aa7c51a" +dependencies = [ + "candid", + "ic-cdk-executor", + "ic-cdk-macros 0.16.0", + "ic0 0.23.0", + "serde", + "serde_bytes", + "slotmap", +] + +[[package]] +name = "ic-cdk-executor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "903057edd3d4ff4b3fe44a64eaee1ceb73f579ba29e3ded372b63d291d7c16c2" + +[[package]] +name = "ic-cdk-macros" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a45800053d80a6df839a71aaea5797e723188c0b992618208ca3b941350c7355" +dependencies = [ + "candid", + "proc-macro2", + "quote", + "serde", + "serde_tokenstream 0.1.7", + "syn 1.0.109", +] + +[[package]] +name = "ic-cdk-macros" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4d857135deef20cc7ea8f3869a30cd9cfeb1392b3a81043790b2cd82adc3e0" +dependencies = [ + "candid", + "proc-macro2", + "quote", + "serde", + "serde_tokenstream 0.2.2", + "syn 2.0.111", +] + +[[package]] +name = "ic-cdk-timers" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a298faf67b21a8c4b1dddf60f15ae4c9e981bfcfd61456f7e0a1ae187269738" +dependencies = [ + "futures", + "ic-cdk 0.16.1", + "ic0 0.23.0", + "serde", + "serde_bytes", + "slotmap", +] + +[[package]] +name = "ic-certificate-verification" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "546dfd75c4da975b9f1c55ef3da461321ab4313a66da653af321ed6dc7319b61" +dependencies = [ + "cached", + "candid", + "ic-cbor", + "ic-certification 3.0.3", + "lazy_static", + "leb128", + "miracl_core_bls12381", + "nom", + "parking_lot", + "sha2 0.10.9", + "thiserror 1.0.69", +] + +[[package]] +name = "ic-certification" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64ee3d8b6e81b51f245716d3e0badb63c283c00f3c9fb5d5219afc30b5bf821" +dependencies = [ + "hex", + "serde", + "serde_bytes", + "sha2 0.10.9", +] + +[[package]] +name = "ic-certification" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb40d73f9f8273dc6569a68859003bbd467c9dc6d53c6fd7d174742f857209d" +dependencies = [ + "hex", + "serde", + "serde_bytes", + "sha2 0.10.9", +] + +[[package]] +name = "ic-http-certification" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1a65b0ffb568e954750067f660e254f4564394f5c064a88e0e93b2eea4a532" +dependencies = [ + "base64 0.22.1", + "candid", + "http", + "ic-certification 3.0.3", + "ic-representation-independent-hash", + "serde", + "serde_cbor", + "thiserror 1.0.69", + "urlencoding", +] + +[[package]] +name = "ic-management-canister-types" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea7e5b8a0f7c3b320d9450ac950547db4f24a31601b5d398f9680b64427455d2" +dependencies = [ + "candid", + "serde", + "serde_bytes", +] + +[[package]] +name = "ic-metrics-encoder" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b5c7628eac357aecda461130f8074468be5aa4d258a002032d82d817f79f1f8" + +[[package]] +name = "ic-representation-independent-hash" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2800ba4910f21d9e1cb7b6ecbbbb0f76074bd2e127b4688c57d0936206caa6e" +dependencies = [ + "leb128", + "sha2 0.10.9", +] + +[[package]] +name = "ic-response-verification" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dda1e3e44089054b2dd05c49467cda769d08df7862c4235c3d8869f8a3f9f19" +dependencies = [ + "base64 0.22.1", + "candid", + "flate2", + "hex", + "http", + "ic-cbor", + "ic-certificate-verification", + "ic-certification 3.0.3", + "ic-http-certification", + "ic-representation-independent-hash", + "leb128", + "log", + "nom", + "sha2 0.10.9", + "thiserror 1.0.69", + "urlencoding", +] + +[[package]] +name = "ic-signature-verification" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8a8115bcd1bfa672e2213a66326b3c93483d3a7a29e33dff6e381c7786c091" +dependencies = [ + "ic-canister-sig-creation", + "ic-certification 2.6.0", + "ic-verify-bls-signature 0.2.0", + "ic_principal", + "serde", + "serde_bytes", + "serde_cbor", + "sha2 0.10.9", +] + +[[package]] +name = "ic-signature-verification" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9de5065430a9b1a61934f7e4a65474a7a11658db84a8b5b0c42baced6c33752" +dependencies = [ + "ic-canister-sig-creation", + "ic-certification 2.6.0", + "ic-verify-bls-signature 0.6.0", + "ic_principal", + "serde", + "serde_bytes", + "serde_cbor", + "sha2 0.10.9", +] + +[[package]] +name = "ic-stable-structures" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d30d4cf17aff1024e13133897048bcba580e063c9000571ab766ca37e2996f4" +dependencies = [ + "ic_principal", +] + +[[package]] +name = "ic-transport-types" +version = "0.40.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2e7706e55836e8104c98149ec0796d20d5213fef972ac01b544657d410f1883" +dependencies = [ + "candid", + "hex", + "ic-certification 3.0.3", + "leb128", + "serde", + "serde_bytes", + "serde_cbor", + "serde_repr", + "sha2 0.10.9", + "thiserror 2.0.17", +] + +[[package]] +name = "ic-verifiable-credentials" +version = "0.1.0" +source = "git+https://github.com/dfinity/verifiable-credentials-sdk?rev=b74c746ea5361af3da207a2c957be4a951f7a72c#b74c746ea5361af3da207a2c957be4a951f7a72c" +dependencies = [ + "candid", + "ic-canister-sig-creation", + "ic-certification 2.6.0", + "ic-signature-verification 0.1.0", + "identity_core", + "identity_credential", + "identity_jose", + "serde", + "serde_bytes", + "serde_cbor", + "serde_json", + "sha2 0.10.9", +] + +[[package]] +name = "ic-verify-bls-signature" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f1f8d75f50002970cc2136f909287bf1d59024fbc80ebffbee871afcbd237" +dependencies = [ + "bls12_381", + "hex", + "lazy_static", + "pairing 0.22.0", + "rand 0.6.5", + "sha2 0.9.9", +] + +[[package]] +name = "ic-verify-bls-signature" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6c4261586eb473fe1219de63186a98e554985d5fd6f3488036c8fb82452e27" +dependencies = [ + "hex", + "ic_bls12_381", + "lazy_static", + "pairing 0.23.0", + "sha2 0.10.9", +] + +[[package]] +name = "ic0" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de254dd67bbd58073e23dc1c8553ba12fa1dc610a19de94ad2bbcd0460c067f" + +[[package]] +name = "ic0" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1499d08fd5be8f790d477e1865d63bab6a8d748300e141270c4296e6d5fdd6bc" + +[[package]] +name = "ic_bls12_381" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e828f9e804ccefe4b9b15b2195f474c60fd4f95ccd14fcb554eb6d7dfafde3" +dependencies = [ + "digest 0.10.7", + "ff 0.13.1", + "group 0.13.0", + "pairing 0.23.0", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "ic_principal" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1762deb6f7c8d8c2bdee4b6c5a47b60195b74e9b5280faa5ba29692f8e17429c" +dependencies = [ + "arbitrary", + "crc32fast", + "data-encoding", + "serde", + "sha2 0.10.9", + "thiserror 1.0.69", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "identity_core" +version = "1.3.1" +source = "git+https://github.com/dfinity/identity.rs.git?rev=aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8#aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8" +dependencies = [ + "ic-cdk 0.13.6", + "iota-crypto", + "multibase", + "serde", + "serde_json", + "strum 0.25.0", + "thiserror 1.0.69", + "time", + "url", + "zeroize", +] + +[[package]] +name = "identity_credential" +version = "1.3.1" +source = "git+https://github.com/dfinity/identity.rs.git?rev=aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8#aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8" +dependencies = [ + "async-trait", + "identity_core", + "identity_did", + "identity_document", + "identity_verification", + "indexmap 2.12.1", + "itertools", + "once_cell", + "serde", + "serde-aux", + "serde_json", + "serde_repr", + "strum 0.25.0", + "thiserror 1.0.69", + "url", +] + +[[package]] +name = "identity_did" +version = "1.3.1" +source = "git+https://github.com/dfinity/identity.rs.git?rev=aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8#aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8" +dependencies = [ + "did_url_parser", + "form_urlencoded", + "identity_core", + "serde", + "strum 0.25.0", + "thiserror 1.0.69", +] + +[[package]] +name = "identity_document" +version = "1.3.1" +source = "git+https://github.com/dfinity/identity.rs.git?rev=aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8#aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8" +dependencies = [ + "did_url_parser", + "identity_core", + "identity_did", + "identity_verification", + "indexmap 2.12.1", + "serde", + "strum 0.25.0", + "thiserror 1.0.69", +] + +[[package]] +name = "identity_jose" +version = "1.3.1" +source = "git+https://github.com/dfinity/identity.rs.git?rev=aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8#aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8" +dependencies = [ + "bls12_381_plus", + "identity_core", + "iota-crypto", + "json-proof-token", + "serde", + "serde_json", + "subtle", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "identity_verification" +version = "1.3.1" +source = "git+https://github.com/dfinity/identity.rs.git?rev=aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8#aa510ef7f441848d6c78058fe51ad4ad1d9bd5d8" +dependencies = [ + "identity_core", + "identity_did", + "identity_jose", + "serde", + "serde_json", + "strum 0.25.0", + "thiserror 1.0.69", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-traits", + "png", +] + +[[package]] +name = "include_dir" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg 1.5.0", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "internet_identity" +version = "0.1.0" +dependencies = [ + "asset_util", + "base64 0.22.1", + "candid", + "candid_parser", + "canister_tests", + "captcha", + "flate2", + "getrandom 0.2.16", + "hex", + "ic-canister-sig-creation", + "ic-cdk 0.16.1", + "ic-cdk-macros 0.16.0", + "ic-cdk-timers", + "ic-certification 3.0.3", + "ic-http-certification", + "ic-metrics-encoder", + "ic-response-verification", + "ic-stable-structures", + "ic-verifiable-credentials", + "identity_jose", + "include_dir", + "internet_identity_interface", + "lazy_static", + "lodepng", + "minicbor", + "pocket-ic", + "pretty_assertions", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.6.4", + "regex", + "rsa", + "serde", + "serde_bytes", + "serde_cbor", + "serde_json", + "sha2 0.10.9", +] + +[[package]] +name = "internet_identity_frontend" +version = "0.1.0" +dependencies = [ + "asset_util", + "base64 0.22.1", + "candid", + "flate2", + "ic-asset-certification", + "ic-cdk 0.16.1", + "ic-cdk-macros 0.16.0", + "ic-cdk-timers", + "ic-http-certification", + "include_dir", + "internet_identity_interface", + "lazy_static", + "serde_bytes", + "serde_json", + "sha2 0.10.9", +] + +[[package]] +name = "internet_identity_interface" +version = "0.1.0" +dependencies = [ + "candid", + "ic-cdk 0.16.1", + "ic-http-certification", + "serde", + "serde_bytes", +] + +[[package]] +name = "iota-crypto" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98a38db844c910d78825e173c083f2ef416b69cb091bba8ac1055763c6db065b" +dependencies = [ + "autocfg 1.5.0", + "digest 0.10.7", + "k256", + "serde", + "sha2 0.10.9", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi 0.5.2", + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "json-proof-token" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "179551c27c512c948af1edaf4bd7e1d1486d223f8ec4fd41cd760f7645fd4197" +dependencies = [ + "cargo-license", + "data-encoding", + "indexmap 2.12.1", + "json-unflattening", + "serde", + "serde_json", + "thiserror 1.0.69", + "zkryptium", +] + +[[package]] +name = "json-unflattening" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964396e7ac82f9bb7c84232afb76cfa325ed03f1fc84b877c8d1b1cebfe196dd" +dependencies = [ + "regex", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2 0.10.9", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lalrpop" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax 0.8.8", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libredox" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50" +dependencies = [ + "bitflags 2.10.0", + "libc", +] + +[[package]] +name = "libz-rs-sys" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15413ef615ad868d4d65dce091cb233b229419c7c0c4bcaa746c0901c49ff39c" +dependencies = [ + "zlib-rs", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "lodepng" +version = "3.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a32335d22e44238e2bb0b4d726964d18952ce1f1279ec3305305d2c61539eb" +dependencies = [ + "crc32fast", + "flate2", + "libc", + "rgb", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "logos" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c000ca4d908ff18ac99b93a062cb8958d331c3220719c52e77cb19cc6ac5d2c1" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68" +dependencies = [ + "beef", + "fnv", + "proc-macro2", + "quote", + "regex-syntax 0.6.29", + "syn 2.0.111", +] + +[[package]] +name = "logos-derive" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbfc0d229f1f42d790440136d941afd806bc9e949e2bcb8faa813b0f00d1267e" +dependencies = [ + "logos-codegen", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "match-lookup" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minicbor" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734daad4ff3b880f23dc2a675dd74553fa8e583367aa7523f96a16e96a516b62" +dependencies = [ + "minicbor-derive", +] + +[[package]] +name = "minicbor-derive" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512ce2c37128698ea15c99b3518936c78a8b112b92468e7b95b9fa045666ebd8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "miracl_core_bls12381" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07cbe42e2a8dd41df582fb8e00fc24d920b5561cc301fcb6d14e2e0434b500f" + +[[package]] +name = "multibase" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8694bb4835f452b0e3bb06dbebb1d6fc5385b6ca1caf2e55fd165c042390ec77" +dependencies = [ + "base-x", + "base256emoji", + "data-encoding", + "data-encoding-macro", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg 1.5.0", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg 1.5.0", + "libm", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + +[[package]] +name = "pairing" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135590d8bdba2b31346f9cd1fb2a912329f5135e832a4f422942eb6ead8b6b3b" +dependencies = [ + "group 0.12.1", +] + +[[package]] +name = "pairing" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" +dependencies = [ + "group 0.13.0", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.12.1", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "pocket-ic" +version = "9.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e523c23bda9dc26ae989aab647b8bd805b54c72a3f2f00d668830d8b490c9c8" +dependencies = [ + "backoff", + "base64 0.13.1", + "candid", + "flate2", + "hex", + "ic-certification 3.0.3", + "ic-management-canister-types", + "ic-transport-types", + "reqwest", + "schemars", + "serde", + "serde_bytes", + "serde_cbor", + "serde_json", + "sha2 0.10.9", + "slog", + "strum 0.26.3", + "strum_macros 0.26.4", + "tempfile", + "thiserror 2.0.17", + "tokio", + "tracing", + "tracing-appender", + "tracing-subscriber", + "wslpath", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "pretty" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d22152487193190344590e4f30e219cf3fe140d9e7a3fdb683d82aa2c5f4156" +dependencies = [ + "arrayvec", + "typed-arena", + "unicode-width 0.2.2", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d11f2fedc3b7dafdc2851bc52f277377c5473d378859be234bc7ebb593144d01" +dependencies = [ + "ar_archive_writer", + "cc", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.17", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.17", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.8", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.3.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax 0.8.8", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.8", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "reqwest" +version = "0.12.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "rgb" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rsa" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88" +dependencies = [ + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.111", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags 2.10.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-aux" +version = "4.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "207f67b28fe90fb596503a9bf0bf1ea5e831e21307658e177c5dfcdfc3ab8a0a" +dependencies = [ + "serde", + "serde-value", + "serde_json", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "indexmap 2.12.1", + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "serde_tokenstream" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "797ba1d80299b264f3aac68ab5d12e5825a561749db4df7cd7c8083900c5d4e9" +dependencies = [ + "proc-macro2", + "serde", + "syn 1.0.109", +] + +[[package]] +name = "serde_tokenstream" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64060d864397305347a78851c51588fd283767e7e7589829e8121d65512340f1" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.111", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "sig_verifier_js" +version = "1.0.0" +dependencies = [ + "assert_matches", + "candid", + "hex", + "ic-canister-sig-creation", + "ic-signature-verification 0.2.0", + "serde", + "serde_json", + "wasm-bindgen", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "slog" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3b8565691b22d2bdfc066426ed48f837fc0c5f2c8cad8d9718f7f99d6995c1" +dependencies = [ + "anyhow", + "erased-serde", + "rustversion", + "serde_core", +] + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "stacker" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1f8b29fb42aafcea4edeeb6b2f2d7ecd0d969c48b4cf0d2e64aafc471dd6e59" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.59.0", +] + +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros 0.25.3", +] + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.111", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.111", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags 2.10.0", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-appender" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf" +dependencies = [ + "crossbeam-channel", + "thiserror 2.0.17", + "time", + "tracing-subscriber", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "time", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.111", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "wslpath" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04a2ecdf2cc4d33a6a93d71bcfbc00bb1f635cdb8029a2cc0709204a045ec7a3" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "zkryptium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c734c171ed591a19dc1127351eb1b4d91864d3e53b2b6e9992bffcb7febf364a" +dependencies = [ + "bls12_381_plus", + "cargo-license", + "digest 0.10.7", + "dotenv", + "elliptic-curve", + "env_logger", + "ff 0.13.1", + "group 0.10.0", + "hex", + "hkdf", + "log", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.10.9", + "sha3", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "zlib-rs" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f936044d677be1a1168fae1d03b583a285a5dd9d8cbf7b24c23aa1fc775235" diff --git a/demos/test-app/Cargo.lock b/demos/test-app/Cargo.lock index 663a8e820d..36891e095e 100644 --- a/demos/test-app/Cargo.lock +++ b/demos/test-app/Cargo.lock @@ -82,6 +82,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" + [[package]] name = "candid" version = "0.10.10" @@ -204,6 +210,16 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + [[package]] name = "ic-cdk" version = "0.16.0" @@ -243,11 +259,28 @@ dependencies = [ "sha2", ] +[[package]] +name = "ic-http-certification" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1a65b0ffb568e954750067f660e254f4564394f5c064a88e0e93b2eea4a532" +dependencies = [ + "base64", + "candid", + "http", + "ic-certification", + "ic-representation-independent-hash", + "serde", + "serde_cbor", + "thiserror", + "urlencoding", +] + [[package]] name = "ic-representation-independent-hash" -version = "2.6.0" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ae59483e377cd9aad94ec339ed1d2583b0d5929cab989328dac2d853b2f570" +checksum = "c2800ba4910f21d9e1cb7b6ecbbbb0f76074bd2e127b4688c57d0936206caa6e" dependencies = [ "leb128", "sha2", @@ -297,10 +330,17 @@ version = "0.1.0" dependencies = [ "candid", "ic-cdk", + "ic-http-certification", "serde", "serde_bytes", ] +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + [[package]] name = "lazy_static" version = "1.5.0" @@ -558,6 +598,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "version_check" version = "0.9.5" From 7cd17abeb7d6771993cf8a2065aa4ec7cb5ad426 Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 19 Dec 2025 17:01:59 +0100 Subject: [PATCH 15/16] Add new_flow_origins https://id.ai --- src/internet_identity_frontend/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internet_identity_frontend/src/main.rs b/src/internet_identity_frontend/src/main.rs index 09c8abc32b..ed17a68dcc 100644 --- a/src/internet_identity_frontend/src/main.rs +++ b/src/internet_identity_frontend/src/main.rs @@ -46,7 +46,7 @@ lazy_static! { "https://identity.internetcomputer.org".to_string(), "https://identity.ic0.app".to_string(), ]), - new_flow_origins: None, + new_flow_origins: Some(vec!["https://id.ai".to_string()]), openid_configs: Some(vec![ internet_identity_interface::internet_identity::types::OpenIdConfig { name: "Google".to_string(), From 0962b4ff9f9f40c66d44932b1c0b5e8c5443338a Mon Sep 17 00:00:00 2001 From: Arshavir Ter-Gabrielyan Date: Fri, 19 Dec 2025 18:35:56 +0100 Subject: [PATCH 16/16] Fix e2e tests for recovery flow --- .../tests/e2e-playwright/fixtures/identity.ts | 12 ++ src/internet_identity_frontend/src/main.rs | 176 +++++++----------- 2 files changed, 75 insertions(+), 113 deletions(-) diff --git a/src/frontend/tests/e2e-playwright/fixtures/identity.ts b/src/frontend/tests/e2e-playwright/fixtures/identity.ts index fb100b4e79..c26c658c5d 100644 --- a/src/frontend/tests/e2e-playwright/fixtures/identity.ts +++ b/src/frontend/tests/e2e-playwright/fixtures/identity.ts @@ -42,6 +42,18 @@ class IdentityWizard { async signInWithPasskey(auth: DummyAuthFn): Promise { await this.#goto(); + + await this.#page + .getByRole("heading", { name: "Manage your Internet Identity" }) + .waitFor(); + + const useAnotherIdentity = this.#page.getByRole("button", { + name: "Use another identity", + }); + if (await useAnotherIdentity.isVisible()) { + await useAnotherIdentity.click(); + } + await this.#page .getByRole("button", { name: "Continue with passkey" }) .click(); diff --git a/src/internet_identity_frontend/src/main.rs b/src/internet_identity_frontend/src/main.rs index ed17a68dcc..55b93cb339 100644 --- a/src/internet_identity_frontend/src/main.rs +++ b/src/internet_identity_frontend/src/main.rs @@ -50,7 +50,7 @@ lazy_static! { openid_configs: Some(vec![ internet_identity_interface::internet_identity::types::OpenIdConfig { name: "Google".to_string(), - logo: "https://www.google.com/favicon.ico".to_string(), + logo: "".to_string(), issuer: "https://accounts.google.com".to_string(), client_id: "775077467414-q1ajffledt8bjj82p2rl5a09co8cf4rf.apps.googleusercontent.com".to_string(), jwks_uri: "https://www.googleapis.com/oauth2/v3/certs".to_string(), @@ -100,126 +100,76 @@ fn certify_all_assets(init: InternetIdentityInit) { }); let mut router_assets = Vec::new(); - for asset in static_assets { + for asset in &static_assets { let content = if asset.encoding == ContentEncoding::GZip { let mut decoder = GzDecoder::new(&asset.content[..]); let mut s = Vec::new(); decoder.read_to_end(&mut s).unwrap(); s } else { - asset.content + asset.content.clone() }; - router_assets.push(Asset::new(asset.url_path, content)); + router_assets.push(Asset::new(asset.url_path.clone(), content)); } - let encodings = vec![ - AssetEncoding::Brotli.default_config(), - AssetEncoding::Gzip.default_config(), - ]; + let asset_configs: Vec<_> = static_assets + .into_iter() + .map( + |asset_util::Asset { + url_path: path, + encoding, + content_type, + content: _, + }| { + if content_type == ContentType::HTML { + AssetConfig::File { + path, + content_type: Some("text/html".to_string()), + headers: get_asset_headers( + integrity_hashes.clone(), + vec![( + "cache-control".to_string(), + NO_CACHE_ASSET_CACHE_CONTROL.to_string(), + )], + ), + fallback_for: vec![AssetFallbackConfig { + scope: "/".to_string(), + status_code: Some(StatusCode::OK), + }], + aliased_by: vec!["/".to_string()], + encodings: vec![AssetEncoding::Identity.default_config()], + } + } else { + let encodings = if encoding == ContentEncoding::GZip { + vec![AssetEncoding::Gzip.default_config()] + } else { + vec![AssetEncoding::Identity.default_config()] + }; - let asset_configs = vec![ - AssetConfig::File { - path: "index.html".to_string(), - content_type: Some("text/html".to_string()), - headers: get_asset_headers( - integrity_hashes.clone(), - vec![( - "cache-control".to_string(), - NO_CACHE_ASSET_CACHE_CONTROL.to_string(), - )], - ), - fallback_for: vec![AssetFallbackConfig { - scope: "/".to_string(), - status_code: Some(StatusCode::OK), - }], - aliased_by: vec!["/".to_string()], - encodings: encodings.clone(), - }, - AssetConfig::Pattern { - pattern: "**/*.html".to_string(), - content_type: Some("text/html".to_string()), - headers: get_asset_headers( - integrity_hashes.clone(), - vec![( - "cache-control".to_string(), - NO_CACHE_ASSET_CACHE_CONTROL.to_string(), - )], - ), - encodings: vec![AssetEncoding::Identity.default_config()], - }, - AssetConfig::Pattern { - pattern: "**/*.css".to_string(), - content_type: Some("text/css".to_string()), - headers: get_asset_headers( - vec![], - vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )], - ), - encodings: encodings.clone(), - }, - AssetConfig::Pattern { - pattern: "**/*.js".to_string(), - content_type: Some("text/javascript".to_string()), - headers: get_asset_headers( - vec![], - vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )], - ), - encodings: encodings.clone(), - }, - AssetConfig::Pattern { - pattern: "**/*.ico".to_string(), - content_type: Some("image/x-icon".to_string()), - headers: get_asset_headers( - vec![], - vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )], - ), - encodings: vec![], - }, - AssetConfig::Pattern { - pattern: "**/*.png".to_string(), - content_type: Some("image/png".to_string()), - headers: get_asset_headers( - vec![], - vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )], - ), - encodings: vec![], - }, - AssetConfig::Pattern { - pattern: "**/*.woff2".to_string(), - content_type: Some("font/woff2".to_string()), - headers: get_asset_headers( - vec![], - vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )], - ), - encodings: encodings.clone(), - }, - AssetConfig::Pattern { - pattern: "**/*.json".to_string(), - content_type: Some("application/json".to_string()), - headers: get_asset_headers( - vec![], - vec![( - "cache-control".to_string(), - IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), - )], - ), - encodings: vec![], - }, - ]; + let headers = if path.starts_with("_app/immutable") { + ( + "cache-control".to_string(), + IMMUTABLE_ASSET_CACHE_CONTROL.to_string(), + ) + } else { + ( + "cache-control".to_string(), + NO_CACHE_ASSET_CACHE_CONTROL.to_string(), + ) + }; + + AssetConfig::File { + path, + content_type: Some(content_type.to_mime_type_string()), + encodings, + headers: get_asset_headers(integrity_hashes.clone(), vec![headers]), + fallback_for: vec![], + aliased_by: vec![], + } + } + }, + ) + .collect(); ASSET_ROUTER.with(|asset_router| { if let Err(err) = asset_router @@ -461,8 +411,8 @@ fn extract_inline_scripts(content: String) -> Vec { #[query] fn http_request(request: HttpRequest) -> HttpResponse { - ASSET_ROUTER.with(|asset_router| { - if let Ok(response) = asset_router.borrow().serve_asset( + ASSET_ROUTER.with_borrow(|asset_router| { + if let Ok(response) = asset_router.serve_asset( &ic_cdk::api::data_certificate().expect("No data certificate available"), &request, ) {