Commit Graph
10 Commits
Author SHA1 Message Date
thePR0M3TH3ANandClaude Opus 4.8 362016ead6 [watch-history] thread chunkDecryptLimit through resolve + expose deferred count
Service-layer plumbing for bounded watch-history loading (slice B part 2).
manager.resolve() now forwards chunkDecryptLimit to fetch() and records the
resulting deferred-chunk count in a per-actor side-channel, so resolve() keeps
returning a bare items array (its sole caller depends on that) while the
"more older chunks available" signal is still retrievable. Exposed via
getWatchHistoryDeferredChunkCount() on the manager and the NostrClient facade.
clear() resets the side-channel.

Still inert by default (no caller passes a finite limit yet); this is the
substrate for activating fast-first-render. Tested: resolve under
chunkDecryptLimit:1 returns only the newest chunk's items and reports
deferredChunkCount=1, reset to 0 after clear().

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 14:49:40 -04:00
thePR0M3TH3ANandClaude Opus 4.8 11ff205fc0 [watch-history] add newest-first, budget-capped chunk decryption (foundation)
Foundation for bounded watch-history loading (slice B part 2). A deep
history references many monthly chunks; under a NIP-46 remote signer each
uncached chunk decrypt is a serialized published relay RPC, so decrypting
them all up front blocks the first render and risks the relay rate limit.

manager.fetch now:
- sorts chunk events newest-first by created_at, so the decrypt budget is
  spent on the most recent history;
- accepts a chunkDecryptLimit option that caps how many *uncached*,
  genuinely-encrypted chunks are decrypted per fetch. Cached/plaintext
  chunks are always decrypted (they cost no RPC) and never count against
  the limit. Default is Infinity -> no behavior change for existing
  callers;
- returns deferredChunkCount so a caller can tell more history is
  available on demand (re-fetching with a larger limit reuses the chunk
  cache, so only the newly requested older chunks cost RPCs).

Test: two uncached nip44 chunks (newest + older) with chunkDecryptLimit:1
asserts only the newest is decrypted (1 RPC), deferredChunkCount is 1, and
only the newest chunk's items appear. Mutation-verified against both
removing the cap and removing the newest-first sort.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 14:42:56 -04:00
thePR0M3TH3ANandClaude Opus 4.8 cd614876f5 [watch-history] strictly format-route decrypt to halve NIP-46 RPCs
Watch-history decryption previously ordered the matching cipher family
first but kept the other family as a *fallback*. The opposite family can
never decrypt a given ciphertext (NIP-04 always carries a literal "?iv="
marker; NIP-44 is plain base64), so that fallback was a guaranteed-wasted
decrypt attempt. Under a NIP-46 remote signer every decrypt is a
*published* relay RPC routed through the serial 250ms request queue, so a
transient failure on the correct family triggered a second wasted RPC
that burned the queue and pushed cold loads toward the relay rate limit
("noting too much") — the symptom users hit.

determineWatchHistoryDecryptionOrder now filters the attempt set to the
single family implied by the ciphertext shape (trusting the ciphertext
over a possibly-misleading "encrypted" tag), with a safety fallback to
the full ordered list when nothing matches so the only available
decryptor is never stranded. This mirrors the list-decrypt routing
already shipped for userBlocks / subscriptions / hashtags (slice A).

Test: a NIP-44 ciphertext mislabeled with an ["encrypted","nip04"] tag,
against a signer exposing both decryptors where nip04 returns decoy data.
Asserts nip04 is never attempted and the nip44 plaintext is used.
Mutation-verified: removing the filter fails the test.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 12:55:18 -04:00
thePR0M3TH3AN 00f96bbe0e update 2026-02-21 15:46:35 -05:00
google-labs-jules[bot]andPR0M3TH3AN 82b9c4ae0b fix(tests): update watchHistory mocks and storage tests
- Update mock pool objects in `tests/nostr/watchHistory.test.js` to include `async list() { return []; }` to prevent `TypeError: pool.list is not a function`.
- Update storage pruning tests to use `profileCache` semantics (per-user storage) by setting active profile and using correct storage keys.
- Ensure `profileCache.activePubkey` is set in tests that rely on persistence.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-27 03:32:33 +00:00
google-labs-jules[bot] b059d66d80 Fix watch history mobile layout and sort order
- Updated CSS for `.watch-history-card` to use `flex-col` on mobile for stacked layout, switching to `sm:flex-row` on larger screens.
- Added `w-full` to `.watch-history-card__thumbnail` on mobile to constrain image width.
- Fixed a bug in `js/nostr/watchHistory.js` where `computeWatchHistoryFingerprintForItems` was sorting the live history array in-place by ID, causing the UI to display an incorrect (non-chronological) order. The fix involves creating a shallow copy before sorting.
- Updated `tests/nostr/watchHistory.test.js` to verify behavior against the current storage version (`v5`).
2026-01-17 13:35:37 +00:00
thePR0M3TH3AN 891226697d Simplify watch history pipeline 2026-01-06 18:53:27 -05:00
thePR0M3TH3AN ba666bdaba Refactor watch history payload building 2026-01-03 13:57:46 -05:00
thePR0M3TH3AN 1ff3523bd0 Improve Nostr watch history snapshot caching 2025-10-22 20:13:10 -04:00
thePR0M3TH3AN 5e0a880d09 Add nostr watch history unit tests 2025-10-22 14:37:38 -04:00