Skip to content

Conversation

@sosweetham
Copy link
Member

@sosweetham sosweetham commented Nov 13, 2025

Description of change

Updates the context provision logic to never use hardware module if user isfake, if context is pre verification, after all this, check if harware key manager exists before determining to use hardware module or not

Issue Number

closes #423

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Device test

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Summary by CodeRabbit

  • New Features

    • Onboarding detects device hardware support and offers a "Use Pre-Verification Code" path when hardware is unavailable.
    • Verification now ensures keys are ready and redirects to onboarding if device support or initialization fails.
  • Improvements

    • "Get Started" disables while checking device and shows "Checking device..." during hardware tests.
    • Cached hardware key usage is avoided for pre-verification/fake-mode users to ensure a software-only flow and clearer error messaging.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 13, 2025

Walkthrough

Adds an isFake flag and pre-verification gating to key manager selection so pre-verification or fake users never use hardware keys; updates key controller to read a fake flag, invalidate cached hardware managers for pre-verification users, and pass isFake to the factory; onboarding/verify UIs now check hardware availability and redirect or offer pre-verification accordingly.

Changes

Cohort / File(s) Summary
Key Manager Factory
infrastructure/eid-wallet/src/lib/crypto/KeyManagerFactory.ts
Adds isFake parameter to getKeyManagerForContext; computes shouldUseHardware = !isFake && context !== "pre-verification" && hardwareAvailable; sets useHardware and preVerificationMode in config so pre-verification or fake contexts avoid hardware.
Key Controller / Key Service
infrastructure/eid-wallet/src/lib/global/controllers/key.ts
Reads fake flag from store via new #isPreVerificationUser(), derives effective context ("pre-verification" when fake), invalidates cached hardware managers for pre-verification users, and passes isFake to KeyManagerFactory.getKeyManagerForContext. Adds UserController import.
Onboarding UI
infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
Adds hardware capability checks, checkingHardware and showHardwareError states; performs a hardware test on Get Started, disables button while checking, shows "Hardware Security Not Available" with a pre-verification fallback, and initializes keys when hardware is available.
Verification UI
infrastructure/eid-wallet/src/routes/(auth)/verify/+page.svelte
Adds mount-time guards and try/catch around key initialization and verification start; redirects to /onboarding when hardware-backed keys aren’t supported or initialization fails.

Sequence Diagram(s)

sequenceDiagram
    participant UI as Onboarding/Verify UI
    participant KeyCtrl as KeyController
    participant Store
    participant KMFactory as KeyManagerFactory
    participant KM as KeyManager

    UI->>KeyCtrl: check hardware availability / user action
    alt hardware unavailable
        UI->>UI: show "Hardware Not Available" (pre-verification option)
        UI-->>KeyCtrl: request pre-verification path
    else hardware available
        UI->>KeyCtrl: proceed to verification/onboarding flow
    end

    KeyCtrl->>Store: read "fake" flag
    Store-->>KeyCtrl: fake (true/false)
    KeyCtrl->>KMFactory: getKeyManagerForContext(keyId, context, isFake)

    rect rgb(230,245,230)
      Note over KMFactory: Selection logic
      alt isFake = true OR context = "pre-verification"
        KMFactory->>KMFactory: choose software key manager
      else hardware available
        KMFactory->>KMFactory: choose hardware key manager
      else
        KMFactory->>KMFactory: fallback to software manager
      end
    end

    KMFactory-->>KM: instantiate manager
    KM-->>KeyCtrl: return KeyManager
    KeyCtrl-->>UI: provide manager / continue flow
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay attention to:
    • Cache invalidation in controllers/key.ts (race conditions, correct detection of hardware manager instances)
    • Correct propagation and defaulting of isFake across callers
    • Error handling that triggers redirects in verify/onboarding flows
    • Tests or runtime checks ensuring hardware detection and pre-verification gates behave consistently

Possibly related PRs

  • Fix/eid onboarding #415 — changes KeyManagerFactory runtime decision logic and signature (adds isFake), directly related to factory usage and cache behavior.
  • feat: setup hw crypto #295 — modifies onboarding/verify routes to add hardware checks and key handling, overlapping UI flow changes.

Suggested reviewers

  • grv-saini-20

Poem

🐰 I hopped through keys both soft and hard,
I nudged a flag to guard the yard.
Pre-verify stays gentle, light,
Hardware sleeps when out of sight.
A tiny hop — the right key found! 🔑

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix/hardware crypto context logic' clearly relates to the main change: correcting context logic to prevent hardware module usage in inappropriate scenarios (fake/pre-verification contexts).
Description check ✅ Passed The description covers the core change objective, references the linked issue #423, identifies the type as Fix, mentions device testing, and completes most checklist items, though formatting and clarity could be improved.
Linked Issues check ✅ Passed The PR successfully addresses the bug #423 objectives: it prevents hardware key usage for software-key devices and prevents verified environment creation on software-key phones by introducing isFake parameter logic and pre-verification context checks.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the hardware module context logic issue; modifications to KeyManagerFactory, key controller, and onboarding/verification flows all serve the primary objective of preventing inappropriate hardware key usage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/hardware-crypto-context-logic

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sosweetham sosweetham marked this pull request as ready for review November 13, 2025 16:10
@sosweetham sosweetham requested a review from coodos as a code owner November 13, 2025 16:10
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
infrastructure/eid-wallet/src/lib/global/controllers/key.ts (1)

