perf(nip07): don't kill slow signers during the permission handshake

On a cold login / permission cache-miss, requestEnablePermissions probes
several permission-payload variants before the no-arg prompt. The specific
(silent) variants were capped at 3s "to fail fast" — but real extensions
REJECT an unsupported payload shape almost immediately (and a fast
rejection already falls through to the next variant), so the 3s cap added
no real safety. What it DID do: kill a slow-but-responsive signer
mid-grant, forcing all 3 specific variants to time out (3s each) before the
prompt variant finally succeeded — ~25s of dead time before signer-ready.

Raise the specific-variant timeout to 20s (SPECIFIC_VARIANT_TIMEOUT_MS).
The bound now only matters for a variant that genuinely HANGS; unsupported
shapes still reject fast, and a slow signer can actually answer the first
supported variant.

Channel-sim at 16s/call: enable extension calls 4 → 1, signer-ready
~42s → ~33s, lists-sync ~58s → ~50s; healthy login unchanged (~1.6s),
all lists still decrypt. Full unit suite green (pre-existing Node
localStorage failures unrelated). KNOWN_BUGS #0.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-06-16 13:04:34 -04:00
1 parent 38c9c52c0a
commit f3bac3066d
1 file changed
+18 -3
+18 -3
View File
@@ -13,6 +13,16 @@ const NIP07_PERMISSIONS_STORAGE_KEY = "bitvid:nip07:permissions";
// still allowing manual overrides via __BITVID_NIP07_ENABLE_VARIANT_TIMEOUT_MS__.
const DEFAULT_ENABLE_VARIANT_TIMEOUT_MS = 45_000;
// Timeout for the SPECIFIC (silent, payload-carrying) permission variants we
// probe before the no-arg prompt. This is NOT a "fail fast" budget: real
// extensions REJECT a payload shape they don't support almost immediately, and
// a fast rejection moves us to the next variant right away. The timeout only
// bounds a variant that HANGS — so a tiny 3s cap added no real safety against
// unsupported variants but DID kill slow-but-responsive signers mid-grant,
// forcing 3 wasted attempts before the prompt variant succeeded (~25s of dead
// time on a 16s/call signer in the channel-sim). Give it real room.
const SPECIFIC_VARIANT_TIMEOUT_MS = 20_000;
export const DEFAULT_NIP07_ENCRYPTION_METHODS = Object.freeze([
// Encryption helpers — request both legacy NIP-04 and modern NIP-44 upfront
"nip04.encrypt",
@@ -569,11 +579,16 @@ export async function requestEnablePermissions(
let lastError = null;
const runPermissionMethod = async (methodName, method) => {
for (const options of permissionVariants) {
// Specific permission payloads should fail fast; prompt-based no-arg calls
// get a longer timeout so users have time to confirm in extension UI.
// Specific (silent) payload variants get a generous bound so a slow signer
// can actually answer the FIRST supported one (unsupported shapes still
// reject fast and fall through immediately). The no-arg prompt variant
// gets the full window so users have time to confirm in the extension UI.
const variantTimeoutOverrides = options
? {
timeoutMs: Math.min(3000, getEnableVariantTimeoutMs()),
timeoutMs: Math.min(
SPECIFIC_VARIANT_TIMEOUT_MS,
getEnableVariantTimeoutMs(),
),
retryMultiplier: 1,
}
: {