fix(idaa): add VPN/network hint, bump TTL to 12h, document server-side verify plan

- Classify persistent network/timeout failures as 'network_error' (separate from
  generic 'api_error') so the UI can show a targeted message
- Add actionable hint for members on hotel WiFi, VPN, or corporate networks:
  turn off VPN, switch to cellular, try a different network
- Extend VERIFIED_TTL_MS_DEFAULT from 45 min to 12 hours — covers a full workday
  so members at conferences do not need to re-verify mid-day
- Document planned server-side Novi verification FastAPI endpoint in
  CLIENT__IDAA_and_customized_mods.md (once implemented, eliminates client-side
  Cloudflare/IP-reputation exposure entirely)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-05-19 18:23:45 -04:00
parent 71e79f032d
commit 6755a68b13
2 changed files with 48 additions and 5 deletions

View File

@@ -66,7 +66,7 @@ let verify_failed_for_uuid: string | null = null;
// Tracks the type of Novi API failure for the UI — 'rate_limited' or 'api_error'.
// A transient API error is NOT the same as a real membership denial; this lets us
// show a distinct "Verification Unavailable" state instead of "Access Denied".
let verify_error_type: 'rate_limited' | 'api_error' | null = $state(null);
let verify_error_type: 'rate_limited' | 'api_error' | 'network_error' | null = $state(null);
// Shown inside the spinner — updated during rate-limit retry waits.
let verifying_status_msg: string = $state('Verifying identity...');
// Incremented by handle_verify_retry() to re-run Effect 2 without a full page reload.
@@ -148,7 +148,10 @@ $effect(() => {
}
});
const VERIFIED_TTL_MS_DEFAULT = 45 * 60 * 1000; // 45 minutes
// WHY 12 hours: members open IDAA in a hotel/conference context and should not need to
// re-verify mid-day. After our client-side Novi call is replaced by server-side (FastAPI),
// this TTL can be tuned independently. Until then, 12h covers a full workday.
const VERIFIED_TTL_MS_DEFAULT = 12 * 60 * 60 * 1000; // 12 hours
// Effect 1: Set URL origin and params
$effect(() => {
@@ -451,8 +454,14 @@ async function verify_novi_uuid(
error
);
verify_failed_for_uuid = uuid; // Latch — stop retry loop for this UUID. See declaration comment.
// 'rate_limited' is set before throw for 429; everything else is an unexpected API error.
if (!verify_error_type) verify_error_type = 'api_error';
// 'rate_limited' is set before throw for 429.
// 'network_error' for persistent network/timeout failures after retry — both the first
// attempt AND the auto-retry failed with TypeError/AbortError. Most common cause: hotel/
// conference WiFi, VPN, or Cloudflare IP reputation blocking the client-side Novi call.
// 'api_error' for everything else (4xx, 5xx, empty 200).
if (!verify_error_type) {
verify_error_type = is_network_or_timeout ? 'network_error' : 'api_error';
}
$idaa_loc.novi_uuid = null;
$idaa_loc.novi_email = null;
$idaa_loc.novi_full_name = null;
@@ -538,9 +547,19 @@ function handle_verify_retry() {
<p class="text-sm">
The membership directory is temporarily busy (rate limited). Please wait a moment and try again.
</p>
{:else if verify_error_type === 'network_error'}
<p class="text-sm">
We were unable to reach the membership directory after two attempts. This is usually caused by a network filter blocking the connection — it is not a problem with your membership.
</p>
<ul class="mt-1 list-disc pl-5 text-left text-sm">
<li>Turn off your VPN if one is running</li>
<li>Switch from hotel or conference WiFi to your phone's cellular data</li>
<li>Try a different network (mobile data, home WiFi)</li>
<li>If on a corporate or hospital network, try from a personal device</li>
</ul>
{:else}
<p class="text-sm">
We were unable to connect to the membership directory. This is usually a temporary network issue — it is not a problem with your membership or access.
We were unable to connect to the membership directory. This is usually a temporary issue — it is not a problem with your membership or access.
</p>
{/if}
<p class="text-xs italic text-gray-500">