From 94c5346eda1db315008b338d28f10730be95d1ca Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Mon, 2 Mar 2026 19:28:13 -0800 Subject: [PATCH] fix: account completion indicators, email verify token type, SW cache - Add /api/account/status endpoint returning email, multi-device, social recovery completion state - Show red/green status dots on Account modal section headers for incomplete vs complete steps (email, device, recovery, data storage) - Highlight Data Storage section with red warning when using local-only storage so users know they're responsible for their own data - Fix email verification 500 error: change token type from 'email_verification' to 'email_verify' to match DB check constraint - Fix service worker: skip non-http(s) schemes to prevent chrome-extension:// cache put errors Co-Authored-By: Claude Opus 4.6 --- shared/components/rstack-identity.ts | 72 +++++++++++++++++++++++----- src/encryptid/db.ts | 2 +- src/encryptid/server.ts | 41 +++++++++++++++- website/sw.ts | 3 ++ 4 files changed, 103 insertions(+), 15 deletions(-) diff --git a/shared/components/rstack-identity.ts b/shared/components/rstack-identity.ts index 31313b3..b1e2c0a 100644 --- a/shared/components/rstack-identity.ts +++ b/shared/components/rstack-identity.ts @@ -712,6 +712,9 @@ export class RStackIdentity extends HTMLElement { let openSection: string | null = null; + // Account completion status + let acctStatus: { email: boolean; multiDevice: boolean; socialRecovery: boolean; guardianCount: number; credentialCount: number } | null = null; + // Lazy-loaded data let guardians: { id: string; name: string; email?: string; status: string }[] = []; let guardiansThreshold = 2; @@ -727,11 +730,36 @@ export class RStackIdentity extends HTMLElement { const close = () => overlay.remove(); + // Load account completion status + const loadStatus = async () => { + try { + const res = await fetch(`${ENCRYPTID_URL}/api/account/status`, { + headers: { Authorization: `Bearer ${getAccessToken()}` }, + }); + if (res.ok) { + acctStatus = await res.json(); + render(); + } + } catch { /* offline */ } + }; + loadStatus(); + + const statusDot = (done: boolean | null) => { + if (done === null) return ''; // still loading + return done + ? '' + : ''; + }; + const render = () => { const backupEnabled = isEncryptedBackupEnabled(); const currentTheme = localStorage.getItem("canvas-theme") || "dark"; const isDark = currentTheme === "dark"; + const emailDone = acctStatus ? acctStatus.email : null; + const deviceDone = acctStatus ? acctStatus.multiDevice : null; + const recoveryDone = acctStatus ? acctStatus.socialRecovery : null; + overlay.innerHTML = `