diff --git a/src/routes/idaa/(idaa)/+layout.svelte b/src/routes/idaa/(idaa)/+layout.svelte index cde4d444..f8d2164f 100644 --- a/src/routes/idaa/(idaa)/+layout.svelte +++ b/src/routes/idaa/(idaa)/+layout.svelte @@ -102,7 +102,20 @@ $effect(() => { if (trusted_li?.length) $idaa_loc.novi_trusted_li = trusted_li; verify_in_flight = true; - novi_verifying = true; + // WHY: Only show the "Verifying identity..." spinner on initial load when the user + // has NO existing valid session. If the TTL expired and we're re-verifying in the + // background (user is already authenticated), run silently — do NOT set + // novi_verifying=true. Setting it would hide children and destroy any running + // components (e.g. Jitsi mid-call). The user can keep working; access is only + // revoked in the catch block if the re-verification actively fails. + const has_valid_session = + $ae_loc.trusted_access || + ($ae_loc.authenticated_access && + $idaa_loc.novi_verified && + $idaa_loc.novi_uuid === url_uuid); + if (!has_valid_session) { + novi_verifying = true; + } verify_novi_uuid(url_uuid, api_key, api_root); }); }); @@ -119,18 +132,23 @@ async function verify_novi_uuid( api_root_url: string, is_retry: boolean = false ) { - console.log(`IDAA Layout: Starting Novi UUID verification for ${uuid}...`); if (!api_key) { - // No Novi API key in site config. All-or-nothing means no UUID-based access. - console.warn('IDAA Layout: Novi API key not configured. UUID-based access denied.'); - $idaa_loc.novi_uuid = null; - $idaa_loc.novi_email = null; - $idaa_loc.novi_full_name = null; - $idaa_loc.novi_verified = false; + // WHY: Do NOT clear $idaa_loc state here, and do NOT log "Starting verification". + // The api_key can be transiently null when $ae_loc.site_cfg_json hasn't finished + // loading (SWR: root layout fires $ae_loc = new_loc before cfg is in the store). + // Clearing novi_verified/novi_uuid here would destroy a valid cached session, making + // the TTL check fail on the very next Effect 2 run — causing a re-auth loop. + // If the api_key is genuinely not configured, $idaa_loc starts with + // novi_verified=false and novi_uuid=null (defaults), so access is denied naturally. + // novi_verifying is left at its current value intentionally: + // - If has_valid_session was false above, novi_verifying=true (spinner stays visible + // until api_key loads and Effect 2 re-runs with a real key). + // - If has_valid_session was true, novi_verifying=false (children keep rendering). + console.warn('IDAA Layout: Novi API key not yet available — skipping verification (will retry when site_cfg_json loads).'); verify_in_flight = false; - novi_verifying = false; return; } + console.log(`IDAA Layout: Starting Novi UUID verification for ${uuid}...`); try { const headers = new Headers();