4-4: Remove unused import.

The UserController type is imported but never used in this file.

Apply this diff to remove the unused import:

-import type { UserController } from "./user";
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6148a99 and 6efb9c2.

📒 Files selected for processing (2)
  • infrastructure/eid-wallet/src/lib/crypto/KeyManagerFactory.ts (1 hunks)
  • infrastructure/eid-wallet/src/lib/global/controllers/key.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
infrastructure/eid-wallet/src/lib/crypto/KeyManagerFactory.ts (1)
infrastructure/eid-wallet/src/lib/crypto/types.ts (2)
  • KeyManager (5-39)
  • KeyManagerConfig (44-48)
infrastructure/eid-wallet/src/lib/global/controllers/key.ts (1)
infrastructure/eid-wallet/src/lib/crypto/KeyManagerFactory.ts (1)
  • KeyManagerFactory (10-106)
🔇 Additional comments (1)
infrastructure/eid-wallet/src/lib/crypto/KeyManagerFactory.ts (1)

85-94: LGTM! Hardware usage logic correctly implements requirements.

The implementation properly addresses the stated objectives from issue #423:

  1. Hardware module is never used when isFake is true (lines 89-90)
  2. Hardware module is never used for "pre-verification" context (line 91)
  3. Hardware is only used when available via runtime check (line 92)

The short-circuit evaluation order is optimal, avoiding unnecessary hardware availability checks when isFake is true.

@coodos coodos force-pushed the fix/hardware-crypto-context-logic branch from 9390d42 to f80bf7a Compare November 13, 2025 17:26
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bed6b47 and f80bf7a.

