Verify somebody from their profile, and see who cannot be

A profile card on Matrix now offers to verify the person it describes -
which is where the question comes up, since it is asked about somebody
rather than about a device.

A message from a device nobody has vouched for carries a warning beside the
sender's name, using the badge path Kick's own badges already run on. It
gets its own short form and its own colour: every other badge here is a
title, and this one is a doubt.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-04 21:01:38 -04:00
co-authored by Claude Opus 5
parent 52c1da9b0c
commit 6a81c50d51
4 changed files with 40 additions and 2 deletions
+1 -1
Submodule nobilis updated: e591b2f540...e0748ea21d
+10
View File
@@ -3754,6 +3754,16 @@ video.lightbox-media {
color: var(--primary);
}
/* The one badge that is a warning rather than a title: this message came
from a device nobody has vouched for. Coloured like an error and left
uncoloured nowhere else, because a doubt about who sent something is the
only thing here worth interrupting a name to say. */
.sender-badge.unverified {
background: transparent;
border: 1px solid var(--error);
color: var(--error);
}
.channel-modes {
padding: 1px var(--spacing-xs);
border-radius: var(--corner-radius-small);
+5 -1
View File
@@ -54,7 +54,11 @@ function badgeLabel(badge: MessageBadge): string {
og: 'OG',
vip: 'VIP',
staff: 'STAFF',
sub_gifter: 'GIFT'
sub_gifter: 'GIFT',
// Not a title like the rest of these - a warning that whoever sent this
// was using a device nobody has vouched for. Without its own short form
// the fallback below would abbreviate the explanation into "SEN".
unverified: '⚠'
}
return short[badge.type] ?? badge.text.slice(0, 3).toUpperCase()
}
@@ -100,6 +100,30 @@ export function ProfileCard(): JSX.Element | null {
</div>
)}
{/* Vouching for somebody, which is a different thing from checking
one of your own sessions: it says this really is them, to every
client of yours and to anybody who trusts you. Matrix only,
because it is the only protocol here with an identity to sign. */}
{profile.service === 'matrix' && profile.id && !profile.pending && (
<div className="button-row profile-actions">
<button
type="button"
className="button subtle"
onClick={() => {
void window.moho
.rpc('startMatrixUserVerification', {
accountId: profile.accountId,
userId: profile.id
})
.then(() => store.closeProfile())
.catch((e: Error) => store.toast('error', e.message))
}}
>
<Icon name="person_check" size={15} /> Verify {profile.name}
</button>
</div>
)}
{profile.pending && (
<p className="small muted profile-waiting">
<span className="spinner" /> Asking {profile.service}…