From 032732cea1014ac1e199543e2af4e138729d6b6e Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Sat, 29 Aug 2026 17:57:33 +0200 Subject: [PATCH] fix: check the account-level Stalwart capability and keep the stored password in step after a change (#47) --- src/api/account-security.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/api/account-security.ts b/src/api/account-security.ts index f23da402..52a4db71 100644 --- a/src/api/account-security.ts +++ b/src/api/account-security.ts @@ -48,10 +48,13 @@ type MethodResponse = [string, Record, string]; // True once a live session advertises Stalwart's JMAP extension. Without it // none of the x:* methods exist, so the screen shows a "not available" notice. +// Stalwart lists `urn:stalwart:jmap` only under the account's +// `accountCapabilities` (verified on 0.16.19), never at session level, so the +// account-level map is what has to be checked (native #47). export function isStalwartSupported(): boolean { const session = jmapClient.currentSession; - if (!session) return false; - return STALWART_CAPABILITY in (session.capabilities ?? {}); + if (!session || !jmapClient.isConnected) return false; + return jmapClient.hasAccountCapability(STALWART_CAPABILITY); } // Pull a single method response out by its call id and throw on a JMAP method @@ -194,6 +197,9 @@ export async function changePassword(currentPassword: string, newPassword: strin const result = resultFor<{ notUpdated?: Record }>(responses, '0'); const failure = result.notUpdated?.singleton; if (failure) throw new Error(failure.description || failure.type || 'Failed to change password'); + // The stored credential must follow, otherwise the next request 401s and + // the next launch evicts the account. + await jmapClient.updatePassword(newPassword); } export async function updateDisplayName(displayName: string): Promise {