Commit Graph
10 Commits
Author SHA1 Message Date
thePR0M3TH3ANandClaude Opus 4.8 29785783fe nostr: fix legacy-zombie resurrection via canonical getActiveKey
client.js carried a stale duplicate of getActiveKey that lacked the
LEGACY: guard added to nostr/utils.js. The tombstone machinery used the
local copy, so a deleted legacy video keyed its tombstone as
ROOT:LEGACY:... while a bare zombie keyed as <pubkey>:<dTag> — the guard
never matched and the video resurrected. Import the single canonical
getActiveKey and drop the duplicate.

Also convert tests/nostr-delete-flow.test.mjs to node:test (it was
silently excluded from the runner and failing), fix its stale write-relay
config, and rewrite its subscription assertions against the real
VideoEventBuffer. New client-level regression test for the guard.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-23 14:53:11 -04:00
thePR0M3TH3ANandClaude Opus 4.8 874897b933 perf(nostr): verify event signatures off the main thread
Profiling the live app showed the single biggest CPU cost was the relay pool
verifying every incoming event's schnorr signature synchronously on the main
thread: ~1.2s of secp256k1 work ([email protected] 855ms) during feed load and tab
switches, dropping to ~16ms when skipped. The pool was constructed as
`new SimplePool()` with no options, so nostr-tools used its default verifying
verifyEvent; the `verifyEvent: () => true` that looked like it disabled this
only existed on a mock tools object and was never wired to the real pool.

Move verification off the main thread instead of dropping it:
- Construct the pool with `verifyEvent: () => true` so it never blocks.
- Add signatureVerifyWorker (+ client) that verifies event batches in a Web
  Worker and returns the valid ids; falls back to main-thread verification only
  when Workers are unavailable (never silently trusts).
- VideoEventBuffer verifies each batch via the worker before committing, and
  drops events that fail (fails closed). The verifier is injectable so tests can
  virtualize the worker; subscribeVideos passes it through and returns the flush
  promise from EOSE so commits are awaitable.

Tests: new signatureVerifyWorkerClient.test.mjs (worker protocol + drop-invalid
+ empty/no-id handling); videoEventBuffer.test.mjs and client.test.mjs adapted
to the async, verified commit path with a passthrough verifier.

Note: tests/nostr-delete-flow.test.mjs has a PRE-EXISTING failure on
`should not trigger subscription callbacks` (fails on clean unstable, and is a
standalone script not run by the unit-test runner); its edits here only adapt it
to the now-async flush.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-12 11:16:25 -04:00
google-labs-jules[bot]andPR0M3TH3AN ac9eab9a10 Refactor deleteAllVersions in NostrClient and fix delete flow test
- Extract logic from `deleteAllVersions` into helper methods: `_hydrateHistoryForDelete`, `_getEventsToDelete`, `_softDeleteVersions`, and `_hardDeleteVersions`.
- Update `_hardDeleteVersions` to use `{ waitForAll: true }` when publishing Kind 5 events, ensuring relay failures are correctly reported.
- Fix `tests/nostr-delete-flow.test.mjs` by explicitly registering the active signer in the test environment.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-10 01:25:41 +00:00
google-labs-jules[bot]andPR0M3TH3AN 1e53070717 perf: batch video updates in subscribeVideos to reduce UI thrashing
Updates `NostrClient.subscribeVideos` to buffer incoming events and invoke the `onVideo` callback once per flush cycle with an array of updates, instead of once per video. This significantly reduces redundant sorting, filtering, and persistence operations in `NostrService`.

Also optimizes `populateNip71MetadataForVideos` to run as a single batched request per flush cycle.

BREAKING CHANGE: `subscribeVideos` callback now receives `Video[]` instead of `Video`. All internal consumers have been updated.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-02 17:04:55 +00:00
google-labs-jules[bot]andPR0M3TH3AN c82ab2d490 Optimize EventsCacheStore persistence with dirty state tracking
Implemented `dirtyEventIds` and `dirtyTombstones` in `NostrClient` to track only modified items.
Updated `EventsCacheStore.persistSnapshot` to accept these dirty sets and iterate only over changed items, skipping the O(N) serialization loop for unchanged data.
Added heuristic to skip deletion scan if the dataset size has not decreased.
Optimized `NostrClient` methods (`flushEventBuffer`, `deleteAllVersions`, `fetchVideos`, etc.) to flag modified events.
Updated `nostr-delete-flow.test.mjs` to use valid hex IDs for NIP-compliant testing.

Benchmark results (5000 items, single update):
- Before: ~19ms (O(N))
- After: ~2ms (O(1))

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-01 16:50:28 +00:00
google-labs-jules[bot] 38f1594243 chore(ai): doc js/nostr/client.js (agent)
- Added JSDoc comments to `NostrClient` class and methods.
- Added JSDoc comments to `EventsCacheStore`.
- Created `docs/nostr-client-overview.md` with high-level documentation.
- Fixed a race condition in `tests/nostr-delete-flow.test.mjs`.
2026-01-19 15:18:36 +00:00
thePR0M3TH3AN 3996986e63 Remove nostr shim and retarget imports 2026-01-06 15:32:21 -05:00
thePR0M3TH3AN e226446e8f Add structured delete summaries and relay failure reporting 2025-10-20 11:21:45 -04:00
thePR0M3TH3AN 9de3be34bc Add tombstone guards to nostr video cache 2025-10-20 10:25:50 -04:00
thePR0M3TH3AN cc3ef2fb1f Ensure delete tombstones carry explicit flag 2025-10-20 09:54:07 -04:00