feat: refuse to learn a first-contact key from an unpinned server
Adds an opt-in "require a pinned server" setting that gates the one RESOLVE path that currently trusts whatever key a server hands back for a brand-new, hand-typed address — self-certifying addresses and already-known contacts are structurally exempt. A refusal shows an inline recovery card in compose to fetch, compare, and pin the key without losing the draft. Also closes two adjacent gaps: a self-certifying address could silently overwrite an already-trusted contact's key (now asks, showing both fingerprints), and a contact's detail view now names its server and pin state.
This commit is contained in:
parent
84397a3fdd
commit
80aca8a29f
4 changed files with 192 additions and 10 deletions
|
|
@ -431,9 +431,14 @@ dialog::backdrop { background: var(--backdrop); }
|
|||
.dialog-head .icon-only { color: var(--muted); }
|
||||
.dialog-head .icon-only:hover { color: var(--fg); }
|
||||
|
||||
/* The recovery card can push content past the viewport on a short window;
|
||||
dialog's own overflow:hidden would just clip it with no way back. */
|
||||
#compose { overflow-y: auto; }
|
||||
#compose form { display: flex; flex-direction: column; gap: 10px; padding: 20px 22px; }
|
||||
#compose input, #compose textarea { width: 100%; }
|
||||
#compose textarea { font-family: inherit; resize: vertical; }
|
||||
#compose .seed-card { margin: 0; }
|
||||
#compose .actions { display: flex; gap: 8px; margin: 4px 0; }
|
||||
#compose footer { display: flex; gap: 8px; align-items: center; justify-content: flex-end; padding-top: 4px; flex-wrap: wrap; }
|
||||
#compose .anon { font-size: 13px; color: var(--muted); margin-right: auto; display: flex; align-items: center; gap: 6px; white-space: nowrap; }
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue