diff --git a/src-tauri/src/fido/mod.rs b/src-tauri/src/fido/mod.rs index 0c68d1b..0049f42 100644 --- a/src-tauri/src/fido/mod.rs +++ b/src-tauri/src/fido/mod.rs @@ -382,8 +382,12 @@ pub fn write_config(config: AppConfigInput, pin: Option) -> Result + import * as Alert from "$lib/components/ui/alert"; + import { TriangleAlert } from "@lucide/svelte"; + import { device } from "$lib/device/manager.svelte"; + + interface Props { + message?: string; + } + + let { message = "This device does implement this feature." }: Props = + $props(); + + + + + {device.error ? "Connection Error" : "Feature not supported"} + + {device.error || message} + + diff --git a/src/lib/components/dialogs/AuthDialog.svelte b/src/lib/components/dialogs/AuthDialog.svelte new file mode 100644 index 0000000..d9acdb8 --- /dev/null +++ b/src/lib/components/dialogs/AuthDialog.svelte @@ -0,0 +1,81 @@ + + + + + + + Authenticate to View Passkeys + + Enter your FIDO2 PIN to access and manage stored credentials. + +
+
+ + e.key === "Enter" && handleUnlock()} + autofocus + /> +
+ {#if error} + + {error} + + {/if} +
+ + + +
+
diff --git a/src/lib/components/dialogs/deleteCredentialDialog.svelte b/src/lib/components/dialogs/deleteCredentialDialog.svelte new file mode 100644 index 0000000..1467823 --- /dev/null +++ b/src/lib/components/dialogs/deleteCredentialDialog.svelte @@ -0,0 +1,73 @@ + + + + + + Are you sure? + + This action cannot be undone. This will permanently delete the + passkey for + {credential?.rpId}. + + + +
+ + +
+ + + Cancel + + +
+
diff --git a/src/lib/device/constants.svelte.ts b/src/lib/device/constants.svelte.ts index e6641ec..4235fb1 100644 --- a/src/lib/device/constants.svelte.ts +++ b/src/lib/device/constants.svelte.ts @@ -3,9 +3,9 @@ import type { DeviceConfig } from "$lib/device/types.svelte.ts"; export const VENDORS = [ { value: "custom", label: "Custom (Manual Entry)", vid: "", pid: "" }, { value: "generic", label: "Generic (FEFF:FCFD)", vid: "FEFF", pid: "FCFD" }, - { value: "pico-hsm", label: "Pico Keys HSM (2E8A:0x10FD)", vid: "2E8A", pid: "0x10FD" }, - { value: "pico-fido", label: "Pico Keys Fido (2E8A:0x10FE)", vid: "2E8A", pid: "0x10FE" }, - { value: "pico-openpgp", label: "Pico Keys OpenPGP (2E8A:0x10FF)", vid: "2E8A", pid: "0x10FF" }, + { value: "pico-hsm", label: "Pico Keys HSM (2E8A:10FD)", vid: "2E8A", pid: "10FD" }, + { value: "pico-fido", label: "Pico Keys Fido (2E8A:10FE)", vid: "2E8A", pid: "10FE" }, + { value: "pico-openpgp", label: "Pico Keys OpenPGP (2E8A:10FF)", vid: "2E8A", pid: "10FF" }, { value: "pico", label: "Pico (2E8A:0003)", vid: "2E8A", pid: "0003" }, { value: "solokeys", label: "SoloKeys (0483:A2CA)", vid: "0483", pid: "A2CA" }, { value: "nitrohsm", label: "NitroHSM (20A0:4230)", vid: "20A0", pid: "4230" }, diff --git a/src/lib/device/manager.svelte.ts b/src/lib/device/manager.svelte.ts index 5bb55a2..a46b88a 100644 --- a/src/lib/device/manager.svelte.ts +++ b/src/lib/device/manager.svelte.ts @@ -38,6 +38,10 @@ class DeviceManager { return match ? match.value : "custom"; } + get hasFido() { + return !!this.fidoInfo; + } + async refresh() { this.loading = true; this.error = null; @@ -63,9 +67,13 @@ class DeviceManager { this.method = status.method; - const fido = await invoke("get_fido_info"); - - this.fidoInfo = fido; + try { + const fido = await invoke("get_fido_info"); + this.fidoInfo = fido; + } catch (e) { + logger.add("FIDO info could not be read (device might not support FIDO features)", "warning"); + this.fidoInfo = null; + } if (!this.connected) { logger.add(`Device Connected! Serial: ${this.info.serial}, FW: v${this.info.firmwareVersion}`, "success"); diff --git a/src/lib/views/aboutView.svelte b/src/lib/views/aboutView.svelte index b6660db..d9d0bc8 100644 --- a/src/lib/views/aboutView.svelte +++ b/src/lib/views/aboutView.svelte @@ -12,37 +12,53 @@ } -
+

About

-
+
- PicoForge Logo + PicoForge Logo

PicoForge

v0.3.0

- An open source commissioning tool for Pico FIDO security keys. Developed with Rust, Tauri, and Svelte. + An open source commissioning tool for Pico FIDO security keys. + Developed with Rust, Tauri, and Svelte.

-
+
- Code By: Suyog Tandel + Code By: + Suyog Tandel
Copyright: - © 2026 Suyog Tandel + © 2026 Suyog Tandel
- diff --git a/src/lib/views/configView.svelte b/src/lib/views/configView.svelte index 79b89f7..7a53a3b 100644 --- a/src/lib/views/configView.svelte +++ b/src/lib/views/configView.svelte @@ -12,55 +12,32 @@ import { device } from "$lib/device/manager.svelte"; import { LED_DRIVERS, VENDORS } from "$lib/device/constants.svelte"; - import { Microchip, RefreshCw, Save, Settings, Tag, TriangleAlert, X, Key } from "@lucide/svelte"; + import { + Microchip, + RefreshCw, + Save, + Settings, + Tag, + TriangleAlert, + X, + } from "@lucide/svelte"; import { configViewState as state } from "$lib/state/configState.svelte"; import NoDeviceStatus from "$lib/components/device/NoDeviceStatus.svelte"; -
+

Configuration

Customize device settings and behavior.

{#if !device.connected} - + {:else}
- - - - - PIN Management - - Configure FIDO2 PIN security - - -
-
-

Current PIN Status

-

- {device.fidoInfo?.options?.clientPin ? "PIN is set" : "No PIN configured"} -

-
- -
- -
-
-

Minimum PIN Length

-

- Current: {device.fidoInfo?.minPinLength || 4} characters -

-
- -
-
-
- @@ -79,7 +56,8 @@ disabled={!device.connected} > - {VENDORS.find((v) => v.value === device.selectedVendor)?.label ?? "Select a vendor"} + {VENDORS.find((v) => v.value === device.selectedVendor) + ?.label ?? "Select a vendor"} {#each VENDORS as vendor} @@ -99,7 +77,8 @@ bind:value={device.config.vid} maxlength={4} placeholder="CAFE" - disabled={!device.connected || device.selectedVendor !== "custom"} + disabled={!device.connected || + device.selectedVendor !== "custom"} class="font-mono" />
@@ -110,7 +89,8 @@ bind:value={device.config.pid} maxlength={4} placeholder="4242" - disabled={!device.connected || device.selectedVendor !== "custom"} + disabled={!device.connected || + device.selectedVendor !== "custom"} class="font-mono" />
@@ -120,7 +100,12 @@
- +
@@ -136,14 +121,25 @@
- +
- + - {LED_DRIVERS.find((d) => d.value === device.config.ledDriver)?.label ?? "Select driver"} + {LED_DRIVERS.find((d) => d.value === device.config.ledDriver) + ?.label ?? "Select driver"} {#each LED_DRIVERS as driver} @@ -168,14 +164,18 @@ disabled={!device.connected} class="flex-1" /> - Level {device.config.ledBrightness} + Level {device.config.ledBrightness}
-

Allow brightness adjustment

+

+ Allow brightness adjustment +

@@ -183,7 +183,9 @@
-

Keep LED on constantly

+

+ Keep LED on constantly +

@@ -201,7 +203,13 @@
- +
@@ -218,7 +226,9 @@
-

Restart device on reset

+

+ Restart device on reset +

@@ -226,7 +236,9 @@
-

Does not work on Android!

+

+ Does not work on Android! +

diff --git a/src/lib/views/homeView.svelte b/src/lib/views/homeView.svelte index 052749c..ce03c43 100644 --- a/src/lib/views/homeView.svelte +++ b/src/lib/views/homeView.svelte @@ -19,7 +19,7 @@ import NoDeviceStatus from "$lib/components/device/NoDeviceStatus.svelte"; -
+

Device Overview

diff --git a/src/lib/views/logsView.svelte b/src/lib/views/logsView.svelte index 7535500..5945fb2 100644 --- a/src/lib/views/logsView.svelte +++ b/src/lib/views/logsView.svelte @@ -8,24 +8,35 @@ import { Terminal } from "@lucide/svelte"; -

+

System Logs

-

Real-time device communication and application events.

+

+ Real-time device communication and application events. +

- +
- + {#if logger.logs.length === 0} -
+

No events recorded yet.

{:else} - +
{#each logger.logs as log}
diff --git a/src/lib/views/passkeysView.svelte b/src/lib/views/passkeysView.svelte index 1b73706..12a26fe 100644 --- a/src/lib/views/passkeysView.svelte +++ b/src/lib/views/passkeysView.svelte @@ -1,64 +1,41 @@ - -
+

Passkeys

-

Manage resident credentials (passkeys) stored on your device.

+

+ Manage your security PIN and the FIDO credentials (passkeys) stored on + your device. +

{#if !device.connected} + {:else if !device.hasFido} + {:else} - - - - - Authenticate to View Passkeys - - Enter your FIDO2 PIN to access and manage stored credentials. - -
-
- - e.key === "Enter" && handleUnlock()} - autofocus - /> -
- {#if error} - - {error} - - {/if} + + +
+ + + PIN Management + + Configure FIDO2 PIN security
- - - - - - - {#if device.unlocked} -
-
- - - Unlocked - - - - {device.credentials.length} - {device.credentials.length === 1 ? "credential" : "credentials"} stored - -
- -
- - {#if device.credentials.length === 0} - - -
- -
-

No Passkeys Found

-

- This device doesn't have any resident credentials stored yet. Create passkeys on websites to see them here. + + +

+
+

Current PIN Status

+

+ {device.fidoInfo?.options?.clientPin + ? "PIN is set" + : "No PIN configured"}

- - - {:else} -
- {#each device.credentials as cred} - +
-
-

- {cred.rpName || cred.rpId || "Unknown Service"} -

-

{cred.userName}

+
+
+

Minimum PIN Length

+

+ Current: {device.fidoInfo?.minPinLength || 4} characters +

+
+ +
+ + + + + +
+ + + Stored Passkeys + + + View and manage your resident credentials + +
+
+ + + + {#if !device.unlocked} +
+
+ +
+

Authentication Required

+

+ Unlock your device to view and manage passkeys. +

+ +
+ {/if} + + {#if device.unlocked} +
+
+ + + Unlocked + + + + {device.credentials.length} + {device.credentials.length === 1 ? "credential" : "credentials"} + stored + +
+ +
+ + {#if device.credentials.length === 0} + + +
+ +
+

No Passkeys Found

+

+ This device doesn't have any resident credentials stored yet. + Create passkeys on websites to see them here. +

+
+
+ {:else} +
+ {#each device.credentials as cred} + +
+ +
+ + {/each} +
+ {/if} + + + +
+ + + {selectedCredential?.rpName || + selectedCredential?.rpId || + "Passkey Details"} + + + Credential details for user {selectedCredential?.userName} + + + +
+
+
+ +
+
+
+ {selectedCredential?.rpId} +
+
+ {selectedCredential?.userName}
- -
- - - - {/each} -
- {/if} - - -
- - - {selectedCredential?.rpName || selectedCredential?.rpId || "Passkey Details"} - - - Credential details for user {selectedCredential?.userName} - - + -
-
-
- -
-
-
{selectedCredential?.rpId}
-
{selectedCredential?.userName}
+
+
+

+ Display Name +

+

+ {selectedCredential?.userDisplayName || "N/A"} +

+
+ +
+

+ User ID (Hex) +

+

+ {selectedCredential?.userId} +

+
+ +
+

+ Credential ID (Hex) +

+

+ {selectedCredential?.credentialId} +

+
+
+ + + Close +
+ + - - -
-
-

Display Name

-

{selectedCredential?.userDisplayName || "N/A"}

-
- -
-

User ID (Hex)

-

- {selectedCredential?.userId} -

-
- -
-

Credential ID (Hex)

-

{selectedCredential?.credentialId}

-
-
-
- - - Close - -
-
-
- - - - - Are you sure? - - This action cannot be undone. This will permanently delete the passkey for - {credentialToDelete?.rpId}. - - - -
- - -
- - - Cancel - - -
-
- {/if} + + {/if} + + {/if}
diff --git a/src/lib/views/securityView.svelte b/src/lib/views/securityView.svelte index 29964b7..a481e36 100644 --- a/src/lib/views/securityView.svelte +++ b/src/lib/views/securityView.svelte @@ -12,32 +12,43 @@ import { Lock, TriangleAlert } from "@lucide/svelte"; async function lockDevice() { - logger.add("Action Blocked: Secure Boot toggle attempted but feature is disabled.", "warning"); + logger.add( + "Action Blocked: Secure Boot toggle attempted but feature is disabled.", + "warning", + ); return; } -
+
-

Secure Boot

-

Permanently lock this device to the current firmware vendor.

+

+ Secure Boot +

+

+ Permanently lock this device to the current firmware vendor. +

Feature Unstable - This feature is currently under work and disabled for safety. + This feature is currently under work and disabled for safety. Lock Settings - +
-

Verifies firmware signature on startup

+

+ Verifies firmware signature on startup +

-

Prevents reading key material via debug ports

+

+ Prevents reading key material via debug ports +

- +
-
- - +
+ +