mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
A raw window.nostr probe in the user's browser (getPublicKey → nip04.encrypt
→ nip04.decrypt, bypassing ALL of bitvid) HUNG forever, with the extension's
own console showing `ObjectMultiplex - orphaned data for "background-liveness"`
+ `malformed chunk` + listener-leak warnings. That is the NIP-07 extension's
content-script ↔ background-service-worker channel being dead (classic MV3
worker death) — an extension/environment failure, not a bitvid bug. No client
change can force an unresponsive signer to answer; the fix is to reload/unlock
the extension.
What bitvid CAN do is stop failing silently. Add js/utils/signerHealthNotice.js:
after a few consecutive list-decrypt timeouts while the signer reports itself
present, emit ONE rate-limited, actionable user notice ("your signer isn't
responding to decryption — unlock/reload the extension and refresh") instead of
the silent 15-minute retry loop. Reset on any decrypt success so a transient
blip doesn't warn. Wired into blocks, hashtags, and subscriptions.
Also documents the definitive root-cause + all resilience increments in
KNOWN_BUGS #0. Test: tests/signer-health-notice.test.mjs (threshold, rate-limit,
success-reset). Full unit suite green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
69 lines
2.3 KiB
JavaScript
69 lines
2.3 KiB
JavaScript
// Shared "is the signer actually answering?" notice.
|
|
//
|
|
// When encrypted lists (blocks, subscriptions, hashtags, DMs) repeatedly time
|
|
// out DESPITE a resolved signer (signerStatus "present"), the cause is almost
|
|
// always the NIP-07 extension's background/service-worker channel being
|
|
// unresponsive — not bitvid (confirmed by a raw window.nostr probe hanging;
|
|
// see KNOWN_BUGS #0). Silently retrying forever leaves the user with no idea
|
|
// why their lists never load. This surfaces ONE clear, actionable message so
|
|
// they can unlock/reload the extension, then stays quiet so it never spams.
|
|
|
|
import { userLogger } from "./logger.js";
|
|
|
|
const CONSECUTIVE_TIMEOUT_THRESHOLD = 3;
|
|
const NOTICE_COOLDOWN_MS = 120_000;
|
|
|
|
const NOTICE_MESSAGE =
|
|
"Your Nostr signer extension isn't responding to decryption requests, so " +
|
|
"encrypted data (hashtags, subscriptions, block list, DMs) can't load. This " +
|
|
"is usually the extension's background worker going to sleep or getting " +
|
|
"stuck. Try unlocking it and/or reloading the extension (toggle it off and " +
|
|
"on from your browser's extensions page), then refresh bitvid.";
|
|
|
|
let consecutiveTimeouts = 0;
|
|
let lastNoticeAt = 0;
|
|
let lastDetail = null;
|
|
|
|
/**
|
|
* Record that a list decrypt timed out while the signer reported itself present.
|
|
* After a few consecutive such timeouts, emit ONE user-facing notice (rate
|
|
* limited) telling the user their signer is unresponsive.
|
|
*/
|
|
export function noteSignerDecryptTimeout(context = "list") {
|
|
consecutiveTimeouts += 1;
|
|
lastDetail = { context, consecutiveTimeouts, at: Date.now() };
|
|
const now = Date.now();
|
|
if (
|
|
consecutiveTimeouts >= CONSECUTIVE_TIMEOUT_THRESHOLD &&
|
|
now - lastNoticeAt > NOTICE_COOLDOWN_MS
|
|
) {
|
|
lastNoticeAt = now;
|
|
userLogger.error(`[signer-unresponsive] ${NOTICE_MESSAGE}`, {
|
|
context,
|
|
consecutiveTimeouts,
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Record that a signer call succeeded — the channel is alive, so reset the
|
|
* streak (a single later timeout shouldn't immediately re-warn).
|
|
*/
|
|
export function noteSignerDecryptSuccess() {
|
|
consecutiveTimeouts = 0;
|
|
}
|
|
|
|
export function getSignerHealthState() {
|
|
return { consecutiveTimeouts, lastNoticeAt, lastDetail };
|
|
}
|
|
|
|
export const __testExports = {
|
|
CONSECUTIVE_TIMEOUT_THRESHOLD,
|
|
NOTICE_COOLDOWN_MS,
|
|
reset() {
|
|
consecutiveTimeouts = 0;
|
|
lastNoticeAt = 0;
|
|
lastDetail = null;
|
|
},
|
|
};
|