diff --git a/docs/KNOWN_BUGS.md b/docs/KNOWN_BUGS.md index ea8d8a5e..40352a3c 100644 --- a/docs/KNOWN_BUGS.md +++ b/docs/KNOWN_BUGS.md @@ -11,6 +11,35 @@ refactor work in that doc — these are defects. ## Open +### 0. Encrypted lists (hashtags, DMs, blocks) fail to DECRYPT on login *(top priority)* +- **Severity:** high — the user's recurring "hashtags/DMs/watch-history don't + load in the profile modal." +- **Diagnosed from real-env console (2026-06-14):** the lists are *fetched* (e.g. + block events `Array(2)`) but **decryption fails**, three different ways: + - DMs: `DM decryption helpers are unavailable` (`client.js` listDirectMessages + → `buildDmDecryptContext` returns 0 decryptors → hard throw, no retry). Happens + when `ensureExtensionPermissions` returns `ok:false`. + - Blocks: `Decryption timed out; signerStatus: 'missing'/'unknown'` + (`userBlocks.js` applyEvents) — the signer/decrypt capability isn't resolved. + - Hashtags: `Decryption timed out after 6s` (`hashtagPreferencesService.js`). +- **Root cause (strong):** a relay-connection STORM. On cold load the app opens + WebSockets to the user's full ~20-relay NIP-65 list (most **dead**) because + subsystems build relay lists from `relayManager.getReadRelayUrls()` + + `getWriteRelayUrls()` (uncapped) — e.g. `userBlocks.loadBlocksInternal`. The + dozens of failing connections churn the main thread and starve the nip-07 + extension's postMessage round-trips → permission/decrypt calls fail or time out. +- **Partial mitigation shipped:** hashtag + subscription decrypt timeout 6s→15s. +- **Proper fix (next):** RelayHealth — bound the SUBSCRIBE/read set to a small, + liveness-ranked healthy core that ALWAYS includes the reliable default + aggregators, applied centrally so every subsystem (blocks, hashtags, subs, + profiles, batch fetcher) reads from it; writes stay uncapped. Plus decrypt + resilience: don't hard-fail DMs on a transient permission miss (retry). + NOTE: a first attempt (`capReadRelays`) was reverted — capping the block-list + read path broke the security-critical `user-blocks` integration test (it + orchestrates per-relay block hydration), so this needs a test-aware rework. + Repro: `scripts/perf/disclaimer-repro.mjs` shape; real-env console is the + source of truth. + ### 1. Logged-out: video grid stays empty until a manual refresh - **Severity:** medium (first-load UX, logged-out). - **Where:** initial feed render path (`js/index.js` disclaimer flow → diff --git a/js/services/hashtagPreferencesService.js b/js/services/hashtagPreferencesService.js index b3afa4a1..bdc967e7 100644 --- a/js/services/hashtagPreferencesService.js +++ b/js/services/hashtagPreferencesService.js @@ -42,11 +42,11 @@ const LOG_PREFIX = "[HashtagPreferences]"; const HASHTAG_IDENTIFIER = "bitvid:tag-preferences"; const DEFAULT_VERSION = 1; -// PERF: Reduced from 10s to 6s — the signer is guaranteed ready before list -// loading starts (authSessionCoordinator waits for the permission pre-grant), -// so decryption should succeed within 2-3s. 6s is generous enough for slow -// relays while still failing fast for scheme fallback. -const DECRYPT_TIMEOUT_MS = 6000; +// Cold-load decryption competes with other encrypted lists for the serialized +// nip-07 extension, and the main thread can be busy connecting to relays. 6s +// proved too aggressive on real accounts (lists timed out and showed empty); +// 15s matches the block-list timeout and lets decryption complete under load. +const DECRYPT_TIMEOUT_MS = 15000; // PERF: Reduced from 3s to 1.5s — extensions that already granted permission // should recover near-instantly. Shorter delay speeds up the login path. const DECRYPT_RETRY_DELAY_MS = NETWORK_RETRY_DELAY_MS; diff --git a/js/subscriptions.js b/js/subscriptions.js index 5a2f2d10..b04e2a05 100644 --- a/js/subscriptions.js +++ b/js/subscriptions.js @@ -53,7 +53,7 @@ const SUBSCRIPTION_SET_KIND = // so decryption should succeed within 2-3s. 6s is generous enough for slow // relays while still failing fast enough for the scheme fallback to try the // next decryption method without stalling the login path. -const DECRYPT_TIMEOUT_MS = 6000; +const DECRYPT_TIMEOUT_MS = 15000; // PERF: Reduced from 3s to 1.5s — extensions that already granted permission // should recover near-instantly. The shorter delay prevents unnecessary wait // time during the critical login path when the first decrypt attempt fails.