From 7bbf8baf86d9ef3a6078f2dae330c46375d2d12c Mon Sep 17 00:00:00 2001 From: Jason Tudisco Date: Thu, 28 May 2026 14:37:13 -0600 Subject: [PATCH] feat(kez-chat/web): show verified badge in chat; require 2+ proofs The verified checkmark only appeared on the profile, never in chat, even for clearly-verified peers. Three gaps fixed: - Chat verified only the open conversation, so list items never showed a badge. Verify all conversations on load (24h per-peer cache). - A peer's proofs were only published to the server on a manual "reverify all", so verified users were invisible to peers. Auto-publish verified subjects when the Identity page loads. - Unify the threshold: a badge now requires >=2 independently-verified proofs, in both chat (VERIFY_MIN_PROOFS) and the profile (isVerified), so "verified" means the same thing everywhere. Co-Authored-By: Claude Opus 4.7 --- kez-chat/web/src/routes/Identity.svelte | 15 ++++++- kez-chat/web/src/routes/Messages.svelte | 58 +++++++++++++++---------- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/kez-chat/web/src/routes/Identity.svelte b/kez-chat/web/src/routes/Identity.svelte index 03269ae..0444bbf 100644 --- a/kez-chat/web/src/routes/Identity.svelte +++ b/kez-chat/web/src/routes/Identity.svelte @@ -21,12 +21,25 @@ const failed = $derived(claims.filter((c) => c.last_verify?.status === "fail")); const pending = $derived(claims.filter((c) => !c.last_verify)); + // Verified badge requires at least this many independently-verified + // proofs. Kept in sync with VERIFY_MIN_PROOFS in Messages.svelte so the + // badge means the same thing on the profile and in chat. + const VERIFY_MIN_PROOFS = 2; + const isVerified = $derived(verified.length >= VERIFY_MIN_PROOFS); + onMount(async () => { if (!session.unlocked) { push("/unlock"); return; } claims = await listClaims(); + // Publish our verified proof subjects to the server profile so peers + // can discover + independently verify them (drives our badge in their + // chat). Previously this only happened on a manual "reverify all", so + // verified users were invisible to peers until they clicked it. + if (claims.some((c) => c.last_verify?.status === "ok")) { + void publishVerifiedSubjects(); + } try { registryRecord = await lookup(session.unlocked.handle); } catch (e) { @@ -109,7 +122,7 @@
{session.unlocked.handle}@{session.unlocked.server} - {#if verified.length > 0}{/if} + {#if isVerified}{/if}