diff --git a/infrastructure/eid-wallet/src/routes/(app)/personal/components/AddKnowledgeSheet.svelte b/infrastructure/eid-wallet/src/routes/(app)/personal/components/AddKnowledgeSheet.svelte index d3578f677..d1dd26bf2 100644 --- a/infrastructure/eid-wallet/src/routes/(app)/personal/components/AddKnowledgeSheet.svelte +++ b/infrastructure/eid-wallet/src/routes/(app)/personal/components/AddKnowledgeSheet.svelte @@ -2,7 +2,11 @@ import { ButtonAction } from "$lib/ui"; import BottomSheet from "$lib/ui/BottomSheet/BottomSheet.svelte"; import { PERSONAL_BINDING_MAX_LENGTH } from "$lib/utils/personalBinding"; -import { Cancel01Icon } from "@hugeicons/core-free-icons"; +import { + Cancel01Icon, + ViewIcon, + ViewOffIcon, +} from "@hugeicons/core-free-icons"; import { HugeiconsIcon } from "@hugeicons/svelte"; interface IAddKnowledgeSheetProps { @@ -19,6 +23,9 @@ let { let question = $state(""); let answer = $state(""); +// The answer is sensitive — mask it by default, with an eye toggle to reveal +// (the spelling tip above means the user needs to be able to check it). +let showAnswer = $state(false); // On open: seed the question from the prop. Answer always starts blank — // we never round-trip the raw answer, so editing means re-entering it. @@ -26,6 +33,7 @@ $effect(() => { if (!isOpen) return; question = currentQuestion; answer = ""; + showAnswer = false; }); const canSave = $derived( @@ -85,17 +93,35 @@ function close() { - +
+ + +
{#if answer.length > PERSONAL_BINDING_MAX_LENGTH - 150}

{answer.length} / {PERSONAL_BINDING_MAX_LENGTH} diff --git a/infrastructure/eid-wallet/src/routes/(public)/recover/+page.svelte b/infrastructure/eid-wallet/src/routes/(public)/recover/+page.svelte index e03fd1c71..af87a8479 100644 --- a/infrastructure/eid-wallet/src/routes/(public)/recover/+page.svelte +++ b/infrastructure/eid-wallet/src/routes/(public)/recover/+page.svelte @@ -13,7 +13,11 @@ import BottomSheet from "$lib/ui/BottomSheet/BottomSheet.svelte"; import LoadingSheet from "$lib/ui/LoadingSheet/LoadingSheet.svelte"; import { capitalize } from "$lib/utils"; import { PERSONAL_BINDING_BY_TYPE_QUERY } from "$lib/utils/personalBinding"; -import { ArrowLeft01Icon } from "@hugeicons/core-free-icons"; +import { + ArrowLeft01Icon, + ViewIcon, + ViewOffIcon, +} from "@hugeicons/core-free-icons"; import { HugeiconsIcon } from "@hugeicons/svelte"; import { Format, @@ -124,6 +128,9 @@ let enameLoading = $state(false); let answerInput = $state(""); let answerError = $state(null); let answerLoading = $state(false); +// The security answer is sensitive — mask it by default, with an eye toggle +// to reveal (spelling matters, so the user needs to be able to check it). +let showAnswer = $state(false); // Question text + envelope id are pulled from the target eVault during // handleSubmitEname. The envelope id is the metaEnvelopeId of the @@ -554,6 +561,7 @@ async function handleSubmitEname() { answerInput = ""; answerError = null; lockedUntilLabel = null; + showAnswer = false; step = "unverified-answer"; } catch (err: unknown) { console.error("[RECOVERY/unverified] eName lookup error:", err); @@ -1337,17 +1345,35 @@ onMount(() => { > {securityQuestion} * - +

+ + +
{#if answerError}