Vendors carrier's locales/en-US/main.ftl (extended to cover gsmol's
remaining strings) as the single source both clients draw wording
from, adds a dependency-free .ftl-to-JSON build step (devbox run
locale) since the file only ever uses Fluent's flat subset, and
replaces every hardcoded string in index.html/app.js with a lookup
into the generated dictionary.
Along the way: removes connect()'s requirePin check, which turned out
to be unreachable under the app's own invariants (every call site
already guarantees its target host is pinned before calling it), and
fixes a leftover call to store.setMasterSaved — removed in the earlier
settings redesign — that was silently breaking onboarding's "I saved
it" button.
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.
Drops the per-server pin list down to the one server your account is
bound to, adds an enforced network timeout, and replaces the global
status toast inside settings with inline feedback and a reusable
confirm dialog for rotate/log out. Mail-fetching preferences move into
the server tab; the now-superseded claim/recall forms are gone since
onboarding covers both.
Generate-or-recover an identity, establish server trust, then bind an
address — each its own screen with no bleed-through, replacing the
old intro/restore cards plus the post-hoc setup checklist banner.