⛔ Files ignored due to path filters (1)
  • infrastructure/eid-wallet/src-tauri/gen/android/.idea/deviceManager.xml is excluded by !**/gen/**
📒 Files selected for processing (3)
  • infrastructure/eid-wallet/src/lib/crypto/KeyManagerFactory.ts (2 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte (4 hunks)
  • infrastructure/eid-wallet/src/routes/(auth)/verify/+page.svelte (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
infrastructure/eid-wallet/src/lib/crypto/KeyManagerFactory.ts (1)
infrastructure/eid-wallet/src/lib/crypto/types.ts (2)
  • KeyManager (5-39)
  • KeyManagerConfig (44-48)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

Comment on lines +42 to +78
// Actually try to generate a test hardware key
const testKeyId = `hardware-test-${Date.now()}`;
console.log(
"Testing hardware key generation with test key:",
testKeyId,
);
try {
const { manager, created } = await globalState.keyService.ensureKey(
testKeyId,
"onboarding",
);
console.log(
"Test key result - Manager type:",
manager.getType(),
"Created:",
created,
);
// Check if we got hardware manager and it actually created a key
if (manager.getType() !== "hardware") {
throw new Error("Got software fallback instead of hardware");
}
// Hardware works! Clean up test key and proceed
console.log("Hardware keys are working");
checkingHardware = false;
} catch (keyError) {
console.error("Hardware key test failed:", keyError);
showHardwareError = true;
checkingHardware = false;
}
} catch (err) {
console.error("Error checking hardware:", err);
showHardwareError = true;
checkingHardware = false;
}
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 13, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Stop generating throwaway hardware keys during capability check

ensureKey actually runs the full hardware credential ceremony. That means the “capability check” now forces a biometric/PIN prompt, and any cancellation or timeout will be misread as “hardware unavailable”, pushing real hardware-capable users into the pre-verification path. On top of that, every click leaves behind a hardware-test-<timestamp> credential that we never clean up, which quickly pollutes the authenticator and can exhaust limited key slots. Please switch this probe to the existing isHardwareAvailable() call (or similar non-destructive check) and drop the throwaway key creation altogether.

Recommended change:

@@
-    checkingHardware = true;
-    showHardwareError = false;
-    error = null;
-
-    try {
-        if (!globalState) {
-            globalState = getContext<() => GlobalState>("globalState")();
-        }
-
-        // Actually try to generate a test hardware key
-        const testKeyId = `hardware-test-${Date.now()}`;
-        console.log(
-            "Testing hardware key generation with test key:",
-            testKeyId,
-        );
-
-        try {
-            const { manager, created } = await globalState.keyService.ensureKey(
-                testKeyId,
-                "onboarding",
-            );
-            console.log(
-                "Test key result - Manager type:",
-                manager.getType(),
-                "Created:",
-                created,
-            );
-
-            // Check if we got hardware manager and it actually created a key
-            if (manager.getType() !== "hardware") {
-                throw new Error("Got software fallback instead of hardware");
-            }
-
-            // Hardware works! Clean up test key and proceed
-            console.log("Hardware keys are working");
-            checkingHardware = false;
-        } catch (keyError) {
-            console.error("Hardware key test failed:", keyError);
-            showHardwareError = true;
-            checkingHardware = false;
-        }
-    } catch (err) {
-        console.error("Error checking hardware:", err);
-        showHardwareError = true;
-        checkingHardware = false;
-    }
+    checkingHardware = true;
+    showHardwareError = false;
+    error = null;
+
+    try {
+        if (!globalState) {
+            globalState = getContext<() => GlobalState>("globalState")();
+        }
+
+        const hardwareAvailable =
+            await globalState.keyService.isHardwareAvailable();
+
+        checkingHardware = false;
+        showHardwareError = !hardwareAvailable;
+    } catch (err) {
+        console.error("Error checking hardware:", err);
+        showHardwareError = true;
+        checkingHardware = false;
+    }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
in infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte around
lines 42-78, stop creating throwaway hardware keys with ensureKey because it
triggers the full credential ceremony and leaves persistent test credentials;
instead call the service's non-destructive probe (e.g., isHardwareAvailable() or
similar) to detect hardware capability, remove the testKeyId generation and
ensureKey invocation, and use the boolean result to set showHardwareError and
checkingHardware accordingly; also remove any catch branches specific to key
creation and only handle probe errors (set showHardwareError=true,
checkingHardware=false) without creating or attempting to clean up credentials.

Copy link
Contributor

Choose a reason for hiding this comment

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

nack, that's the only way to do it

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the key service implementation to see what methods are available
echo "=== Searching for KeyService class definition ==="
ast-grep --pattern 'class KeyService {
  $$$
}'

echo -e "\n=== Searching for isHardwareAvailable method ==="
rg -n "isHardwareAvailable" --type ts

echo -e "\n=== Searching for hardware capability check methods ==="
rg -nP "(checkHardware|isHardware|hardwareAvailable|canUseHardware)" --type ts -C2

echo -e "\n=== Finding KeyService file ==="
fd -e ts -e js "KeyService" --full-path

echo -e "\n=== Searching for KeyManager availability checks ==="
rg -n "getType\(\)" --type ts -g "*KeyManager*" -C2

Length of output: 21879


🏁 Script executed:

#!/bin/bash
# Get the full implementation of isHardwareAvailable to understand what it checks
echo "=== KeyManagerFactory.isHardwareAvailable implementation ==="
ast-grep --pattern 'static async isHardwareAvailable(): Promise<boolean> {
  $$$
}'

echo -e "\n=== Find the full KeyManagerFactory file ==="
fd "KeyManagerFactory.ts" --full-path

echo -e "\n=== Get lines 65-80 of KeyManagerFactory to see isHardwareAvailable ==="
find . -name "KeyManagerFactory.ts" -exec sed -n '65,80p' {} \;

echo -e "\n=== Check what getHardwareKeyManager does ==="
ast-grep --pattern 'static getHardwareKeyManager() {
  $$$
}'

Length of output: 880


🏁 Script executed:

#!/bin/bash
# Check what the exists() method does in HardwareKeyManager
echo "=== HardwareKeyManager.exists() implementation ==="
cat infrastructure/eid-wallet/src/lib/crypto/HardwareKeyManager.ts

echo -e "\n=== Check if exists() might trigger a credential ceremony ==="
rg -n "exists.*credential|exists.*prompt|exists.*biometric" --type ts -C3

Length of output: 4760


@coodos, understood — if generating a real test key is the only reliable way to verify hardware support, I'll defer to your experience with the platform.

That said, the test keys created with hardware-test-${Date.now()} are never cleaned up. Each "Get Started" click will leave behind a persistent credential in the hardware keystore, which could accumulate over time or exhaust limited key slots on some devices.

Would you consider adding cleanup logic after the hardware check completes (success or failure)? Something like:

try {
    const { manager, created } = await globalState.keyService.ensureKey(
        testKeyId,
        "onboarding",
    );
    // ... existing checks ...
    
    // Clean up test key
    if (created && manager.getType() === "hardware") {
        // Delete the test key if your KeyManager supports it
        // or track it for later cleanup
    }
} catch (keyError) {
    // ... existing error handling ...
}

If the hardware API doesn't expose a delete/cleanup method, at minimum tracking these test key IDs for bulk cleanup later would prevent them from accumulating indefinitely.

@coodos coodos merged commit 5982c51 into main Nov 13, 2025
4 checks passed
@coodos coodos deleted the fix/hardware-crypto-context-logic branch November 13, 2025 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Hardware module gets used on software key eName

4 participants