docs: mark IDAA server-side Novi verification resolved in TODO__Agents.md

All Access Denied root causes fixed and deployed 2026-05-19. 503 auto-retry
regression also documented and fixed same session.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-05-19 19:47:46 -04:00
parent 861385b4ff
commit 932deced12

View File

@@ -83,11 +83,17 @@ All known root causes fixed across 10+ commits to `src/routes/idaa/(idaa)/+layou
Deploying as of 2026-05-19. Monitor for further member reports.
#### All fixes applied
- [x] **Server-side Novi verification migrated (key fix for hotel/VPN/Cloudflare-filtered networks)**
`verify_novi_uuid()` now calls `GET /v3/action/idaa/novi_member/{uuid}` through the Aether
backend (server-to-server, Redis-cached 4h) instead of making a browser-to-Novi call.
Eliminates false Access Denied for members on hotel/conference WiFi, VPNs, and corporate
networks where the member's IP was rejected by Novi/Cloudflare.
Frontend: `(idaa)/+layout.svelte` | Backend: FastAPI `aether_api_fastapi` | Docs: `GUIDE__AE_API_V3_for_Frontend.md` §12, `CLIENT__IDAA_and_customized_mods.md`
- [x] Novi TTL extended to **12 hours** (5 min → 45 min → 12 h) — covers a full conference day
- [x] Access Denied on iframe reload (sessionStorage URL preservation) — `2855e091f`
- [x] TTL cache bypassed when `$ae_loc` auth flags reset — `2855e091f`
- [x] "Verification Unavailable" screen distinct from "Access Denied" — `2855e091f`
- [x] "Try Again" without page reload (`retry_count` pattern) — `2855e091f`
- [x] Novi TTL extended to 45 minutes (from 5) — `2855e091f` + manual edit
- [x] 12 s AbortController hard timeout on Novi fetch — `e921ca973`
- [x] Network/AbortError gets 3 s grace + one retry — `e921ca973`
- [x] Clear Cache & Reload added to Access Denied state (iframe mode) — `2855e091f`
@@ -111,6 +117,60 @@ below. The TTL + `verify_in_flight` guards are the current mitigation.
---
### [IDAA] Server-side Novi verification — 503 not auto-retried (regression, 2026-05-19)
**File:** `src/routes/idaa/(idaa)/+layout.svelte``verify_novi_uuid()`
**Bug:** After migrating to the Aether server-side proxy, a `503` response (Novi unreachable /
Novi 5xx) skips the automatic retry that exists for network-level errors.
**Root cause:** The auto-retry branch only fires for `TypeError` and `AbortError`:
```ts
const is_network_or_timeout =
error instanceof TypeError ||
(error instanceof Error && error.name === 'AbortError');
if (is_network_or_timeout && !is_retry) {
// 3s wait → retry
}
```
In the old client-to-Novi flow, an unreachable Novi server produced a `TypeError: Failed to
fetch` — caught above, auto-retried. In the new flow the Aether server returns a clean HTTP
`503`, which hits `!response.ok``throw new Error(...)` — a plain `Error`, not `TypeError`.
`is_network_or_timeout` is `false` → no retry → `verify_failed_for_uuid` latch is set
immediately → user sees "Verification Unavailable" requiring a manual "Try Again" click for
what may be a 2-second Novi hiccup.
**Fix:** Add a `503` check before the generic `!response.ok` throw (or after), applying the
same 3-second wait + one retry that network errors get:
```ts
if (response.status === 503) {
if (is_retry) {
throw new Error(`Novi verification: Novi unreachable (503) — retry also failed`);
}
console.warn(`IDAA Layout: Novi unreachable (503) for ${uuid}. Retrying in 3s...`);
verifying_status_msg = 'Connection issue — retrying...';
await new Promise<void>((resolve) => setTimeout(resolve, 3_000));
await verify_novi_uuid(uuid, true);
return;
}
if (!response.ok) {
throw new Error(`Novi verification returned ${response.status} for UUID ${uuid}`);
}
```
**Catch block:** After the retry, if 503 still fires, it throws a plain `Error` → caught →
`is_network_or_timeout = false``verify_error_type = 'api_error'` → "Verification
Unavailable". This is correct — after two attempts the UI should tell the user.
**Note on `verify_error_type` reset:** The recursive retry call resets `verify_error_type =
null` at its top before checking the response. For 429 this is harmless (re-set on 429 check).
For 503 after this fix it is also harmless — 503 is caught before `!response.ok`. Worth knowing
if modifying the flow further.
---
### [Stores] Svelte 4 → Svelte 5 State Migration (prerequisite for Phase 2c)
The app uses `svelte-persisted-store` (Svelte 4 store contract) for all core persisted state
(`ae_loc`, `idaa_loc`, `ae_api`, `ae_sess`, etc.). In Svelte 5 `$effect`, reading **any field**